[jboss-svn-commits] JBL Code SVN: r33056 - in labs/jbosstm/trunk: ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean and 18 other directories.

jboss-svn-commits at lists.jboss.org jboss-svn-commits at lists.jboss.org
Mon May 24 14:34:17 EDT 2010


Author: mmusgrov
Date: 2010-05-24 14:34:15 -0400 (Mon, 24 May 2010)
New Revision: 33056

Added:
   labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/ActionBean.java
   labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/ActionBeanMBean.java
   labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/ActionBeanWrapperInterface.java
   labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/LogRecordWrapper.java
   labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/LogRecordWrapperMBean.java
   labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/OSEntryBean.java
   labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/OSEntryBeanMBean.java
   labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/ObjStoreBrowser.java
   labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/ObjStoreBrowserMBean.java
   labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/ObjStoreItemMBean.java
   labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/ParticipantStatus.java
   labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/StateManagerWrapper.java
   labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/UidWrapper.java
   labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/util/JMXServer.java
   labs/jbosstm/trunk/ArjunaCore/arjuna/tests/classes/com/hp/mwtests/ts/arjuna/tools/ObjStoreBrowserTest.java
   labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/tools/
   labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/tools/osb/
   labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/tools/osb/mbean/
   labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/tools/osb/mbean/jta/
   labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/tools/osb/mbean/jta/JTAActionBean.java
   labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/tools/osb/mbean/jta/XAResourceMBean.java
   labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/tools/osb/mbean/jta/XAResourceRecordBean.java
   labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/tools/osb/mbean/jta/XAResourceRecordBeanMBean.java
   labs/jbosstm/trunk/ArjunaJTA/jta/tests/classes/com/hp/mwtests/ts/jta/tools/
   labs/jbosstm/trunk/ArjunaJTA/jta/tests/classes/com/hp/mwtests/ts/jta/tools/ObjStoreBrowserTest.java
   labs/jbosstm/trunk/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/tools/
   labs/jbosstm/trunk/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/tools/osb/
   labs/jbosstm/trunk/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/tools/osb/mbean/
   labs/jbosstm/trunk/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/tools/osb/mbean/jts/
   labs/jbosstm/trunk/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/tools/osb/mbean/jts/ArjunaTransactionImpleWrapper.java
   labs/jbosstm/trunk/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/tools/osb/mbean/jts/ToolsInitialiser.java
   labs/jbosstm/trunk/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/tools/osb/mbean/jts/XAResourceRecordBean.java
   labs/jbosstm/trunk/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/tools/osb/mbean/jts/XAResourceRecordBeanMBean.java
   labs/jbosstm/trunk/ArjunaJTS/jtax/tests/classes/com/hp/mwtests/ts/jta/jts/common/ExtendedCrashRecord.java
   labs/jbosstm/trunk/ArjunaJTS/jtax/tests/classes/com/hp/mwtests/ts/jta/jts/tools/
   labs/jbosstm/trunk/ArjunaJTS/jtax/tests/classes/com/hp/mwtests/ts/jta/jts/tools/JTSObjStoreBrowserTest.java
Removed:
   labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/BasicActionBean.java
   labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/BasicActionBeanMBean.java
   labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/ObjStoreBean.java
   labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/ObjStoreEntryBean.java
   labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/ObjStoreTypeBean.java
   labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/common/
   labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/util/ActionWrapper.java
   labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/util/JMXServer.java
Modified:
   labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/common/ObjectStoreEnvironmentBean.java
   labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/common/ObjectStoreEnvironmentBeanMBean.java
   labs/jbosstm/trunk/atsintegration/transaction-jboss-beans.xml
   labs/jbosstm/trunk/atsintegration/transaction-jboss-beans.xml.jts
Log:
[JBTM-716] Add tests for ObjectStore MBeans. [JBTM-719] New MBeans to facilitate RHQ plugin

Modified: labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/common/ObjectStoreEnvironmentBean.java
===================================================================
--- labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/common/ObjectStoreEnvironmentBean.java	2010-05-24 18:25:49 UTC (rev 33055)
+++ labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/common/ObjectStoreEnvironmentBean.java	2010-05-24 18:34:15 UTC (rev 33056)
@@ -20,7 +20,6 @@
  */
 package com.arjuna.ats.arjuna.common;
 
-import com.arjuna.ats.arjuna.objectstore.ObjectStore;
 import com.arjuna.ats.arjuna.objectstore.StateType;
 import com.arjuna.ats.internal.arjuna.objectstore.HashedStore;
 import com.arjuna.ats.internal.arjuna.objectstore.ShadowNoFileLockStore;
@@ -73,10 +72,7 @@
     private volatile long txLogSize = 10 * 1024 * 1024;  // default maximum log txLogSize in bytes;
     @FullPropertyName(name = "com.arjuna.ats.arjuna.coordinator.transactionLog.purgeTime")
     private volatile long purgeTime = 100000; // in milliseconds
-    @FullPropertyName(name = "org.jboss.jbosstm.tools.jmx.osb.JMXEnabled")
-    private volatile boolean jmxEnabled = true;
 
-
     /**
      * Returns the maximum allowed size, in bytes, of the cache store's in-memory cache.
      *
@@ -616,24 +612,4 @@
     {
         this.purgeTime = purgeTime;
     }
-
-    /**
-     * Determines whether JMX instrumentation of the Object Store is enabled.
-     *
-     * @return true if JMX instrumentation is enabled
-     */
-    public boolean isJmxEnabled()
-	{
-		return jmxEnabled;
-	}
-
-    /**
-     * Enable or disable JMX instrumentation of the Object Store.
-     *
-     * @param enable set to true to enable.
-     */
-    public void setJmxEnabled(boolean enable)
-	{
-		jmxEnabled = enable;
-	}
 }

Modified: labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/common/ObjectStoreEnvironmentBeanMBean.java
===================================================================
--- labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/common/ObjectStoreEnvironmentBeanMBean.java	2010-05-24 18:25:49 UTC (rev 33055)
+++ labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/common/ObjectStoreEnvironmentBeanMBean.java	2010-05-24 18:34:15 UTC (rev 33056)
@@ -118,9 +118,4 @@
     long getPurgeTime();
 
     void setPurgeTime(long purgeTime);
-
-    boolean isJmxEnabled();
-
-    void setJmxEnabled(boolean enable);
-
 }

Added: labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/ActionBean.java
===================================================================
--- labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/ActionBean.java	                        (rev 0)
+++ labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/ActionBean.java	2010-05-24 18:34:15 UTC (rev 33056)
@@ -0,0 +1,315 @@
+package com.arjuna.ats.arjuna.tools.osb.mbean;
+
+import com.arjuna.ats.arjuna.coordinator.TwoPhaseOutcome;
+import com.arjuna.ats.arjuna.logging.tsLogger;
+import com.arjuna.ats.arjuna.AtomicAction;
+import com.arjuna.ats.arjuna.common.Uid;
+import com.arjuna.ats.arjuna.coordinator.AbstractRecord;
+import com.arjuna.ats.arjuna.coordinator.RecordList;
+import com.arjuna.ats.arjuna.coordinator.TxControl;
+import com.arjuna.ats.arjuna.exceptions.ObjectStoreException;
+import com.arjuna.ats.arjuna.tools.osb.util.JMXServer;
+
+import java.lang.reflect.Constructor;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * MBean implementation of an ObjectStore entry that represents an AtomicAction
+ *
+ * @message com.arjuna.ats.arjuna.tools.osb.mbean.m_1
+ *		  [com.arjuna.ats.arjuna.tools.osb.mbean.m_1] - remove committed failed.
+ * @message com.arjuna.ats.arjuna.tools.osb.mbean.m_2
+ *		  [com.arjuna.ats.arjuna.tools.osb.mbean.m_2] - remove ok.
+ * @message com.arjuna.ats.arjuna.tools.osb.mbean.m_3
+ *		  [com.arjuna.ats.arjuna.tools.osb.mbean.m_3] - remove committed exception: {0}.
+ */
+public class ActionBean extends OSEntryBean implements ActionBeanMBean {
+    // Basic properties this enty
+	private StateManagerWrapper sminfo;
+    // collection of participants belonging to this BasicAction
+	private Collection<LogRecordWrapper> participants = new ArrayList<LogRecordWrapper>();
+    // wrapper around the real AtomicAction
+	private ActionBeanWrapperInterface ra;
+
+	public ActionBean(UidWrapper w) {
+		super(w);
+
+		boolean isJTS = JMXServer.isJTS() && w.getType().endsWith("ArjunaTransactionImple");
+        // Participants in a JTS transaction are represented by entries in the ObjectStore
+		List<UidWrapper> recuids = null;
+
+		if (isJTS) {
+			try {
+				Class<ActionBeanWrapperInterface> cl = (Class<ActionBeanWrapperInterface>) Class.forName(JMXServer.AJT_WRAPPER_TYPE);
+				Constructor<ActionBeanWrapperInterface> constructor = cl.getConstructor(ActionBean.class, UidWrapper.class);
+				ra = constructor.newInstance(this, w);
+			} catch (Exception e) { // ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException
+				if (tsLogger.arjLoggerI18N.isDebugEnabled())
+					tsLogger.arjLoggerI18N.debug("Error constructing " + JMXServer.AJT_WRAPPER_TYPE + ": " + e);
+				ra = new AtomicActionWrapper(w);
+			}
+		} else {
+			ra = new AtomicActionWrapper(w);
+		}
+
+		ra.activate();
+		sminfo = new StateManagerWrapper(TxControl.getStore(), getUid(), getType());
+
+		if (isJTS) {
+            /*
+             * for JTS actions the participants will have entries in the ObjectStore.
+             * these entries will be associated with the current MBean (refer to
+             * the method findParticipants below for details)
+             */
+			recuids = w.probe(JMXServer.AJT_RECORD_TYPE, JMXServer.AJT_XAREC_TYPE);
+        }
+
+		for (ParticipantStatus lt : ParticipantStatus.values()) {
+			findParticipants(recuids, ra.getRecords(lt), lt);
+		}
+	}
+
+	public StringBuilder toString(String prefix, StringBuilder sb) {
+		ra.toString(prefix, sb);
+		prefix += '\t';
+		sb.append('\n').append(prefix).append(sminfo.getCreationTime());
+		sb.append('\n').append(prefix).append(sminfo.getAgeInSeconds());
+
+		for (LogRecordWrapper p : participants) {
+			p.toString(prefix, sb);
+		}
+
+		return sb;
+	}
+
+    /**
+     * return the Uid for given AbstractRecord
+     * @param rec the record whose Uid is required
+     * @return  the Uid of the requested record
+     */
+	public Uid getUid(AbstractRecord rec) {
+		return ra.getUid(rec);
+	}
+
+    /**
+     * Remove this AtomicAction from the ObjectStore
+     * @return a textual indication of whether the remove operation succeeded
+     */
+	public String remove() {
+		try {
+			if (!TxControl.getStore().remove_committed(getUid(), getType()))
+				return "remove committed failed"; // TODO com.arjuna.ats.arjuna.tools.osb.mbean.m_1
+			else
+				w.probe();
+
+			return "remove ok"; // TODO com.arjuna.ats.arjuna.tools.osb.mbean.m_2
+		} catch (ObjectStoreException e) {
+			return "remove committed exception: " + e.getMessage(); // TODO com.arjuna.ats.arjuna.tools.osb.mbean.m_3
+		}
+	}
+
+    /**
+     * create MBean representations of the participants of this transaction
+     * @param recuids some transaction participants are represented in the ObjectStore
+     * - if this is the case then recuids contains a list of MBean wrappers representing them.
+     * Otherwise this list will be empty.
+     * @param list the records representing the participants
+     * @param listType indicates the type of the records in list (PREPARED, PENDING, FAILED, READONLY, HEURISTIC)
+     */
+	private void findParticipants(List<UidWrapper> recuids, RecordList list, ParticipantStatus listType) {
+		if (list != null) {
+			for (AbstractRecord rec = list.peekFront(); rec != null; rec = list.peekNext(rec)) {
+				LogRecordWrapper lw;
+				int i = recuids == null ? -1 : recuids.indexOf(new UidWrapper(ra.getUid(rec)));
+
+				if (i != -1) {
+					OSEntryBean p = recuids.get(i).getMBean();
+
+					if (p instanceof LogRecordWrapper) {
+						lw = (LogRecordWrapper) p;
+						lw.init(this, rec, listType);
+					} else {
+						if (tsLogger.arjLoggerI18N.isDebugEnabled())
+							tsLogger.arjLoggerI18N.debug("participant record is not a LogRecordWrapper");
+						lw = createParticipant(rec, listType);
+						lw.activate();
+					}
+				} else {
+					lw = createParticipant(rec, listType);
+					lw.activate();
+				}
+
+				participants.add(lw);
+			}
+		}
+	}
+
+    /**
+     * Extension point for other Bean implementations to provide an implementation bean for its participants.
+     * For example @see com.arjuna.ats.internal.jta.tools.osb.mbean.jta.JTAActionBean
+     * @param rec the record that should be represented by an MBean
+     * @param listType the status of the record
+     * @return the MBean implementation of the participant
+     */
+	protected LogRecordWrapper createParticipant(AbstractRecord rec, ParticipantStatus listType) {
+		return new LogRecordWrapper(this, rec, listType);
+	}
+
+    /**
+     * See if there is participant Bean corresponding to the given record
+     * @param rec the record for the target participant
+     * @return the bean corresponding to the requested record
+     */
+	public LogRecordWrapper getParticipant(AbstractRecord rec) {
+		for (LogRecordWrapper w : participants)
+			if (w.getRecord().equals(rec))
+				return w;
+
+		return null;
+	}
+
+    /**
+     * register this bean (and its participants) with the MBeanServer
+     */
+	public void register() {
+		super.register();
+
+		for (LogRecordWrapper p : participants)
+			JMXServer.getAgent().registerMBean(p.getName(), p);
+	}
+
+    /**
+     * unregister this bean (and its participants) with the MBeanServer
+     */
+	public void unregister() {
+		for (LogRecordWrapper p : participants)
+			JMXServer.getAgent().unregisterMBean(p.getName());
+
+		super.unregister();
+	}
+
+	public long getAgeInSeconds() {
+		return sminfo.getAgeInSeconds();
+	}
+
+	public String getCreationTime() {
+		return sminfo.getCreationTime();
+	}
+
+	public boolean isParticipant() {
+		return false;
+	}
+
+    /**
+     * Request a change in status of a participant. For example if a record has a
+     * heuristic status then this method could be used to move it back into the
+     * prepared state so that the recovery system can replay phase 2 of the
+     * committment protocol
+     * @param logrec the record whose status is to be changed
+     * @param newStatus the desired status
+     * @return true if the status was changed
+     */
+	public boolean setStatus(LogRecordWrapper logrec, ParticipantStatus newStatus) {
+		ParticipantStatus lt = logrec.getListType();
+		AbstractRecord targRecord = logrec.getRecord();
+
+		RecordList oldList = ra.getRecords(lt);
+		RecordList newList = ra.getRecords(newStatus);
+
+        if (lt.equals(ParticipantStatus.HEURISTIC) && !targRecord.forgetHeuristic()) {
+            return false;
+        }
+
+		// move the record from currList to targList
+		if (oldList.remove(targRecord)) {
+            
+			if (newList.insert(targRecord)) {
+				if (lt.equals(ParticipantStatus.HEURISTIC)) {
+                    switch (newStatus) {
+                        case FAILED:
+                            ra.clearHeuristicDecision(TwoPhaseOutcome.FINISH_ERROR);
+                            break;
+                        case PENDING:
+                            ra.clearHeuristicDecision(TwoPhaseOutcome.NOT_PREPARED);
+                            break;
+                        case PREPARED:
+                            ra.clearHeuristicDecision(TwoPhaseOutcome.PREPARE_OK);
+                            break;
+                        case READONLY:
+                            ra.clearHeuristicDecision(TwoPhaseOutcome.PREPARE_READONLY);
+                            break;
+                        default:
+                            break;
+                    }
+                }
+
+				ra.doUpdateState();
+                
+				return true;
+			}
+		}
+
+		return false;
+	}
+
+    /**
+     *
+     * @return the MBeans corresponding to the participants within this action
+     */
+    public Collection<LogRecordWrapper> getParticipants() {
+        return Collections.unmodifiableCollection(participants);
+    }
+
+    /**
+     * The ActionBean needs access to the participant lists maintained by an AtomicAction but these
+     * lists are protected. Therefore define a simple extension class to get at these records:
+     */
+    class AtomicActionWrapper extends AtomicAction implements ActionBeanWrapperInterface {
+		boolean activated;
+
+		public AtomicActionWrapper(UidWrapper w) {
+			super(w.getUid());
+		}
+
+		public boolean activate() {
+			if (!activated)
+				activated = super.activate();
+
+			return activated;
+		}
+
+		public void doUpdateState() {
+			updateState();
+		}
+
+		public Uid getUid(AbstractRecord rec) {
+			return get_uid();
+		}
+		
+		public StringBuilder toString(String prefix, StringBuilder sb) {
+			prefix += '\t';
+			return sb.append('\n').append(prefix).append(get_uid());
+		}
+
+        public void clearHeuristicDecision(int newDecision) {
+            if (super.heuristicList.size() == 0)
+                setHeuristicDecision(newDecision);
+        }
+
+        public RecordList getRecords(ParticipantStatus type) {
+			switch (type) {
+				default:
+				case PREPARED: return preparedList;
+				case FAILED: return failedList;
+				case HEURISTIC: return heuristicList;
+				case PENDING: return pendingList;
+				case READONLY: return readonlyList;
+			}
+		}
+	}
+
+}

Added: labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/ActionBeanMBean.java
===================================================================
--- labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/ActionBeanMBean.java	                        (rev 0)
+++ labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/ActionBeanMBean.java	2010-05-24 18:34:15 UTC (rev 33056)
@@ -0,0 +1,15 @@
+package com.arjuna.ats.arjuna.tools.osb.mbean;
+
+import com.arjuna.ats.arjuna.tools.osb.annotation.MXBeanDescription;
+import com.arjuna.ats.arjuna.tools.osb.annotation.MXBeanPropertyDescription;
+
+ at MXBeanDescription("Management view of a transaction")
+public interface ActionBeanMBean extends OSEntryBeanMBean {
+	long getAgeInSeconds();
+	String getCreationTime();
+	@MXBeanPropertyDescription("Indicates whether this entry corresponds to a transaction participant")
+	boolean isParticipant();
+
+	@MXBeanPropertyDescription("Tell the Transaction Manager to remove this action")
+	String remove();
+}

Added: labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/ActionBeanWrapperInterface.java
===================================================================
--- labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/ActionBeanWrapperInterface.java	                        (rev 0)
+++ labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/ActionBeanWrapperInterface.java	2010-05-24 18:34:15 UTC (rev 33056)
@@ -0,0 +1,19 @@
+package com.arjuna.ats.arjuna.tools.osb.mbean;
+
+import com.arjuna.ats.arjuna.common.Uid;
+import com.arjuna.ats.arjuna.coordinator.AbstractRecord;
+import com.arjuna.ats.arjuna.coordinator.RecordList;
+
+/**
+ * common interface for JTA and JTS transactions
+ */
+public interface ActionBeanWrapperInterface {
+	RecordList getRecords(ParticipantStatus type);
+	boolean activate();
+	void doUpdateState();
+	Uid get_uid();
+	Uid getUid(AbstractRecord rec);
+	StringBuilder toString(String prefix, StringBuilder sb);
+
+    void clearHeuristicDecision(int newDecision);
+}
\ No newline at end of file

Deleted: labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/BasicActionBean.java
===================================================================
--- labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/BasicActionBean.java	2010-05-24 18:25:49 UTC (rev 33055)
+++ labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/BasicActionBean.java	2010-05-24 18:34:15 UTC (rev 33056)
@@ -1,218 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags.
- * See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- * This copyrighted material is made available to anyone wishing to use,
- * modify, copy, or redistribute it subject to the terms and conditions
- * of the GNU Lesser General Public License, v. 2.1.
- * This program is distributed in the hope that it will be useful, but WITHOUT A
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
- * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
- * You should have received a copy of the GNU Lesser General Public License,
- * v.2.1 along with this distribution; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA  02110-1301, USA.
- *
- * (C) 2009
- * @author Red Hat Middleware LLC.
- */
-package com.arjuna.ats.arjuna.tools.osb.mbean;
-
-import com.arjuna.ats.arjuna.coordinator.RecordList;
-import com.arjuna.ats.arjuna.coordinator.AbstractRecord;
-import com.arjuna.ats.arjuna.common.Uid;
-import com.arjuna.ats.arjuna.exceptions.ObjectStoreException;
-import com.arjuna.ats.arjuna.tools.osb.mbean.common.LogRecordListBean;
-import com.arjuna.ats.arjuna.tools.osb.mbean.common.LogRecordBean;
-import com.arjuna.ats.arjuna.tools.osb.util.ActionWrapper;
-
-import javax.management.ObjectInstance;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Collection;
-import java.util.Iterator;
-
-/**
- * @see BasicActionBeanMBean
- */
-public class BasicActionBean extends ObjStoreEntryBean implements BasicActionBeanMBean
-{
-    protected ActionWrapper action_;
-    protected Map<String, LogRecordListBean> lists = new HashMap<String, LogRecordListBean>();
-    private boolean activated;
-
-    public BasicActionBean(ObjStoreTypeBean parent, Uid uid)
-    {
-        super(parent, uid);
-    }
-
-    public ObjectInstance register()
-    {
-        if (activated)
-            remove();
-
-        if (action_ == null)
-            action_ = new BasicActionWrapper(uid);
-
-        try {
-            action_.getAction().activate();
-        } catch (Exception e) {
-            addError(e.getMessage());
-        }
-
-        action_.populateLists(lists, this);
-
-        for (LogRecordListBean listBean : lists.values())
-            listBean.register();
-
-        activated = true;
-
-        return super.register();
-    }
-
-    public void remove()
-    {
-
-        if (action_ == null)
-            return;
-
-        action_.getAction().deactivate();
-        activated = false;
-
-        try {
-            action_.remove();
-        } catch (ObjectStoreException e) {
-            throw new RuntimeException(e);
-        }
-
-        action_ = null;
-
-        // record successfuly remove the mbean
-        unregister();
-    }
-
-    public int getFailedCount()
-    {
-        return getListSize("Failed");
-    }
-    public int getHeuristicCount()
-    {
-        return getListSize("Heuristic");
-    }
-    public int getPendingCount()
-    {
-        return getListSize("Pending");
-    }
-    public int getPreparedCount()
-    {
-        return getListSize("Prepared");
-    }
-    public int getReadOnlyCount()
-    {
-        return getListSize("ReadOnly");
-    }
-
-    private int getListSize(String type) {
-        LogRecordListBean lb = lists.get(type);
-
-        return (lb == null ? 0 : lb.getSize());
-    }
-
-    public String[] getFailedList()
-    {
-        return toStringArray(lists.get("Failed"));
-    }
-
-    public String[] getHeuristicList()
-    {
-        return toStringArray(lists.get("Heuristic"));
-    }
-
-    public String[] getPendingList()
-    {
-        return toStringArray(lists.get("Pending"));
-    }
-
-    public String[] getPreparedList()
-    {
-        return toStringArray(lists.get("Prepared"));
-    }
-
-    public String[] getReadOnlyList()
-    {
-        return toStringArray(lists.get("Readonly"));
-    }
-
-    public static String[] toStringArray(LogRecordListBean listBean)
-    {
-        Collection<LogRecordBean> beans = listBean.getRegisteredMBeans();
-
-        if (beans != null) {
-            String[] res = new String[beans.size()];
-            int i = 0;
-
-            for (LogRecordBean bean : beans)
-                res[i++] = bean.getObjectName();
-
-            return res;
-        }
-
-        return new String[0];
-    }
-
-    public static String[] toStringArray(RecordList rl)
-    {
-        String[] res = new String[rl.size()];
-        AbstractRecord rec = rl.peekFront();
-        int i = 0;
-
-        while (rec != null)
-        {
-            res[i++] = rec.getTypeOfObject();
-            rec = rl.peekNext(rec);
-        }
-
-        return res;
-    }
-
-    public boolean unregister()
-    {
-        for (Iterator<Map.Entry<String, LogRecordListBean>> i = lists.entrySet().iterator(); i.hasNext();)
-        {
-            Map.Entry<String, LogRecordListBean> entry = i.next();
-            if (entry.getValue().unregister())
-                i.remove();
-        }
-
-        return (lists.size() == 0 && super.unregister());
-    }
-
-    public class BasicActionWrapper extends com.arjuna.ats.arjuna.coordinator.BasicAction implements ActionWrapper
-    {
-        public BasicActionWrapper (Uid objUid)
-        {
-            super(objUid);
-        }
-
-        public com.arjuna.ats.arjuna.coordinator.BasicAction getAction() {
-            return this;
-        }
-
-        public void populateLists(Map<String, LogRecordListBean> lists, BasicActionBean bean)
-        {
-            lists.put("Heuristic", new LogRecordListBean(bean, heuristicList, "Heuristic List"));
-            lists.put("Failed", new LogRecordListBean(bean, failedList, "Failed List"));
-            lists.put("Readonly", new LogRecordListBean(bean, readonlyList, "Readonly List"));
-            lists.put("Pending", new LogRecordListBean(bean, pendingList, "Pending List"));
-            lists.put("Prepared", new LogRecordListBean(bean, preparedList, "Prepared List"));
-        }
-
-        public void remove() throws ObjectStoreException
-        {
-            if (!getStore().remove_committed(getSavingUid(), type()))
-                throw new ObjectStoreException();
-        }
-    }
-}

Deleted: labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/BasicActionBeanMBean.java
===================================================================
--- labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/BasicActionBeanMBean.java	2010-05-24 18:25:49 UTC (rev 33055)
+++ labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/BasicActionBeanMBean.java	2010-05-24 18:34:15 UTC (rev 33056)
@@ -1,62 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags.
- * See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- * This copyrighted material is made available to anyone wishing to use,
- * modify, copy, or redistribute it subject to the terms and conditions
- * of the GNU Lesser General Public License, v. 2.1.
- * This program is distributed in the hope that it will be useful, but WITHOUT A
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
- * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
- * You should have received a copy of the GNU Lesser General Public License,
- * v.2.1 along with this distribution; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA  02110-1301, USA.
- *
- * (C) 2009
- * @author Red Hat Middleware LLC.
- */
-package com.arjuna.ats.arjuna.tools.osb.mbean;
-
-import com.arjuna.ats.arjuna.tools.osb.annotation.MXBeanDescription;
-import com.arjuna.ats.arjuna.tools.osb.annotation.MXBeanPropertyDescription;
-import com.arjuna.ats.arjuna.tools.osb.mbean.common.StateBeanMBean;
-
-/**
- * MBean representation of an ObjectStore BasicAction providing a summary of the number
- * of records in each of the various lists
- *
- * @see com.arjuna.ats.arjuna.coordinator.BasicAction
- */
-
- at MXBeanDescription("A representation of the state of each participant involved in an action")
-public interface BasicActionBeanMBean extends StateBeanMBean
-{
-//	@MXBeanPropertyDescription("Permanently remove this mxbean")
-//    public void remove();
-/*  TODO array types don't seem to work with the JMX agent inside the JBoss AS
-    @MXBeanPropertyDescription("Participants that failed during phase 2 (of a two phase commit protocol)")
-    String[] getFailedList();
-    @MXBeanPropertyDescription("Particpants that returned a heuristic out come during phase 2 (of a two phase commit protocol)")
-    String[] getHeuristicList();
-    @MXBeanPropertyDescription("Participants that have not had phase 1 (of a two phase commit protocol) called on them")
-    String[] getPendingList();
-    @MXBeanPropertyDescription("Particpants that have successfully completed phase 1 (of a two phase commit protocol)")
-    String[] getPreparedList();
-    @MXBeanPropertyDescription("Particpants that indicated no chages were made when asked to complete phase 1 (of a two phase commit protocol)")
-    String[] getReadOnlyList();
-*/
-
-    @MXBeanPropertyDescription("Number of participants that failed during phase 2 (of a two phase commit protocol)")    
-    int getFailedCount();
-    @MXBeanPropertyDescription("Number of particpants that returned a heuristic out come during phase 2 (of a two phase commit protocol)")
-    int getHeuristicCount();
-    @MXBeanPropertyDescription("Number of particpants that have successfully completed phase 1 (of a two phase commit protocol)")
-    int getPendingCount();
-    @MXBeanPropertyDescription("Number of particpants that indicated no chages were made when asked to complete phase 1 (of a two phase commit protocol)")
-    int getPreparedCount();
-    @MXBeanPropertyDescription("Number of particpants that indicated no chages were made when asked to complete phase 1 (of a two phase commit protocol)")
-    int getReadOnlyCount();
-}

Added: labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/LogRecordWrapper.java
===================================================================
--- labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/LogRecordWrapper.java	                        (rev 0)
+++ labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/LogRecordWrapper.java	2010-05-24 18:34:15 UTC (rev 33056)
@@ -0,0 +1,124 @@
+package com.arjuna.ats.arjuna.tools.osb.mbean;
+
+import com.arjuna.ats.arjuna.common.Uid;
+import com.arjuna.ats.arjuna.coordinator.AbstractRecord;
+
+/**
+ * An MBean implementation for representing a participant in an Atomic Action or transaction
+ */
+public class LogRecordWrapper extends OSEntryBean implements LogRecordWrapperMBean {
+	protected ActionBean parent;
+	protected AbstractRecord rec;
+	protected boolean activated;
+	protected ParticipantStatus listType;
+	protected String objName;
+
+	public LogRecordWrapper(Uid uid) {
+		objName = "type=unitialised,puid=" + uid.fileStringForm();
+	}
+
+	public LogRecordWrapper(ActionBean parent, AbstractRecord rec, ParticipantStatus listType) {
+		init(parent,  rec, listType);
+	}
+
+	public void init(ActionBean parent, AbstractRecord rec, ParticipantStatus listType) {
+		this.parent = parent;
+		this.rec = rec;
+		this.listType = listType;
+		objName = parent.getName() + ",puid=" + rec.order().fileStringForm();
+	}
+
+	public String getName() {
+		return objName;
+	}
+
+	public boolean isParticipant() {
+		return true;
+	}
+
+	public String getStatus() {
+		return listType.toString();
+	}
+
+	public void setStatus(String newState) {
+		doSetStatus(newState);
+	}
+
+    public String clearHeuristic() {
+        return doSetStatus("PREPARED");
+    }
+
+	public String doSetStatus(String newState) {
+		try {
+			return setStatus(Enum.valueOf(ParticipantStatus.class, newState.toUpperCase()));
+		} catch (IllegalArgumentException e) {
+			StringBuilder sb = new StringBuilder("Valid status values are: ");
+
+			for (ParticipantStatus lt : ParticipantStatus.values()) {
+				sb.append(lt.name()).append(", ");
+			}
+
+			sb.append(" and only HEURISTIC and PREPARED will persist after JVM restart.");
+
+			return sb.toString();
+		}
+	}
+
+	public String setStatus(ParticipantStatus newState) {
+		if (parent != null && parent.setStatus(this, newState)) {
+			listType = newState;
+			return "status change was successful";
+		} else {
+			return "failed";
+		}
+	}
+
+	public String getType() {
+		return rec == null ? "uninitialised" : rec.type();
+	}
+
+	public AbstractRecord getRecord() {
+		return rec;
+	}
+
+	public ParticipantStatus getListType() {
+		return listType;
+	}
+
+	public boolean activate() {
+		if (!activated && rec != null)
+			activated = rec.activate();
+
+		return activated;
+	}
+
+	public StringBuilder toString(String prefix, StringBuilder sb) {
+		prefix += "\t";
+		if (parent != null && rec != null) {
+			sb.append('\n').append(prefix).append(parent.getUid(rec));
+			sb.append('\n').append(prefix).append(listType.toString());
+			sb.append('\n').append(prefix).append(rec.type());
+			sb.append('\n').append(prefix).append(parent.getCreationTime());
+			sb.append('\n').append(prefix).append(parent.getAgeInSeconds());
+		} else {
+			sb.append('\n').append(prefix).append(objName);
+		}
+
+		return sb;
+	}
+
+	public String callMethod(Object object, String mName)
+	{
+		try {
+			return (String) object.getClass().getMethod(mName).invoke(object);
+		} catch (NoSuchMethodException e) {
+			return "Not supported";
+		} catch (Exception e) {
+			return "Error: " + e.getMessage();
+		}
+	}
+
+	public boolean isHeuristic() {
+		return listType.equals(ParticipantStatus.HEURISTIC);
+	}
+}

Added: labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/LogRecordWrapperMBean.java
===================================================================
--- labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/LogRecordWrapperMBean.java	                        (rev 0)
+++ labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/LogRecordWrapperMBean.java	2010-05-24 18:34:15 UTC (rev 33056)
@@ -0,0 +1,22 @@
+package com.arjuna.ats.arjuna.tools.osb.mbean;
+
+import com.arjuna.ats.arjuna.tools.osb.annotation.MXBeanDescription;
+import com.arjuna.ats.arjuna.tools.osb.annotation.MXBeanPropertyDescription;
+
+ at MXBeanDescription("Representation of a transaction participant")
+public interface LogRecordWrapperMBean extends OSEntryBeanMBean {
+	@MXBeanPropertyDescription("Indication of the status of this transaction participant (prepared, heuristic, etc)")
+	String getStatus();
+
+	//@MXBeanPropertyDescription("Change the status of this participant back to prepared or to a heuristic")
+	void setStatus(String newState);
+
+    @MXBeanPropertyDescription("Clear any heuristics so that the recovery system will replay the commit")
+    String clearHeuristic();
+    
+	@MXBeanPropertyDescription("The internal type of this transaction participant")
+	String getType();
+
+	@MXBeanPropertyDescription("This entry corresponds to a transaction participant")
+	boolean isParticipant();
+}

Added: labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/OSEntryBean.java
===================================================================
--- labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/OSEntryBean.java	                        (rev 0)
+++ labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/OSEntryBean.java	2010-05-24 18:34:15 UTC (rev 33056)
@@ -0,0 +1,74 @@
+package com.arjuna.ats.arjuna.tools.osb.mbean;
+
+import com.arjuna.ats.arjuna.logging.tsLogger;
+import com.arjuna.ats.arjuna.common.Uid;
+import com.arjuna.ats.arjuna.coordinator.AbstractRecord;
+import com.arjuna.ats.arjuna.tools.osb.util.JMXServer;
+
+/**
+ * Superclass for MBean implementations representing ObjectStore entries
+ */
+public class OSEntryBean implements OSEntryBeanMBean {	
+	protected UidWrapper w;
+
+	public OSEntryBean() {
+		this.w = new UidWrapper(Uid.nullUid());
+	}
+
+	public OSEntryBean(UidWrapper w) {
+		this.w = w;
+	}
+
+	public void register(String name) {
+		if (tsLogger.arjLoggerI18N.isDebugEnabled())
+			tsLogger.arjLoggerI18N.debug("Registering: " + name);
+		JMXServer.getAgent().registerMBean(name, this);
+	}
+
+	public void unregister(String name) {
+		if (tsLogger.arjLoggerI18N.isDebugEnabled())
+			tsLogger.arjLoggerI18N.debug("Unregistering: " + name);
+
+		JMXServer.getAgent().unregisterMBean(name);
+	}
+
+	public void register() {
+		register(getName());
+	}
+
+	public void unregister() {
+		unregister(getName());
+	}
+
+	public String getName() {
+		return w.getName();
+	}
+
+	public String getType() {
+		return w.getType();
+	}
+
+	public String type() {
+		return getType();
+	}
+
+	public boolean activate() {
+		return false;
+	}
+
+	public Uid getUid(AbstractRecord rec) {
+		return rec.get_uid();
+	}
+
+	public String getId() {
+		return w.getUid().stringForm();
+	}
+
+	public Uid getUid() {
+		return w.getUid();
+	}
+
+	public StringBuilder toString(String prefix, StringBuilder sb) {
+		return sb.append(prefix).append('\t').append(getId()).append('\n');
+	}
+}

Added: labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/OSEntryBeanMBean.java
===================================================================
--- labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/OSEntryBeanMBean.java	                        (rev 0)
+++ labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/OSEntryBeanMBean.java	2010-05-24 18:34:15 UTC (rev 33056)
@@ -0,0 +1,9 @@
+package com.arjuna.ats.arjuna.tools.osb.mbean;
+
+import com.arjuna.ats.arjuna.tools.osb.annotation.MXBeanDescription;
+
+ at MXBeanDescription("")
+public interface OSEntryBeanMBean extends ObjStoreItemMBean {
+	String getType();
+	String getId();
+}

Deleted: labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/ObjStoreBean.java
===================================================================
--- labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/ObjStoreBean.java	2010-05-24 18:25:49 UTC (rev 33055)
+++ labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/ObjStoreBean.java	2010-05-24 18:34:15 UTC (rev 33056)
@@ -1,229 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags.
- * See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- * This copyrighted material is made available to anyone wishing to use,
- * modify, copy, or redistribute it subject to the terms and conditions
- * of the GNU Lesser General Public License, v. 2.1.
- * This program is distributed in the hope that it will be useful, but WITHOUT A
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
- * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
- * You should have received a copy of the GNU Lesser General Public License,
- * v.2.1 along with this distribution; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA  02110-1301, USA.
- *
- * (C) 2009
- * @author Red Hat Middleware LLC.
- */
-package com.arjuna.ats.arjuna.tools.osb.mbean;
-
-import javax.management.ObjectInstance;
-import javax.management.OperationsException;
-import javax.management.MBeanException;
-
-import com.arjuna.ats.arjuna.objectstore.ObjectStore;
-import com.arjuna.ats.arjuna.state.InputObjectState;
-import com.arjuna.ats.arjuna.exceptions.ObjectStoreException;
-import com.arjuna.ats.arjuna.common.arjPropertyManager;
-import com.arjuna.ats.arjuna.logging.tsLogger;
-import com.arjuna.ats.arjuna.tools.osb.util.JMXServer;
-
-import java.util.Collection;
-import java.util.Arrays;
-import java.util.ArrayList;
-import java.util.List;
-import java.io.IOException;
-import java.io.File;
-import java.io.FilenameFilter;
-
-/**
- * MBean representation of an Object Store.
- * An Object Store contains a type hierarchy for storing different kinds of record.
- * The hierarchy is reflected in the set of keys of the corresponding MBeans, ie a containing type will
- * have a set of keys that are a strict superset of each of the types further up the hierarchy.
- *
- * @see com.arjuna.ats.arjuna.objectstore.ObjectStore
- *
- * @message com.arjuna.ats.arjuna.tools.osb.mbean.ObjStoreBean.m_1
- *		  [com.arjuna.ats.arjuna.tools.osb.mbean.ObjStoreBean.m_1] - new store for location: {0}.
- * @message com.arjuna.ats.arjuna.tools.osb.mbean.ObjStoreBean.m_2
- *		  [com.arjuna.ats.arjuna.tools.osb.mbean.ObjStoreBean.m_2] - Error creating object store root: {0}.
- * @message com.arjuna.ats.arjuna.tools.osb.mbean.ObjStoreBean.m_3
- *		  [com.arjuna.ats.arjuna.tools.osb.mbean.ObjStoreBean.m_3] - Error creating object store root: {0}.
- * @message com.arjuna.ats.arjuna.tools.osb.mbean.ObjStoreBean.m_4
- *		  [com.arjuna.ats.arjuna.tools.osb.mbean.ObjStoreBean.m_4] - parsing store type: {0}
- * @message com.arjuna.ats.arjuna.tools.osb.mbean.ObjStoreBean.m_5
- *		  [com.arjuna.ats.arjuna.tools.osb.mbean.ObjStoreBean.m_5] - Browsing store {0} location: {1}
- *
- */
-public class ObjStoreBean extends ObjStoreTypeBean
-{
-    private ObjectStore store;
-    private int id;
-
-    private static ObjStoreBean localStore;
-    
-    public static ObjStoreTypeBean getObjectStoreBrowserBean()
-            throws OperationsException, MBeanException, InterruptedException, IOException
-    {
-        if (localStore == null)
-            localStore = (ObjStoreBean) getObjectStoreBrowserBean(0, arjPropertyManager.getObjectStoreEnvironmentBean().getObjectStoreDir());
-
-        return localStore;
-    }
-
-    public static ObjStoreTypeBean getObjectStoreBrowserBean(int id, String storeDir)
-            throws OperationsException, MBeanException, InterruptedException, IOException
-    {
-        ObjStoreBean sbean = new ObjStoreBean(id, storeDir);
-
-        sbean.register();
-
-        return sbean;
-    }
-
-    public ObjStoreBean()
-    {
-        super();
-    }
-
-    private List<String> getStoreNames()
-    {
-        File osf = new File(store.storeDir());
-        List<String> storeNames = new ArrayList<String>();
-
-        if (osf.exists())
-            storeNames = Arrays.asList(osf.list(new FilenameFilter() {
-                public boolean accept(File dir, String name) {
-                    return new File(dir, name).isDirectory();
-                }
-            }));
-
-        return storeNames;
-    }
-
-    // TODO dont restrict the mbean to filesystem based stores
-    public ObjStoreBean(int id, String storeLocation)
-    {
-        super(null, "/", "root");
-        this.id = id;
-
-        if (tsLogger.arjLoggerI18N.isDebugEnabled())
-            tsLogger.arjLoggerI18N.debug("com.arjuna.ats.arjuna.tools.osb.mbean.ObjStoreBean.m_1",
-                    new Object[] { storeLocation });
-
-        store = getObjectStore(storeLocation, null);
-    }
-
-    public String getObjectName()
-    {
-        // return a unique name for this object store
-        return "jboss.jta:type=ObjectStore,id=" + id;
-    }
-
-    public ObjectStore getStore()
-    {
-        return store;
-    }
-
-    public ObjectInstance register()
-    {
-        if (arjPropertyManager.getObjectStoreEnvironmentBean().isJmxEnabled()) {
-            Collection<ObjStoreTypeBean> beans = new ArrayList<ObjStoreTypeBean> ();
-            ObjectInstance oi = JMXServer.getAgent().registerMBean(this);
-
-            if (tsLogger.arjLoggerI18N.isDebugEnabled())
-                tsLogger.arjLoggerI18N.debug("com.arjuna.ats.arjuna.tools.osb.mbean.ObjStoreBean.m_4",
-                        new Object[] { arjPropertyManager.getCoordinatorEnvironmentBean().getActionStore() });
-
-            for (String storeName : getStoreNames()) {
-                allTypes(this, storeName, beans);
-
-                if (tsLogger.arjLoggerI18N.isDebugEnabled())
-                    tsLogger.arjLoggerI18N.debug("com.arjuna.ats.arjuna.tools.osb.mbean.ObjStoreBean.m_5",
-                            new Object[] { storeName, store.storeDir() });
-
-                for(ObjStoreTypeBean bean : beans)
-                    bean.register();
-
-                registeredBeans.addAll(beans);
-
-                beans.clear();
-            }
-
-            super.register();
-
-            return oi;
-        }
-
-        return null;
-    }
-
-    public boolean unregister()
-    {
-        return super.unregister();
-    }
-
-    public ObjectStore getObjectStore(String storeDir, String storeName)
-    {
-        arjPropertyManager.getObjectStoreEnvironmentBean().setObjectStoreDir(storeDir);
-        String storeImple = arjPropertyManager.getCoordinatorEnvironmentBean().getActionStore();
-        arjPropertyManager.getObjectStoreEnvironmentBean().setLocalOSRoot(storeName);
-
-        try {
-            Class osImple = Class.forName(storeImple);
-
-            return (ObjectStore) osImple.newInstance();
-        } catch (Exception e) {
-            if (tsLogger.arjLoggerI18N.isWarnEnabled())
-                tsLogger.arjLoggerI18N.warn("com.arjuna.ats.arjuna.tools.osb.mbean.ObjStoreBean.m_2",
-                        new Object[] { e });
-        }
-
-        return null;
-    }
-
-    public void allTypes(ObjStoreTypeBean parent, String storeName, Collection<ObjStoreTypeBean> names)
-    {
-        InputObjectState types = new InputObjectState();
-
-        try {
-            if (getObjectStore(store.storeDir(), storeName).allTypes(types)) {
-                while (true) {
-                    try {
-                        String theName = types.unpackString();
-
-                        if (theName.length() == 0)
-                            break;
-                        else
-                            names.add(new ObjStoreTypeBean(parent, storeName, theName));
-                    } catch (IOException e) {
-                        break; // end of list
-                    }
-                }
-            }
-        } catch (ObjectStoreException e) {
-            if (tsLogger.arjLoggerI18N.isWarnEnabled())
-                tsLogger.arjLoggerI18N.warn("com.arjuna.ats.arjuna.tools.osb.mbean.ObjStoreBean.m_3",
-                        new Object[] { e });
-        }
-    }
-
-    public static void main(String[] args) throws OperationsException, MBeanException, InterruptedException, IOException {
-        String[] storeLocations = {
-                "/home/mmusgrov/source/as/trunk/build/output/jboss-6.0.0-SNAPSHOT/server/all/data/tx-object-store",
-//                "../../logs/os.2",
-        };
-        ObjStoreBean[] browsers = new ObjStoreBean[storeLocations.length];
-
-        for (int i = 0; i < storeLocations.length; i++) {
-            browsers[i] = new ObjStoreBean(i, storeLocations[i]);
-            browsers[i].register();
-        }
-
-        Thread.sleep(24000000);
-    }
-}

Added: labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/ObjStoreBrowser.java
===================================================================
--- labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/ObjStoreBrowser.java	                        (rev 0)
+++ labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/ObjStoreBrowser.java	2010-05-24 18:34:15 UTC (rev 33056)
@@ -0,0 +1,255 @@
+package com.arjuna.ats.arjuna.tools.osb.mbean;
+
+import java.io.*;
+import java.net.URL;
+import java.util.*;
+
+import com.arjuna.ats.arjuna.logging.tsLogger;
+import com.arjuna.ats.arjuna.common.Uid;
+import com.arjuna.ats.arjuna.coordinator.TxControl;
+import com.arjuna.ats.arjuna.exceptions.ObjectStoreException;
+import com.arjuna.ats.arjuna.objectstore.ObjectStoreIterator;
+import com.arjuna.ats.arjuna.state.InputObjectState;
+import com.arjuna.ats.arjuna.tools.osb.util.JMXServer;
+
+import com.arjuna.ats.arjuna.common.*;
+
+/**
+ * An MBean implementation for walking an ObjectStore and creating/deleting MBeans
+ * that represent completing transactions (ie ones on which the user has called commit)
+ */
+public class ObjStoreBrowser implements ObjStoreBrowserMBean {
+	private static final String STORE_MBEAN_NAME = "jboss.jta:type=ObjectStore";
+	private static final String OS_BEAN_PROPFILE = "osmbean.properties";
+
+    // define which object store types can be represented by mbeans
+	private Properties typeHandlers;
+
+	private Map<String, List<UidWrapper>> allUids;
+
+	public static void main(String[] args) throws Exception {
+		InputStreamReader isr = new InputStreamReader(System.in);
+		BufferedReader br = new BufferedReader(isr);
+		String logDir = System.getProperty("objectstore.dir");
+		ObjStoreBrowser browser = new ObjStoreBrowser(logDir);
+
+		browser.start();
+
+		do {
+			System.out.println("> "); System.out.flush();
+			String[] req = br.readLine().split("\\s+");
+
+			if (req.length == 0 || "quit".equals(req[0]))
+				break;
+
+			browser.probe();
+
+			if ("dump".equals(req[0])) {
+				if (req.length == 1) {
+					System.out.println("Uid not found");
+				} else {
+					UidWrapper w = browser.findUid(req[1]);
+
+					if (w != null)
+						System.out.println("Attributes: " + w.toString("", new StringBuilder()));
+					else
+						System.out.println("Uid not found: " + req[1]);
+				}
+			} else if ("list".equals(req[0])) {
+				System.out.println(browser.dump(new StringBuilder()));
+			} //else if ("query".equals(req[0])) {
+			  //  browser.queryTest();
+		} while (true);
+	}
+
+	public static Properties loadProperties(String fname) {
+		Properties properties = new Properties();
+		URL url = ClassLoader.getSystemResource(fname);
+		try {
+			if (url != null)
+				properties.load(url.openStream());
+		} catch (IOException e) {
+		}
+
+		return properties;
+	}
+
+    /**
+     * Initialise the MBean
+     */
+	public void start()
+	{
+		JMXServer.getAgent().registerMBean(STORE_MBEAN_NAME, this);
+		probe();
+	}
+
+    /**
+     * Unregister all MBeans representing objects in the ObjectStore
+     * represented by this MBean
+     */
+	public void stop()
+	{
+		for (List<UidWrapper> uids : allUids.values()) {
+			for (Iterator<UidWrapper> i = uids.iterator(); i.hasNext(); ) {
+				UidWrapper w = i.next();
+				i.remove();
+				w.unregister();
+			}
+		}
+
+		JMXServer.getAgent().unregisterMBean(STORE_MBEAN_NAME);
+	}
+
+    /**
+     * Define which object store types will registered as MBeans
+     * @param types the list of ObjectStore types that can be represented
+     * as MBeans
+     */
+	public void setTypes(Map<String, String> types) {
+		for (Map.Entry<String, String> entry : types.entrySet()) {
+			if (tsLogger.arjLoggerI18N.isDebugEnabled())
+				tsLogger.arjLoggerI18N.debug("ObjStoreBrowser: adding type handler " + entry.getKey() + "," + entry.getValue());
+			typeHandlers.put(entry.getKey(), entry.getValue());
+		}
+	}
+
+	private void init(String logDir) {
+		if (logDir != null)
+			arjPropertyManager.getObjectStoreEnvironmentBean().setObjectStoreDir(logDir);
+
+		if (tsLogger.arjLoggerI18N.isDebugEnabled())
+			tsLogger.arjLoggerI18N.debug("ObjectStoreDir: " + arjPropertyManager.getObjectStoreEnvironmentBean().getObjectStoreDir());
+
+		allUids = new HashMap<String, List<UidWrapper>> ();
+		typeHandlers = loadProperties(OS_BEAN_PROPFILE);
+        
+		if (typeHandlers.size() == 0)
+			typeHandlers = loadProperties("META-INF/" + OS_BEAN_PROPFILE);
+	}
+
+	public ObjStoreBrowser() {
+		init(null);
+	}
+
+	public ObjStoreBrowser(String logDir) {
+		init(logDir);
+	}
+
+	public StringBuilder dump(StringBuilder sb) {
+		for (Map.Entry<String, List<UidWrapper>> typeEntry : allUids.entrySet()) {
+			sb.append(typeEntry.getKey()).append('\n');
+
+			for (UidWrapper uid : typeEntry.getValue())
+				uid.toString("\t", sb);
+		}
+
+		return sb;
+	}
+
+    /**
+     * See if the given uid has previously been registered as an MBean
+     * @param uid the unique id representing an ObjectStore entry
+     * @return the MBean wrapper corresponding to the requested Uid (or null
+     * if it hasn't been registered)
+     */
+	public UidWrapper findUid(Uid uid) {
+		return findUid(uid.stringForm());
+	}
+
+	public UidWrapper findUid(String uid) {
+		for (Map.Entry<String, List<UidWrapper>> typeEntry : allUids.entrySet())
+			for (UidWrapper w : typeEntry.getValue())
+				if (w.getUid().stringForm().equals(uid))
+					return w;
+
+		return null;
+	}
+
+    /**
+     * See if any new MBeans need to be registered or if any existing MBeans no longer exist
+     * as ObjectStore entries.
+     */
+	public void probe() {
+		InputObjectState types = new InputObjectState();
+
+		try {
+			if (TxControl.getStore().allTypes(types)) {
+				String tname;
+
+				do {
+					try {
+						tname = types.unpackString();
+
+						if (tname.length() != 0) {
+							List<UidWrapper> uids = allUids.get(tname);
+							if (uids == null) {
+								uids = new ArrayList<UidWrapper> ();
+								allUids.put(tname, uids);
+							}
+
+							if (typeHandlers.containsKey(tname))
+								updateMBeans(uids, System.currentTimeMillis(), true, tname, typeHandlers.getProperty(tname));
+						}
+					} catch (IOException e1) {
+						tname = "";
+					}
+				} while (tname.length() != 0);
+			}
+		} catch (ObjectStoreException e2) {
+			if (tsLogger.arjLoggerI18N.isDebugEnabled())
+				tsLogger.arjLoggerI18N.debug(e2.toString());
+		}
+	}
+
+    /**
+     * Register new MBeans of the requested type (or unregister ones whose
+     * corresponding ObjectStore entry has been removed)
+     * @param type the ObjectStore entry type
+     * @param beantype the class name of the MBean implementation used to represent
+     * the request type
+     * @return the list of MBeans representing the requested ObjectStore type
+     */
+	public List<UidWrapper> probe(String type, String beantype) {
+		if (!allUids.containsKey(type))
+			return null;
+
+		List<UidWrapper> uids = allUids.get(type);
+
+		updateMBeans(uids, System.currentTimeMillis(), false, type, beantype);
+
+		return uids;
+	}
+
+	private void updateMBeans(List<UidWrapper> uids, long tstamp, boolean register, String type, String thandler) {
+		ObjectStoreIterator iter = new ObjectStoreIterator(TxControl.getStore(), type);
+
+		while (true) {
+			Uid u = iter.iterate();
+			if (Uid.nullUid().equals(u))
+				break;
+
+			UidWrapper w = new UidWrapper(this, thandler, type, u);
+			int i = uids.indexOf(w);
+
+			if (i == -1) {
+				w.setTimestamp(tstamp);
+				uids.add(w);
+				w.createMBean();
+				if (register)
+					w.register();
+			} else {
+				uids.get(i).setTimestamp(tstamp);
+			}
+		}
+
+		for (Iterator<UidWrapper> i = uids.iterator(); i.hasNext(); ) {
+			UidWrapper w = i.next();
+
+			if (w.getTimestamp() != tstamp) {
+				if (register)
+					w.unregister();
+				i.remove();
+			}
+		}
+	}
+}

Added: labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/ObjStoreBrowserMBean.java
===================================================================
--- labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/ObjStoreBrowserMBean.java	                        (rev 0)
+++ labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/ObjStoreBrowserMBean.java	2010-05-24 18:34:15 UTC (rev 33056)
@@ -0,0 +1,10 @@
+package com.arjuna.ats.arjuna.tools.osb.mbean;
+
+import com.arjuna.ats.arjuna.tools.osb.annotation.MXBeanDescription;
+import com.arjuna.ats.arjuna.tools.osb.annotation.MXBeanPropertyDescription;
+
+ at MXBeanDescription("Representation of the transaction logging mechanism")
+public interface ObjStoreBrowserMBean extends ObjStoreItemMBean {
+	@MXBeanPropertyDescription("See if any new transactions have been created or completed")
+	void probe();
+}

Deleted: labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/ObjStoreEntryBean.java
===================================================================
--- labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/ObjStoreEntryBean.java	2010-05-24 18:25:49 UTC (rev 33055)
+++ labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/ObjStoreEntryBean.java	2010-05-24 18:34:15 UTC (rev 33056)
@@ -1,43 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags.
- * See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- * This copyrighted material is made available to anyone wishing to use,
- * modify, copy, or redistribute it subject to the terms and conditions
- * of the GNU Lesser General Public License, v. 2.1.
- * This program is distributed in the hope that it will be useful, but WITHOUT A
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
- * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
- * You should have received a copy of the GNU Lesser General Public License,
- * v.2.1 along with this distribution; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA  02110-1301, USA.
- *
- * (C) 2009
- * @author Red Hat Middleware LLC.
- */
-package com.arjuna.ats.arjuna.tools.osb.mbean;
-
-import com.arjuna.ats.arjuna.common.Uid;
-import com.arjuna.ats.arjuna.objectstore.ObjectStore;
-import com.arjuna.ats.arjuna.tools.osb.mbean.common.StateBean;
-
-/**
- * Super class for MBean representations of Object Store records
- *
- * @see com.arjuna.ats.arjuna.tools.osb.mbean.common.StateBeanMBean
- */
-public class ObjStoreEntryBean extends StateBean
-{
-	public ObjStoreEntryBean(ObjStoreTypeBean parent, Uid uid)
-    {
-        super(parent, parent.getStore(), uid);
-    }
-
-    public ObjectStore getStore()
-    {
-        return ((ObjStoreTypeBean) parent).getStore();
-    }
-}

Added: labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/ObjStoreItemMBean.java
===================================================================
--- labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/ObjStoreItemMBean.java	                        (rev 0)
+++ labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/ObjStoreItemMBean.java	2010-05-24 18:34:15 UTC (rev 33056)
@@ -0,0 +1,8 @@
+package com.arjuna.ats.arjuna.tools.osb.mbean;
+
+import com.arjuna.ats.arjuna.tools.osb.annotation.MXBeanDescription;
+import com.arjuna.ats.arjuna.tools.osb.annotation.MXBeanPropertyDescription;
+
+ at MXBeanDescription("Base view of transaction log entry")
+public interface ObjStoreItemMBean {
+}

Deleted: labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/ObjStoreTypeBean.java
===================================================================
--- labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/ObjStoreTypeBean.java	2010-05-24 18:25:49 UTC (rev 33055)
+++ labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/ObjStoreTypeBean.java	2010-05-24 18:34:15 UTC (rev 33056)
@@ -1,267 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags.
- * See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- * This copyrighted material is made available to anyone wishing to use,
- * modify, copy, or redistribute it subject to the terms and conditions
- * of the GNU Lesser General Public License, v. 2.1.
- * This program is distributed in the hope that it will be useful, but WITHOUT A
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
- * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
- * You should have received a copy of the GNU Lesser General Public License,
- * v.2.1 along with this distribution; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA  02110-1301, USA.
- *
- * (C) 2009
- * @author Red Hat Middleware LLC.
- */
-package com.arjuna.ats.arjuna.tools.osb.mbean;
-
-import java.util.*;
-import java.io.IOException;
-import java.lang.reflect.Constructor;
-
-import com.arjuna.ats.arjuna.objectstore.ObjectStore;
-import com.arjuna.ats.arjuna.common.Uid;
-import com.arjuna.ats.arjuna.exceptions.ObjectStoreException;
-import com.arjuna.ats.arjuna.state.InputObjectState;
-import com.arjuna.ats.arjuna.tools.osb.mbean.common.BasicBean;
-import com.arjuna.ats.arjuna.logging.tsLogger;
-import com.arjuna.ats.internal.arjuna.common.UidHelper;
-
-import javax.management.ObjectInstance;
-
-/**
- * MBean corresponding to an Object Store type.
- * An Ojbect Store type correspond to the type of record that can be stored in a given store location.
- *
- * @see com.arjuna.ats.arjuna.objectstore.ObjectStore
- *
- * @message com.arjuna.ats.arjuna.tools.osb.mbean.ObjStoreTypeBean.m_1
- *		  [com.arjuna.ats.arjuna.tools.osb.mbean.ObjStoreTypeBean.m_1] - new type: {0} store name: {0}.
- * @message com.arjuna.ats.arjuna.tools.osb.mbean.ObjStoreTypeBean.m_2
- *		  [com.arjuna.ats.arjuna.tools.osb.mbean.ObjStoreTypeBean.m_2] - error unpacking uids for type: {0}, : {1}.
- * @message com.arjuna.ats.arjuna.tools.osb.mbean.ObjStoreTypeBean.m_3
- *		  [com.arjuna.ats.arjuna.tools.osb.mbean.ObjStoreTypeBean.m_3] - Error unpacking uids for type: {0} : {1}.
- * @message com.arjuna.ats.arjuna.tools.osb.mbean.ObjStoreTypeBean.m_4
- *		  [com.arjuna.ats.arjuna.tools.osb.mbean.ObjStoreTypeBean.m_4] - registering bean: {0}.
- * @message com.arjuna.ats.arjuna.tools.osb.mbean.ObjStoreTypeBean.m_5
- *		  [com.arjuna.ats.arjuna.tools.osb.mbean.ObjStoreTypeBean.m_5] - Warning: no viewer for object store type {0}.
- * @message com.arjuna.ats.arjuna.tools.osb.mbean.ObjStoreTypeBean.m_6
- *		  [com.arjuna.ats.arjuna.tools.osb.mbean.ObjStoreTypeBean.m_6] - Error registering bean for class {0} : {1}.
- * @message com.arjuna.ats.arjuna.tools.osb.mbean.ObjStoreTypeBean.m_7
- *		  [com.arjuna.ats.arjuna.tools.osb.mbean.ObjStoreTypeBean.m_7] - Warning: error {0} creating viewer for object store type {1}.
- */
-public class ObjStoreTypeBean extends BasicBean
-{
-    /*
-     * A map for associating Object Store record type names with Java types that know how to represent
-     * them as JMX beans.
-     * 
-     * TODO move this map to an external file to make it easy to add new handlers
-     */
-    private static final Map<String, String[]> typeHandlers = new HashMap<String, String[]> () {{
-        put("StateManager/BasicAction/TwoPhaseCoordinator/AtomicAction", new String[] {
-                "com.arjuna.ats.arjuna.tools.osb.mbean.common.AtomicActionBean",
-                "com.arjuna.ats.arjuna.tools.osb.mbean.BasicActionBean"});
-        put("Recovery/TransactionStatusManager", new String[] {
-                "com.arjuna.ats.arjuna.tools.osb.mbean.common.TransactionStatusManagerItemBean" });
-
-        // JTS record type handlers
-        put("StateManager/BasicAction/TwoPhaseCoordinator/ArjunaTransactionImple", new String[] {
-                "com.arjuna.ats.internal.jta.tools.osb.mbean.jts.ArjunaTransactionImpleBean",
-                "com.arjuna.ats.arjuna.tools.osb.mbean.BasicActionBean" });
-        put("RecoveryCoordinator", new String[] {
-                "com.arjuna.ats.internal.jta.tools.osb.mbean.jts.RecoveryCoordinatorBean",
-                "com.arjuna.ats.arjuna.tools.osb.mbean.common.UidBean" });
-        put("CosTransactions/XAResourceRecord", new String[] {
-                "com.arjuna.ats.internal.jta.tools.osb.mbean.jts.JTSXAResourceRecordBean",
-                "com.arjuna.ats.arjuna.tools.osb.mbean.common.UidBean" });
-//		put("StateManager/AbstractRecord/XAResourceRecord", "org.jboss.jbosstm.tools.jmx.osb.mbeanimpl.JTAXAResourceRecordBean");
-    }};
-
-    private String type;
-    private String storeName;
-    protected List<BasicBean> registeredBeans = new ArrayList<BasicBean> ();
-
-    public ObjStoreTypeBean()
-    {
-        super();
-    }
-
-    public ObjStoreTypeBean(ObjStoreTypeBean parent, String storeName, String type)
-    {
-        super(parent, type);
-        this.parent = parent;
-        this.type = type;
-        this.storeName = storeName;
-
-        if (tsLogger.arjLoggerI18N.isDebugEnabled())
-            tsLogger.arjLoggerI18N.debug("com.arjuna.ats.arjuna.tools.osb.mbean.ObjStoreTypeBean.m_1",
-                    new Object[] { type, storeName });
-    }
-
-    public ObjectStore getStore()
-    {
-        return ((ObjStoreTypeBean) parent).getStore();
-    }
-
-    public String getObjectName()
-    {
-        return toObjectName(storeName, type).toString();
-    }
-
-    protected StringBuilder toObjectName(String storeName, String type)
-    {
-        StringBuilder on = new StringBuilder();
-        String[] nc = type.split("/");
-
-        on.append(parent.getObjectName()).append(',');
-        on.append("name=").append(storeName);
-
-        for (int i = 0; i < nc.length; i++) {
-            on.append(',').append('L').append(i + 1).append("=").append(nc[i]);
-        }
-
-        return on;
-    }
-
-    private void allUids(Collection<Uid> uis)
-    {
-        InputObjectState uids = new InputObjectState();
-
-        try {
-            if (getStore().allObjUids(type, uids)) {
-                try {
-                    boolean endOfUids = false;
-
-                    while (!endOfUids) {
-                        Uid theUid = UidHelper.unpackFrom(uids);
-
-                        if (theUid.equals(Uid.nullUid()))
-                            endOfUids = true;
-                        else
-                            uis.add(new Uid(theUid));
-                    }
-                } catch (IOException e) {
-                    if (tsLogger.arjLoggerI18N.isWarnEnabled())
-                        tsLogger.arjLoggerI18N.warn("com.arjuna.ats.arjuna.tools.osb.mbean.ObjStoreTypeBean.m_2",
-                                new Object[] { type, e });
-
-                }
-            }
-        } catch (ObjectStoreException e) {
-            if (tsLogger.arjLoggerI18N.isWarnEnabled())
-                tsLogger.arjLoggerI18N.warn("com.arjuna.ats.arjuna.tools.osb.mbean.ObjStoreTypeBean.m_3",
-                        new Object[] { type, e });
-
-        }
-    }
-
-    @Override
-    public void refresh()
-    {
-        clearErrors();
-        unregisterDependents(true);
-        register();
-        Iterator<BasicBean> i = registeredBeans.iterator();
-
-        while (i.hasNext()) {
-            BasicBean bb = i.next();
-
-            if (!bb.isMarked()) {
-                i.remove();
-                bb.unregister();
-            }
-        }
-    }
-
-    public ObjectInstance register()
-    {
-        Collection<Uid> uids = new ArrayList<Uid>();
-        ObjectInstance oi;
-        BasicBean bean;
-
-        if (tsLogger.arjLoggerI18N.isDebugEnabled())
-            tsLogger.arjLoggerI18N.debug("com.arjuna.ats.arjuna.tools.osb.mbean.ObjStoreTypeBean.m_4",
-                    new Object[] { getObjectName() });
-
-        allUids(uids);
-        oi = super.register(); // register this
-
-        if (!uids.isEmpty()) {
-//            oi = super.register(); // register this
-
-            for (Uid uid : uids) {
-                if ((bean = createBean(uid)) != null)
-                    registeredBeans.add(bean);
-            }
-        }
-
-        return oi;
-    }
-
-    public boolean unregister()
-    {
-        return super.unregister();
-    }
-
-    public void unregisterDependents(boolean markOnly)
-    {
-        for (BasicBean osBean : registeredBeans) {
-            if (markOnly)
-                osBean.mark();
-            else
-                osBean.unregister();
-        }
-
-        if (!markOnly)
-            registeredBeans.clear();
-    }
-
-    private BasicBean createBean(Uid uid)
-    {
-        String[] cnames = typeHandlers.get(type);
-
-        if (cnames == null) {
-            if (tsLogger.arjLoggerI18N.isWarnEnabled())
-                tsLogger.arjLoggerI18N.debug("com.arjuna.ats.arjuna.tools.osb.mbean.ObjStoreTypeBean.m_5",
-                        new Object[] { type });
-
-            cnames = new String[] { "com.arjuna.ats.tools.osb.mbean.ObjStoreEntryBean" };
-        }
-
-        for (String cname : cnames) {
-            try {
-                Class<BasicBean> cl = (Class<BasicBean>) Class.forName(cname);
-                Constructor<BasicBean> ccon = cl.getConstructor(ObjStoreTypeBean.class, Uid.class);
-                BasicBean action = ccon.newInstance(this, uid);
-
-                for (BasicBean registeredBean : registeredBeans) {
-                    if (registeredBean == action) {
-                        registeredBean.mark();
-                        return null;
-                    }
-                }
-
-                // TODO make sure all the parent beans are registered
-                action.register();
-
-                return action;
-            } catch (Exception e) {
-                if (tsLogger.arjLoggerI18N.isDebugEnabled())
-                    tsLogger.arjLoggerI18N.debug("com.arjuna.ats.arjuna.tools.osb.mbean.ObjStoreTypeBean.m_7",
-                            new Object[] { e.getMessage(), type });                
-            }
-        }
-
-        if (tsLogger.arjLoggerI18N.isWarnEnabled())
-            tsLogger.arjLoggerI18N.warn("com.arjuna.ats.arjuna.tools.osb.mbean.ObjStoreTypeBean.m_6",
-                    new Object[] { type, "No suitable handler" });
-
-        return null;
-    }
-}

Added: labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/ParticipantStatus.java
===================================================================
--- labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/ParticipantStatus.java	                        (rev 0)
+++ labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/ParticipantStatus.java	2010-05-24 18:34:15 UTC (rev 33056)
@@ -0,0 +1,6 @@
+package com.arjuna.ats.arjuna.tools.osb.mbean;
+
+/**
+ * Enumeration of the commit status of a participant in an action/transaction
+ */
+public enum ParticipantStatus {PREPARED, PENDING, FAILED, READONLY, HEURISTIC}
\ No newline at end of file

Added: labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/StateManagerWrapper.java
===================================================================
--- labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/StateManagerWrapper.java	                        (rev 0)
+++ labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/StateManagerWrapper.java	2010-05-24 18:34:15 UTC (rev 33056)
@@ -0,0 +1,68 @@
+package com.arjuna.ats.arjuna.tools.osb.mbean;
+
+import com.arjuna.ats.arjuna.logging.tsLogger;
+import com.arjuna.ats.arjuna.StateManager;
+import com.arjuna.ats.arjuna.common.Uid;
+import com.arjuna.ats.arjuna.exceptions.ObjectStoreException;
+import com.arjuna.ats.arjuna.objectstore.ObjectStore;
+import com.arjuna.ats.arjuna.state.InputObjectState;
+
+import java.io.IOException;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+public class StateManagerWrapper extends StateManager {
+	public static final DateFormat formatter = new SimpleDateFormat("E, dd MMM yyyy HH:mm:ss Z");
+
+	String state;
+	Uid txId = Uid.nullUid();
+	Uid processUid = Uid.nullUid();
+	long birthDate = -1;
+
+	public StateManagerWrapper(ObjectStore os, Uid uid, String type) {
+		super(uid);
+
+		try {
+			
+			unpackHeader(os.read_committed(uid, type));
+		} catch (IOException e) {
+			if (tsLogger.arjLoggerI18N.isInfoEnabled())
+				  tsLogger.arjLoggerI18N.info("org.jboss.jbosstm.tools.jmx.osb.MbState.m_1",
+						  new Object[] { e.getMessage() });
+		} catch (ObjectStoreException e) {
+			  if (tsLogger.arjLoggerI18N.isInfoEnabled())
+				  tsLogger.arjLoggerI18N.info("org.jboss.jbosstm.tools.jmx.osb.MbState.m_1",
+						  new Object[] { e.getMessage() });
+		}
+	}
+
+	public String getCreationTime()
+	{
+		return birthDate < 0 ? "" : formatter.format(new Date(birthDate));
+	}
+
+	public long getAgeInSeconds()
+	{
+		return (birthDate < 0 ? -1 : ((System.currentTimeMillis()) - birthDate) / 1000L);
+	}
+
+	void unpackHeader(InputObjectState os) throws IOException
+	{
+		if (os != null) {
+			state = os.unpackString();
+			byte[] txIdBytes = os.unpackBytes();
+			txId = new Uid(txIdBytes);
+
+			if (state.equals("#ARJUNA#")) {
+				if (!txId.equals(Uid.nullUid())) {
+					byte[] pUidBytes = os.unpackBytes();
+					processUid = new Uid(pUidBytes);
+				}
+
+				birthDate = os.unpackLong();
+			}
+		}
+	}
+
+}

Added: labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/UidWrapper.java
===================================================================
--- labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/UidWrapper.java	                        (rev 0)
+++ labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/mbean/UidWrapper.java	2010-05-24 18:34:15 UTC (rev 33056)
@@ -0,0 +1,134 @@
+package com.arjuna.ats.arjuna.tools.osb.mbean;
+
+import com.arjuna.ats.arjuna.logging.tsLogger;
+import com.arjuna.ats.arjuna.common.Uid;
+
+import java.lang.reflect.Constructor;
+import java.util.List;
+
+/**
+ * Base class MBean implementation wrapper for MBeans corresponding to a Uid
+ */
+public class UidWrapper {
+	private String name;
+	private ObjStoreBrowser browser;
+	private String beantype;
+	private String ostype;
+	private Uid uid;
+	private long tstamp;
+	private OSEntryBean mbean;
+
+	public UidWrapper(Uid uid) {
+		this.uid = uid;
+		this.name = "";
+		this.beantype = "";
+		this.ostype = "";
+	}
+
+	public OSEntryBean getMBean() {
+		return mbean;
+	}
+
+	public UidWrapper(ObjStoreBrowser browser, String beantype, String ostype, Uid uid) {
+		this.browser = browser;
+		this.ostype = ostype;
+		this.beantype = beantype;
+		this.uid = uid;
+		this.tstamp = 0L;
+		this.name = "jboss.jta:type=ObjectStore,itype=" + ostype + ",uid=" + uid.fileStringForm(); // + ",participant=false";
+	}
+
+    /**
+     * Refresh the management view of the whole ObjectStore
+     */
+	public void probe() {
+		browser.probe();
+	}
+
+	public String getType() {
+		return ostype;
+	}
+
+	public String getName() {
+		return name;
+	}
+
+	void register() {
+		mbean.register();
+	}
+
+	void unregister() {
+		mbean.unregister();
+	}
+
+    /**
+     * The timestamp represent the time (in milliseconds) when the bean was registered.
+     * It is used for deciding when a bean needs unregistering.
+     * @return
+     */
+	public long getTimestamp() {
+		return tstamp;
+	}
+
+	public void setTimestamp(long tstamp) {
+		this.tstamp = tstamp;
+	}
+
+	public Uid getUid() {
+        return uid;
+    }
+
+	@Override
+	public boolean equals(Object o) {
+		if (this == o) return true;
+		if (o == null || getClass() != o.getClass()) return false;
+
+		UidWrapper that = (UidWrapper) o;
+
+        return !(uid != null ? !uid.equals(that.uid) : that.uid != null);
+
+    }
+
+	@Override
+	public int hashCode() {
+		return uid != null ? uid.hashCode() : 0;
+	}
+
+	@Override
+	public String toString() {
+		return "UidWrapper{" +
+				"ostype='" + ostype + '\'' +
+				", uid=" + uid +
+				", tstamp=" + tstamp +
+				'}';
+	}
+
+	public StringBuilder toString(String prefix, StringBuilder sb) {
+		return mbean.toString(prefix, sb);
+	}
+
+	public List<UidWrapper> probe(String type, String beantype) {
+		return browser.probe(type, beantype);
+	}
+
+    /**
+     * Construct an MBean to represent this ObjectStore record. The bean type used
+     * for construct the MBean is provided in the configuration of the @see ObjStoreBrowser
+     * @return
+     */
+	public OSEntryBean createMBean() {
+		try {
+			Class<OSEntryBean> cl = (Class<OSEntryBean>) Class.forName(beantype);
+			Constructor<OSEntryBean> constructor = cl.getConstructor(UidWrapper.class);
+			mbean = constructor.newInstance(this);
+		} catch (Exception e) { // ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException
+			if (tsLogger.arjLoggerI18N.isInfoEnabled())
+				tsLogger.arjLoggerI18N.info("Error constructing mbean: " + e);
+			mbean = new OSEntryBean(this);
+		}
+
+		mbean.activate();
+
+		return mbean;
+	}
+}

Deleted: labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/util/ActionWrapper.java
===================================================================
--- labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/util/ActionWrapper.java	2010-05-24 18:25:49 UTC (rev 33055)
+++ labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/util/ActionWrapper.java	2010-05-24 18:34:15 UTC (rev 33056)
@@ -1,37 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags.
- * See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- * This copyrighted material is made available to anyone wishing to use,
- * modify, copy, or redistribute it subject to the terms and conditions
- * of the GNU Lesser General Public License, v. 2.1.
- * This program is distributed in the hope that it will be useful, but WITHOUT A
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
- * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
- * You should have received a copy of the GNU Lesser General Public License,
- * v.2.1 along with this distribution; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA  02110-1301, USA.
- *
- * (C) 2009
- * @author Red Hat Middleware LLC.
- */
-package com.arjuna.ats.arjuna.tools.osb.util;
-
-import com.arjuna.ats.arjuna.exceptions.ObjectStoreException;
-import com.arjuna.ats.arjuna.tools.osb.mbean.BasicActionBean;
-import com.arjuna.ats.arjuna.tools.osb.mbean.common.LogRecordListBean;
-
-import java.util.Map;
-
-/**
- * An interface that abstracts the differences between the JTS and JTA  versions of actions
- */
-public interface ActionWrapper
-{
-    void populateLists(Map<String, LogRecordListBean> lists, BasicActionBean bean);
-    void remove() throws ObjectStoreException;
-    com.arjuna.ats.arjuna.coordinator.BasicAction getAction();
-}

Deleted: labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/util/JMXServer.java
===================================================================
--- labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/util/JMXServer.java	2010-05-24 18:25:49 UTC (rev 33055)
+++ labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/util/JMXServer.java	2010-05-24 18:34:15 UTC (rev 33056)
@@ -1,161 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags.
- * See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- * This copyrighted material is made available to anyone wishing to use,
- * modify, copy, or redistribute it subject to the terms and conditions
- * of the GNU Lesser General Public License, v. 2.1.
- * This program is distributed in the hope that it will be useful, but WITHOUT A
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
- * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
- * You should have received a copy of the GNU Lesser General Public License,
- * v.2.1 along with this distribution; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA  02110-1301, USA.
- *
- * (C) 2009,
- * @author Red Hat Middleware LLC.
- */
-package com.arjuna.ats.arjuna.tools.osb.util;
-
-import com.arjuna.ats.arjuna.tools.osb.mbean.common.BasicBean;
-import com.arjuna.ats.arjuna.logging.tsLogger;
-
-import javax.management.*;
-import java.lang.management.ManagementFactory;
-import java.util.List;
-import java.util.ArrayList;
-import java.util.Iterator;
-
-/**
- * Simple wrapper for accessing the JMX server
- *
- * @message com.arjuna.ats.arjuna.tools.osb.util.JMXServer.m_1
- *          [com.arjuna.ats.arjuna.tools.osb.util.JMXServer.m_1] - registering bean {0}.
- * @message com.arjuna.ats.arjuna.tools.osb.util.JMXServer.m_2
- *          [com.arjuna.ats.arjuna.tools.osb.util.JMXServer.m_2] - Instance already exists: {0}.
- * @message com.arjuna.ats.arjuna.tools.osb.util.JMXServer.m_3
- *          [com.arjuna.ats.arjuna.tools.osb.util.JMXServer.m_3] - Error registrating {0} - {1}.
- * @message com.arjuna.ats.arjuna.tools.osb.util.JMXServer.m_4
- *          [com.arjuna.ats.arjuna.tools.osb.util.JMXServer.m_4] - Try to unregister mbean with invalid name {0}.
- * @message com.arjuna.ats.arjuna.tools.osb.util.JMXServer.m_5]
- *          [com.arjuna.ats.arjuna.tools.osb.util.JMXServer.m_5] - Unable to unregister bean {0} error: {1}.
- * @message com.arjuna.ats.arjuna.tools.osb.util.JMXServer.m_6
- *          [com.arjuna.ats.arjuna.tools.osb.util.JMXServer.m_6] - Unable to unregister bean {0} error: {1}.
- */
-
-public class JMXServer
-{
-    private static MBeanServer server;
-    private static JMXServer agent = new JMXServer();
-
-    public static JMXServer getAgent() { return agent; }
-
-    private List<BasicBean> registeredBeans = new ArrayList<BasicBean>();
-
-    public JMXServer()
-    {
-        Class<?> c1;
-        Class<?> c2;
-
-        try {
-            c1 = Class.forName("com.arjuna.ats.internal.jta.Implementations");
-            c1.getMethod("initialise").invoke(null);
-        } catch (Exception e) {
-        }
-
-        try {
-            c1 = Class.forName("com.arjuna.ats.internal.jts.Implementations");
-            c2 = Class.forName("com.arjuna.ats.internal.jta.Implementationsx"); // needed for XAResourceRecord
-
-            c1.getMethod("initialise").invoke(null);
-            c2.getMethod("initialise").invoke(null);
-        } catch (Exception e) {
-        }
-    }
-
-    public MBeanServer getServer()
-    {
-        if (server == null)
-        {
-            List<MBeanServer> servers = MBeanServerFactory.findMBeanServer(null);
-
-            if (servers != null && servers.size() > 0)
-                server = servers.get(0);
-            else
-                server = ManagementFactory.getPlatformMBeanServer();
-
-            if (server == null)
-                server = MBeanServerFactory.createMBeanServer();
-        }
-
-        return server;
-    }
-
-    public ObjectInstance registerMBean(BasicBean bean)
-    {
-        ObjectInstance oi = null;
-
-        try {
-            if (tsLogger.arjLoggerI18N.isInfoEnabled())
-                tsLogger.arjLoggerI18N.debug("com.arjuna.ats.arjuna.tools.osb.util.JMXServer.m_1",
-                        new Object[] { bean.getObjectName() });
-            oi = getServer().registerMBean(bean, new ObjectName(bean.getObjectName()));
-            registeredBeans.add(bean);
-        } catch (InstanceAlreadyExistsException e) {
-            if (tsLogger.arjLoggerI18N.isInfoEnabled())
-                tsLogger.arjLoggerI18N.debug("com.arjuna.ats.arjuna.tools.osb.util.JMXServer.m_2",
-                        new Object[] { bean.getObjectName() });
-        } catch (javax.management.JMException e) {
-            if (tsLogger.arjLoggerI18N.isWarnEnabled())
-                tsLogger.arjLoggerI18N.warn("com.arjuna.ats.arjuna.tools.osb.util.JMXServer.m_3",
-                        new Object[] { bean.getObjectName(), e.getMessage() });
-        }
-
-		return oi;
-    }
-
-    public boolean unregisterMBean(String objectName)
-	{
-        boolean unregistered = false;
-        try {
-			unregistered = unregisterMBean(new ObjectName(objectName));
-            Iterator<BasicBean> i = registeredBeans.iterator();
-
-            while (i.hasNext()) {
-                BasicBean bb = i.next();
-
-                if (objectName.equals(bb.getObjectName())) {
-                    i.remove();
-                    break;
-                }
-            }
-        } catch (MalformedObjectNameException e) {
-            if (tsLogger.arjLoggerI18N.isWarnEnabled())
-                tsLogger.arjLoggerI18N.warn("com.arjuna.ats.arjuna.tools.osb.util.JMXServer.m_4",
-                        new Object[] { e.getMessage() });
-		}
-
-        return unregistered;
-    }
-
-    public boolean unregisterMBean(ObjectName objectName)
-    {
-        try {
-            getServer().unregisterMBean(objectName);
-        	return true;
-        } catch (InstanceNotFoundException e) {
-            if (tsLogger.arjLoggerI18N.isWarnEnabled())
-                tsLogger.arjLoggerI18N.warn("com.arjuna.ats.arjuna.tools.osb.util.JMXServer.m_5",
-                        new Object[] { objectName, e.getMessage() });
-        } catch (MBeanRegistrationException e) {
-            if (tsLogger.arjLoggerI18N.isWarnEnabled())
-                tsLogger.arjLoggerI18N.warn("com.arjuna.ats.arjuna.tools.osb.util.JMXServer.m_6",
-                        new Object[] { objectName, e.getMessage() });
-        }
-
-        return false;
-    }
-}

Added: labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/util/JMXServer.java
===================================================================
--- labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/util/JMXServer.java	                        (rev 0)
+++ labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/tools/osb/util/JMXServer.java	2010-05-24 18:34:15 UTC (rev 33056)
@@ -0,0 +1,160 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags.
+ * See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License, v. 2.1.
+ * This program is distributed in the hope that it will be useful, but WITHOUT A
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
+ * You should have received a copy of the GNU Lesser General Public License,
+ * v.2.1 along with this distribution; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA  02110-1301, USA.
+ *
+ * (C) 2009,
+ * @author Red Hat Middleware LLC.
+ */
+package com.arjuna.ats.arjuna.tools.osb.util;
+
+import com.arjuna.ats.arjuna.logging.tsLogger;
+import com.arjuna.ats.arjuna.tools.osb.mbean.ObjStoreItemMBean;
+
+import javax.management.*;
+import java.lang.management.ManagementFactory;
+import java.lang.reflect.Constructor;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Simple wrapper for accessing the JMX server
+ *
+ * @message com.arjuna.ats.arjuna.tools.osb.util.JMXServer.m_1
+ *		  [com.arjuna.ats.arjuna.tools.osb.util.JMXServer.m_1] - registering bean {0}.
+ * @message com.arjuna.ats.arjuna.tools.osb.util.JMXServer.m_2
+ *		  [com.arjuna.ats.arjuna.tools.osb.util.JMXServer.m_2] - Instance already exists: {0}.
+ * @message com.arjuna.ats.arjuna.tools.osb.util.JMXServer.m_3
+ *		  [com.arjuna.ats.arjuna.tools.osb.util.JMXServer.m_3] - Error registrating {0} - {1}.
+ * @message com.arjuna.ats.arjuna.tools.osb.util.JMXServer.m_4
+ *		  [com.arjuna.ats.arjuna.tools.osb.util.JMXServer.m_4] - Try to unregister mbean with invalid name {0}.
+ * @message com.arjuna.ats.arjuna.tools.osb.util.JMXServer.m_5]
+ *		  [com.arjuna.ats.arjuna.tools.osb.util.JMXServer.m_5] - Unable to unregister bean {0} error: {1}.
+ * @message com.arjuna.ats.arjuna.tools.osb.util.JMXServer.m_6
+ *		  [com.arjuna.ats.arjuna.tools.osb.util.JMXServer.m_6] - Unable to unregister bean {0} error: {1}.
+ */
+
+public class JMXServer
+{
+	public static String JTS_INITIALISER_CNAME = "com.arjuna.ats.internal.jta.tools.osb.mbean.jts.ToolsInitialiser";
+	public static String AJT_RECORD_TYPE = "CosTransactions/XAResourceRecord";
+	public static String AJT_WRAPPER_TYPE = "com.arjuna.ats.internal.jta.tools.osb.mbean.jts.ArjunaTransactionImpleWrapper";
+	public static String AJT_XAREC_TYPE = "com.arjuna.ats.internal.jta.tools.osb.mbean.jts.XAResourceRecordBean";
+
+	private static MBeanServer server;
+	private static JMXServer agent = new JMXServer();
+	public static JMXServer getAgent() { return agent; }
+
+	public static boolean isJTS() {return getAgent().isJTS;}
+
+	private boolean isJTS;
+
+	public JMXServer()
+	{
+		Class<?> c1;
+		Class<?> c2;
+
+		try {
+			Class cl = Class.forName(JTS_INITIALISER_CNAME);
+			Constructor constructor = cl.getConstructor();
+			constructor.newInstance();
+			isJTS = true;
+		} catch (Exception e) { // ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException
+			if (tsLogger.arjLoggerI18N.isDebugEnabled())
+				tsLogger.arjLoggerI18N.debug("JTS not available: " + e);
+		}
+
+
+		try {
+			c1 = Class.forName("com.arjuna.ats.internal.jta.Implementations");
+			c1.getMethod("initialise").invoke(null);
+		} catch (Exception e) {
+		}
+
+		try {
+			c2 = Class.forName("com.arjuna.ats.internal.jta.Implementationsx"); // needed for XAResourceRecord
+
+			c2.getMethod("initialise").invoke(null);
+		} catch (Exception e) {
+		}
+	}
+
+	public MBeanServer getServer()
+	{
+		if (server == null)
+		{
+			List<MBeanServer> servers = MBeanServerFactory.findMBeanServer(null);
+
+			if (servers != null && servers.size() > 0)
+				server = servers.get(0);
+			else
+				server = ManagementFactory.getPlatformMBeanServer();
+
+			if (server == null)
+				server = MBeanServerFactory.createMBeanServer();
+		}
+
+		return server;
+	}
+
+	public ObjectInstance registerMBean(String name, ObjStoreItemMBean bean)
+	{
+		ObjectInstance oi = null;
+
+		try {
+			if (tsLogger.arjLoggerI18N.isInfoEnabled())
+				tsLogger.arjLoggerI18N.debug("com.arjuna.ats.arjuna.tools.osb.util.JMXServer.m_1",
+						new Object[] { name });
+			oi = getServer().registerMBean(bean, new ObjectName(name));
+		} catch (InstanceAlreadyExistsException e) {
+			if (tsLogger.arjLoggerI18N.isInfoEnabled())
+				tsLogger.arjLoggerI18N.debug("com.arjuna.ats.arjuna.tools.osb.util.JMXServer.m_2",
+						new Object[] { name });
+		} catch (javax.management.JMException e) {
+			if (tsLogger.arjLoggerI18N.isWarnEnabled())
+				tsLogger.arjLoggerI18N.warn("com.arjuna.ats.arjuna.tools.osb.util.JMXServer.m_3",
+						new Object[] { name, e.getMessage() });
+		}
+
+		return oi;
+	}
+
+	public boolean unregisterMBean(String name)
+	{
+		try {
+			getServer().unregisterMBean(new ObjectName(name));
+			return true;
+		} catch (MalformedObjectNameException e) {
+			if (tsLogger.arjLoggerI18N.isWarnEnabled())
+				tsLogger.arjLoggerI18N.warn("com.arjuna.ats.arjuna.tools.osb.util.JMXServer.m_5",
+						new Object[] { name, e.getMessage() });
+		} catch (InstanceNotFoundException e) {
+			if (tsLogger.arjLoggerI18N.isWarnEnabled())
+				tsLogger.arjLoggerI18N.warn("com.arjuna.ats.arjuna.tools.osb.util.JMXServer.m_5",
+						new Object[] { name, e.getMessage() });
+		} catch (MBeanRegistrationException e) {
+			// can't happen - none of our beans implement the MBeanRegistration interface
+			if (tsLogger.arjLoggerI18N.isWarnEnabled())
+				tsLogger.arjLoggerI18N.warn("com.arjuna.ats.arjuna.tools.osb.util.JMXServer.m_6",
+						new Object[] { name, e.getMessage() });
+		}
+
+		return false;
+	}
+
+	public Set<ObjectName> queryNames(String name, QueryExp query) throws MalformedObjectNameException {
+		return getServer().queryNames(new ObjectName(name), query);
+	}
+}

Added: labs/jbosstm/trunk/ArjunaCore/arjuna/tests/classes/com/hp/mwtests/ts/arjuna/tools/ObjStoreBrowserTest.java
===================================================================
--- labs/jbosstm/trunk/ArjunaCore/arjuna/tests/classes/com/hp/mwtests/ts/arjuna/tools/ObjStoreBrowserTest.java	                        (rev 0)
+++ labs/jbosstm/trunk/ArjunaCore/arjuna/tests/classes/com/hp/mwtests/ts/arjuna/tools/ObjStoreBrowserTest.java	2010-05-24 18:34:15 UTC (rev 33056)
@@ -0,0 +1,241 @@
+package com.hp.mwtests.ts.arjuna.tools;
+
+import java.util.*;
+
+import com.arjuna.ats.arjuna.common.Uid;
+import com.arjuna.ats.arjuna.common.recoveryPropertyManager;
+import com.arjuna.ats.arjuna.coordinator.AbstractRecord;
+import com.arjuna.ats.arjuna.coordinator.ActionStatus;
+import com.arjuna.ats.arjuna.coordinator.RecordType;
+import com.arjuna.ats.arjuna.coordinator.abstractrecord.RecordTypeManager;
+import com.arjuna.ats.arjuna.coordinator.abstractrecord.RecordTypeMap;
+import com.arjuna.ats.arjuna.tools.osb.util.JMXServer;
+
+import com.arjuna.ats.arjuna.tools.osb.mbean.*;
+
+import com.arjuna.ats.internal.arjuna.recovery.AtomicActionRecoveryModule;
+import com.arjuna.ats.internal.arjuna.recovery.RecoveryManagerImple;
+import com.hp.mwtests.ts.arjuna.resources.CrashRecord;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+import com.arjuna.ats.arjuna.AtomicAction;
+
+public class ObjStoreBrowserTest {
+    private RecoveryManagerImple rcm;
+
+    @Before
+    public void setUp () throws Exception
+    {
+        recoveryPropertyManager.getRecoveryEnvironmentBean().setRecoveryBackoffPeriod(1);
+
+        rcm = new RecoveryManagerImple(true);
+        rcm.addModule(new AtomicActionRecoveryModule());
+    }
+
+    @After
+    public void tearDown () throws Exception
+    {
+        rcm.removeAllModules(false);
+        rcm.stop(false);
+    }
+
+    /**
+     * create an MBean to represent an ObjectStore
+     * @return An object that maintains MBeans representing completing transactions
+     */
+    private ObjStoreBrowser createObjStoreBrowser() {
+        ObjStoreBrowser osb = new ObjStoreBrowser();
+
+        // define which object store types we are prepared to represent by mbeans
+        osb.setTypes( new HashMap<String, String>() {{
+			put("StateManager/BasicAction/TwoPhaseCoordinator/AtomicAction", "com.arjuna.ats.arjuna.tools.osb.mbean.ActionBean");
+		}});
+
+        return osb;
+    }
+
+    @Test
+    public void testOSEntryBean() throws Exception {
+        com.arjuna.common.tests.simple.EnvironmentBeanTest.testBeanByReflection(new OSEntryBean());
+    }
+
+    @Test
+    public void testLogRecordWrapper() throws Exception {
+        com.arjuna.common.tests.simple.EnvironmentBeanTest.testBeanByReflection(new LogRecordWrapper(Uid.nullUid()));
+    }
+
+    @Test
+    public void testObjectStoreBrowser() throws Exception {
+        com.arjuna.common.tests.simple.EnvironmentBeanTest.testBeanByReflection(createObjStoreBrowser());
+    }
+
+    @Test
+	public void basicOSBTest () throws Exception
+	{
+        ObjStoreBrowser osb = new ObjStoreBrowser("os");
+
+        Properties p = ObjStoreBrowser.loadProperties("invalid property file");
+
+        assertTrue(p.size() == 0);
+        osb.start();
+
+        // there should not be any MBeans
+        assertNull(osb.findUid(Uid.nullUid()));
+
+        // listing beans of an invalid type returns null
+        assertNull(osb.probe("InvalidType", "BeanClass"));
+
+        // listing beans of a valid type returns an empty list
+        assertNotNull(osb.probe("Recovery",
+                "com.arjuna.ats.arjuna.tools.osb.mbean.OSEntryBean"));
+
+        osb.stop();
+    }
+
+    /**
+     * Create an atomic action with two participants, one of which will generate a heuristic during phase 2.
+     * The test will move the heuristic back into the prepared state and trigger recovery to replay phase 2.
+     * The test then asserts that the corresponding MBeans have been unregistered.
+     * @throws Exception if test fails unexpectedly
+     */
+    @Test
+    public void aaReplayTest() throws Exception {
+        aaTest(true);
+    }
+    
+    /**
+     * Similar to aaReplayTest except that the whole transaction record is removed from the object store
+     * (instead of replaying the record that generates a heuristic).
+     * @throws Exception if test fails unexpectedly
+     */
+    @Test
+    public void aaRemoveTest() throws Exception {
+        aaTest(false);
+    }
+    
+	public void aaTest(boolean replay) throws Exception {
+		ObjStoreBrowser osb = createObjStoreBrowser();
+        AtomicAction A = new AtomicAction();
+        CrashRecord recs[] = {
+                new CrashRecord(CrashRecord.CrashLocation.NoCrash, CrashRecord.CrashType.Normal),
+                new CrashRecord(CrashRecord.CrashLocation.CrashInCommit, CrashRecord.CrashType.HeuristicHazard)
+        };
+
+        // register CrashRecord record type so that it is persisted in the object store correctly
+        RecordTypeManager.manager().add(new RecordTypeMap() {
+            public Class<? extends AbstractRecord> getRecordClass () { return CrashRecord.class;}
+            public int getType () {return RecordType.USER_DEF_FIRST0;}
+        });
+
+        // create an atomic action, register crash records with it and then commit
+        A.begin();
+
+        for (CrashRecord rec : recs)
+            A.add(rec);
+
+        int outcome = A.commit();
+
+        // the second participant should have generated a heuristic during commit
+        assertEquals(ActionStatus.H_HAZARD, outcome);
+
+        // generate MBeans representing the atomic action that was just committed
+		osb.start();
+
+        // there should be one MBean corresponding to the AtomicAction A
+        UidWrapper w = osb.findUid(A.get_uid());
+        assertNotNull(w);
+        OSEntryBean ai = w.getMBean();
+        assertNotNull(ai);
+
+        // the MBean should wrap an ActionBean
+        assertTrue(ai instanceof ActionBean);
+        ActionBean actionBean = (ActionBean) ai;
+
+        // and there should be one MBean corresponding to the CrashRecord that got the heuristic:
+        int recCount = 0;
+        for (CrashRecord rec : recs) {
+            LogRecordWrapper lw = actionBean.getParticipant(rec);
+
+            if (lw != null) {
+                recCount += 1;
+
+                assertTrue(lw.isHeuristic());
+
+                // put the participant back onto the pending list
+                lw.setStatus("PREPARED");
+                // and check that the record is no longer in a heuristic state
+                assertFalse(lw.isHeuristic());
+            }
+        }
+
+        assertEquals(1, recCount);
+
+        if (!replay) {
+            actionBean.remove();
+        } else {
+            /*
+            * prompt the recovery manager to replay the record that was
+            * moved off the heuristic list and back onto the prepared list
+            */
+            Thread.sleep(1000); // TODO why does sleep cause the scan to recognise the record can be replayed
+            rcm.scan();
+        }
+
+        /*
+         * Since the recovery scan (or explicit remove request) will have successfully removed the record from
+         * the object store another probe should cause the MBean representing the record to be unregistered
+         */
+        osb.probe();
+
+        // look up the MBean and verify that it no longer exists
+        w = osb.findUid(A.get_uid());
+        assertNull(w);
+
+		osb.dump(new StringBuilder());
+        osb.stop();
+	}
+
+    // define an MBean interface for use in the next test
+    public interface NotAnotherMBean extends ObjStoreItemMBean {}
+
+    @Test
+    public void testJMXServer() throws Exception {
+
+        class NonCompliantBean implements NotAnotherMBean {}
+        
+        ObjStoreBrowser osb = createObjStoreBrowser();
+        OSEntryBean bean;
+        String validName = "jboss.jta:type=TestObjectStore";
+
+        osb.start();
+
+        bean = new OSEntryBean();
+
+        // MalformedObjectNameException
+        assertNull(JMXServer.getAgent().registerMBean("InvalidName", bean));
+        assertFalse(JMXServer.getAgent().unregisterMBean("InvalidName"));
+
+        // InstanceNotFoundException
+        assertFalse(JMXServer.getAgent().unregisterMBean(validName));
+
+        // NotCompliantMBeanException
+        assertNull(JMXServer.getAgent().registerMBean(validName, new NonCompliantBean()));
+
+        // Do it right this time
+        int cnt = JMXServer.getAgent().queryNames(validName, null).size();
+        assertNotNull(JMXServer.getAgent().registerMBean(validName, bean));
+        assertEquals(cnt + 1, JMXServer.getAgent().queryNames(validName, null).size());
+
+        // InstanceAlreadyExistsException
+        assertNull(JMXServer.getAgent().registerMBean(validName, bean));
+
+        // Make sure unregistering a valid bean works
+        assertTrue(JMXServer.getAgent().unregisterMBean(validName));
+        assertEquals(0, JMXServer.getAgent().queryNames(validName, null).size());
+
+        osb.stop();
+    }
+}

Added: labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/tools/osb/mbean/jta/JTAActionBean.java
===================================================================
--- labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/tools/osb/mbean/jta/JTAActionBean.java	                        (rev 0)
+++ labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/tools/osb/mbean/jta/JTAActionBean.java	2010-05-24 18:34:15 UTC (rev 33056)
@@ -0,0 +1,26 @@
+package com.arjuna.ats.internal.jta.tools.osb.mbean.jta;
+
+import com.arjuna.ats.arjuna.coordinator.AbstractRecord;
+import com.arjuna.ats.arjuna.tools.osb.mbean.ActionBean;
+import com.arjuna.ats.arjuna.tools.osb.mbean.ParticipantStatus;
+import com.arjuna.ats.arjuna.tools.osb.mbean.LogRecordWrapper;
+import com.arjuna.ats.arjuna.tools.osb.mbean.UidWrapper;
+
+/**
+ * JTA specific version of an ActionBean that knows when a participant record
+ * corresponds to an XAResource
+ */
+public class JTAActionBean extends ActionBean {
+    
+    public JTAActionBean(UidWrapper w) {
+        super(w);
+    }
+
+    @Override
+    protected LogRecordWrapper createParticipant(AbstractRecord rec, ParticipantStatus listType) {
+        if (rec instanceof com.arjuna.ats.internal.jta.resources.arjunacore.XAResourceRecord)
+            return new com.arjuna.ats.internal.jta.tools.osb.mbean.jta.XAResourceRecordBean(this, rec, listType);
+        else
+            return super.createParticipant(rec, listType);
+    }
+}

Added: labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/tools/osb/mbean/jta/XAResourceMBean.java
===================================================================
--- labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/tools/osb/mbean/jta/XAResourceMBean.java	                        (rev 0)
+++ labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/tools/osb/mbean/jta/XAResourceMBean.java	2010-05-24 18:34:15 UTC (rev 33056)
@@ -0,0 +1,17 @@
+package com.arjuna.ats.internal.jta.tools.osb.mbean.jta;
+
+import com.arjuna.ats.arjuna.tools.osb.annotation.MXBeanDescription;
+import com.arjuna.ats.arjuna.tools.osb.annotation.MXBeanPropertyDescription;
+import com.arjuna.ats.arjuna.tools.osb.mbean.LogRecordWrapperMBean;
+
+ at MXBeanDescription("Management view of an XAResource participating in a transaction")
+public interface XAResourceMBean extends LogRecordWrapperMBean {
+	@MXBeanPropertyDescription("The java type that implements this XAResource")
+	String getClassName();
+	@MXBeanPropertyDescription("JNDI name of the JCA resource")
+	String getEisProductName();
+	@MXBeanPropertyDescription("JCA product version")
+	String getEisProductVersion();
+	@MXBeanPropertyDescription("The number of seconds before the resource can rollback the branch")
+	int getTimeout();
+}

Added: labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/tools/osb/mbean/jta/XAResourceRecordBean.java
===================================================================
--- labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/tools/osb/mbean/jta/XAResourceRecordBean.java	                        (rev 0)
+++ labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/tools/osb/mbean/jta/XAResourceRecordBean.java	2010-05-24 18:34:15 UTC (rev 33056)
@@ -0,0 +1,50 @@
+package com.arjuna.ats.internal.jta.tools.osb.mbean.jta;
+
+import com.arjuna.ats.arjuna.coordinator.AbstractRecord;
+import com.arjuna.ats.arjuna.tools.osb.mbean.ActionBean;
+import com.arjuna.ats.arjuna.tools.osb.mbean.ParticipantStatus;
+import com.arjuna.ats.arjuna.tools.osb.mbean.LogRecordWrapper;
+import com.arjuna.ats.arjuna.tools.osb.mbean.UidWrapper;
+
+import javax.transaction.xa.XAResource;
+
+/**
+ * MBean implementation of a transaction participant corresponding to a JTA XAResource
+ */
+public class XAResourceRecordBean extends LogRecordWrapper implements XAResourceRecordBeanMBean {
+    String className = "unavailable";
+    String eisProductName = "unavailable";
+    String eisProductVersion = "unavailable";
+    int timeout = 0;
+
+    public XAResourceRecordBean(UidWrapper w) {
+        super(w.getUid());
+    }
+    public XAResourceRecordBean(ActionBean parent, AbstractRecord rec, ParticipantStatus listType) {
+        super(parent, rec, listType);
+//        xares = new JTAXAResourceRecordWrapper(rec.order());
+    }
+
+    public boolean activate() {
+        boolean ok = super.activate();
+        XAResource xares = (XAResource) rec.value();
+
+        if (xares != null) {
+            className = xares.getClass().getName();
+            eisProductName = callMethod(xares, "getEisProductName");
+            this.eisProductVersion = callMethod(xares, "getEisProductVersion");
+
+            try {
+                timeout = xares.getTransactionTimeout();
+            } catch (Exception e) {
+            }
+        }
+
+        return ok;
+    }
+
+    public String getClassName() { return className; }
+    public String getEisProductName() { return eisProductName; }
+    public String getEisProductVersion() { return eisProductVersion; }
+    public int getTimeout() { return timeout; }
+}

Added: labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/tools/osb/mbean/jta/XAResourceRecordBeanMBean.java
===================================================================
--- labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/tools/osb/mbean/jta/XAResourceRecordBeanMBean.java	                        (rev 0)
+++ labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/tools/osb/mbean/jta/XAResourceRecordBeanMBean.java	2010-05-24 18:34:15 UTC (rev 33056)
@@ -0,0 +1,7 @@
+package com.arjuna.ats.internal.jta.tools.osb.mbean.jta;
+
+import com.arjuna.ats.arjuna.tools.osb.annotation.MXBeanDescription;
+
+ at MXBeanDescription("Management view of an XAResource participating in a transaction")
+public interface XAResourceRecordBeanMBean extends XAResourceMBean {
+}

Added: labs/jbosstm/trunk/ArjunaJTA/jta/tests/classes/com/hp/mwtests/ts/jta/tools/ObjStoreBrowserTest.java
===================================================================
--- labs/jbosstm/trunk/ArjunaJTA/jta/tests/classes/com/hp/mwtests/ts/jta/tools/ObjStoreBrowserTest.java	                        (rev 0)
+++ labs/jbosstm/trunk/ArjunaJTA/jta/tests/classes/com/hp/mwtests/ts/jta/tools/ObjStoreBrowserTest.java	2010-05-24 18:34:15 UTC (rev 33056)
@@ -0,0 +1,113 @@
+package com.hp.mwtests.ts.jta.tools;
+
+import java.util.*;
+
+import com.arjuna.ats.arjuna.common.Uid;
+import com.arjuna.ats.arjuna.tools.osb.mbean.*;
+import com.arjuna.ats.internal.arjuna.thread.ThreadActionData;
+import com.arjuna.ats.internal.jta.tools.osb.mbean.jta.JTAActionBean;
+import com.arjuna.ats.internal.jta.tools.osb.mbean.jta.XAResourceRecordBean;
+import com.hp.mwtests.ts.jta.common.DummyXA;
+import com.hp.mwtests.ts.jta.common.FailureXAResource;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionImple;
+
+import javax.transaction.HeuristicMixedException;
+import javax.transaction.xa.XAException;
+import javax.transaction.xa.XAResource;
+import javax.transaction.xa.Xid;
+
+import static org.junit.Assert.*;
+
+class ExtendedFailureXAResource extends FailureXAResource {
+    boolean forgotten;
+
+    @Override
+    public void commit(Xid id, boolean onePhase) throws XAException {
+        if (!forgotten)
+            super.commit(id, onePhase);
+    }
+
+    @Override
+    public void forget(Xid xid) throws XAException {
+        super.forget(xid);
+        forgotten = true;
+    }
+}
+
+public class ObjStoreBrowserTest {
+
+    private ObjStoreBrowser createObjStoreBrowser() {
+        ObjStoreBrowser osb = new ObjStoreBrowser();
+
+        osb.setTypes( new HashMap<String, String>() {{
+            put("StateManager/BasicAction/TwoPhaseCoordinator/ArjunaTransactionImple", "com.arjuna.ats.arjuna.tools.osb.mbean.ActionBean");
+            put("StateManager/BasicAction/TwoPhaseCoordinator/AtomicAction", "com.arjuna.ats.internal.jta.tools.osb.mbean.jta.JTAActionBean");
+        }});
+
+        return osb;
+    }
+
+    @BeforeClass
+    public static void setUp() {
+    }
+
+    @Test
+    public void testXAResourceRecordBean() throws Exception {
+        com.arjuna.common.tests.simple.EnvironmentBeanTest.testBeanByReflection(new XAResourceRecordBean(new UidWrapper(Uid.nullUid())));
+    }
+
+    @Test
+    public void testMBeanHeuristic () throws Exception
+    {
+        ThreadActionData.purgeActions();
+        ObjStoreBrowser osb = createObjStoreBrowser();
+        XAResource[] resources = {
+                new DummyXA(false),
+                new FailureXAResource(FailureXAResource.FailLocation.commit) // generates a heuristic on commit
+        };
+
+        TransactionImple tx = new TransactionImple(0);
+
+        // enlist the XA resources into the transaction
+        for (XAResource resource : resources) {
+
+            tx.enlistResource(resource);
+        }
+
+        try {
+            tx.commit();
+
+            fail("Expected a mixed heuristic");
+        } catch (final HeuristicMixedException ex) {
+        }
+
+        osb.start();
+        // there should be one MBean corresponding to the Transaction
+        UidWrapper w = osb.findUid(tx.get_uid());
+        assertNotNull(w);
+        OSEntryBean ai = w.getMBean();
+        assertNotNull(ai);
+
+        // the MBean should wrap a JTAActionBean
+        assertTrue(ai instanceof JTAActionBean);
+        JTAActionBean actionBean = (JTAActionBean) ai;
+
+        // and the transaction should contain only one participant (namely the FailureXAResource that generated the heuristic):
+        Collection<LogRecordWrapper> participants = actionBean.getParticipants();
+
+        assertEquals(1, participants.size());
+
+        for (LogRecordWrapper participant : participants) {
+            assertTrue(participant.isHeuristic());
+            // put the participant back onto the pending list
+            participant.setStatus("PREPARED");
+            // and check that the record is no longer in a heuristic state
+            assertFalse(participant.isHeuristic());
+        }
+
+        osb.stop();
+    }
+}

Added: labs/jbosstm/trunk/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/tools/osb/mbean/jts/ArjunaTransactionImpleWrapper.java
===================================================================
--- labs/jbosstm/trunk/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/tools/osb/mbean/jts/ArjunaTransactionImpleWrapper.java	                        (rev 0)
+++ labs/jbosstm/trunk/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/tools/osb/mbean/jts/ArjunaTransactionImpleWrapper.java	2010-05-24 18:34:15 UTC (rev 33056)
@@ -0,0 +1,67 @@
+package com.arjuna.ats.internal.jta.tools.osb.mbean.jts;
+
+import com.arjuna.ats.arjuna.common.Uid;
+import com.arjuna.ats.arjuna.coordinator.AbstractRecord;
+import com.arjuna.ats.arjuna.coordinator.RecordList;
+import com.arjuna.ats.arjuna.tools.osb.mbean.*;
+import com.arjuna.ats.internal.jts.orbspecific.coordinator.ArjunaTransactionImple;
+
+/**
+ * MBean wrapper for exposing the lists maintained by a JTS transaction
+ *
+ * @see com.arjuna.ats.internal.jts.orbspecific.coordinator.ArjunaTransactionImple
+ */
+public class ArjunaTransactionImpleWrapper extends ArjunaTransactionImple implements ActionBeanWrapperInterface {
+
+    ActionBean action;
+    boolean activated;
+
+    public ArjunaTransactionImpleWrapper (ActionBean action, UidWrapper w) {
+        super(w.getUid());
+        this.action = action;
+    }
+
+    public boolean activate() {
+        if (!activated)
+            activated = super.activate();
+
+        return activated;
+    }
+
+    public void doUpdateState() {
+        updateState();
+    }
+
+    public Uid getUid(AbstractRecord rec) {
+        return rec.order();
+    }
+
+    public void register() {
+
+    }
+
+    public void unregister() {
+        
+    }
+
+    public RecordList getRecords(ParticipantStatus type) {
+        switch (type) {
+            default:
+            case PREPARED: return preparedList;
+            case FAILED: return failedList;
+            case HEURISTIC: return heuristicList;
+            case PENDING: return pendingList;
+            case READONLY: return readonlyList;
+        }
+    }
+
+    public StringBuilder toString(String prefix, StringBuilder sb) {
+        prefix += '\t';
+        return sb.append('\n').append(prefix).append(get_uid());
+    }
+
+    public void clearHeuristicDecision(int newDecision) {
+        if (super.heuristicList.size() == 0)
+            setHeuristicDecision(newDecision);
+    }
+}

Added: labs/jbosstm/trunk/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/tools/osb/mbean/jts/ToolsInitialiser.java
===================================================================
--- labs/jbosstm/trunk/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/tools/osb/mbean/jts/ToolsInitialiser.java	                        (rev 0)
+++ labs/jbosstm/trunk/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/tools/osb/mbean/jts/ToolsInitialiser.java	2010-05-24 18:34:15 UTC (rev 33056)
@@ -0,0 +1,50 @@
+package com.arjuna.ats.internal.jta.tools.osb.mbean.jts;
+
+import com.arjuna.ats.jta.common.jtaPropertyManager;
+
+public class ToolsInitialiser {
+	static private String JTS_TM_CLASSNAME_STANDALONE =
+		"com.arjuna.ats.internal.jta.transaction.jts.TransactionManagerImple";
+	static private String JTS_TM_CLASSNAME_ATS =
+		"com.arjuna.ats.jbossatx.jts.TransactionManagerDelegate";
+    static private String ORB_NAME = "tools-orb";
+	static boolean initOrb = false;
+
+	private boolean isJTS;
+
+	public boolean isJTS() {
+		return isJTS;
+	}
+
+    public ToolsInitialiser() throws Exception {
+		String tmClassName = jtaPropertyManager.getJTAEnvironmentBean().getTransactionManagerClassName();
+
+		isJTS = (JTS_TM_CLASSNAME_STANDALONE.equals(tmClassName)
+			|| JTS_TM_CLASSNAME_ATS.equals(tmClassName));
+
+		if (initOrb) {
+        	try {
+            	com.arjuna.orbportability.ORB _orb;
+            	if (!com.arjuna.ats.internal.jts.ORBManager.isInitialised()) {
+                	_orb = com.arjuna.orbportability.ORB.getInstance(ORB_NAME);
+                	com.arjuna.orbportability.OA oa = com.arjuna.orbportability.OA.getRootOA(_orb);
+
+                	_orb.initORB((String[]) null, null);
+                	oa.initPOA(null);
+            	}
+        	} catch (Exception e) {
+            	
+        	}
+        }
+
+		if (isJTS) {
+        	try {
+            	Class c = Class.forName("com.arjuna.ats.internal.jts.Implementations");
+				//Class<?> c2 = Class.forName("com.arjuna.ats.internal.jta.Implementationsx"); // needed for XAResourceRecord
+
+            	c.getMethod("initialise").invoke(null);
+        	} catch (Exception e) {
+        	}
+		}
+    }
+}

Added: labs/jbosstm/trunk/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/tools/osb/mbean/jts/XAResourceRecordBean.java
===================================================================
--- labs/jbosstm/trunk/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/tools/osb/mbean/jts/XAResourceRecordBean.java	                        (rev 0)
+++ labs/jbosstm/trunk/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/tools/osb/mbean/jts/XAResourceRecordBean.java	2010-05-24 18:34:15 UTC (rev 33056)
@@ -0,0 +1,53 @@
+package com.arjuna.ats.internal.jta.tools.osb.mbean.jts;
+
+import com.arjuna.ats.arjuna.common.Uid;
+import com.arjuna.ats.arjuna.coordinator.AbstractRecord;
+import com.arjuna.ats.arjuna.tools.osb.mbean.ActionBean;
+import com.arjuna.ats.arjuna.tools.osb.mbean.ParticipantStatus;
+import com.arjuna.ats.arjuna.tools.osb.mbean.LogRecordWrapper;
+import com.arjuna.ats.arjuna.tools.osb.mbean.UidWrapper;
+
+/**
+ * MBean implementation of a transaction participant corresponding to a JTA XAResource
+ */
+public class XAResourceRecordBean extends LogRecordWrapper implements XAResourceRecordBeanMBean {
+    JTSXAResourceRecordWrapper xares;
+    String className = "unavailable";
+    String eisProductName = "unavailable";
+    String eisProductVersion = "unavailable";
+    int timeout = 0;
+
+    public XAResourceRecordBean(UidWrapper w) {
+        super(w.getUid());
+        xares = new JTSXAResourceRecordWrapper(w.getUid());
+    }
+    public XAResourceRecordBean(ActionBean parent, AbstractRecord rec, ParticipantStatus listType) {
+        super(parent, rec, listType);
+        xares = new JTSXAResourceRecordWrapper(rec.order());
+    }
+
+    public String getClassName() { return className; }
+    public String getEisProductName() { return eisProductName; }
+    public String getEisProductVersion() { return eisProductVersion; }
+    public int getTimeout() { return timeout; }
+
+    /**
+     * Extension of an XAResource record for exposing the underlying XAResource which is protected
+     */
+    public class JTSXAResourceRecordWrapper extends com.arjuna.ats.internal.jta.resources.jts.orbspecific.XAResourceRecord {
+        public JTSXAResourceRecordWrapper(Uid uid) {
+            super(uid);
+
+            if (_theXAResource != null) {
+                XAResourceRecordBean.this.className = _theXAResource.getClass().getName();
+                XAResourceRecordBean.this.eisProductName = callMethod(_theXAResource, "getEisProductName");
+                XAResourceRecordBean.this.eisProductVersion = callMethod(_theXAResource, "getEisProductVersion");
+
+                try {
+                    timeout = _theXAResource.getTransactionTimeout();
+                } catch (Exception e) {
+                }
+            }
+        }
+    }
+}

Added: labs/jbosstm/trunk/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/tools/osb/mbean/jts/XAResourceRecordBeanMBean.java
===================================================================
--- labs/jbosstm/trunk/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/tools/osb/mbean/jts/XAResourceRecordBeanMBean.java	                        (rev 0)
+++ labs/jbosstm/trunk/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/tools/osb/mbean/jts/XAResourceRecordBeanMBean.java	2010-05-24 18:34:15 UTC (rev 33056)
@@ -0,0 +1,9 @@
+package com.arjuna.ats.internal.jta.tools.osb.mbean.jts;
+
+import com.arjuna.ats.internal.jta.tools.osb.mbean.jta.XAResourceMBean;
+
+import com.arjuna.ats.arjuna.tools.osb.annotation.MXBeanDescription;
+
+ at MXBeanDescription("Management view of an XAResource participating in a transaction")
+public interface XAResourceRecordBeanMBean extends XAResourceMBean {
+}

Added: labs/jbosstm/trunk/ArjunaJTS/jtax/tests/classes/com/hp/mwtests/ts/jta/jts/common/ExtendedCrashRecord.java
===================================================================
--- labs/jbosstm/trunk/ArjunaJTS/jtax/tests/classes/com/hp/mwtests/ts/jta/jts/common/ExtendedCrashRecord.java	                        (rev 0)
+++ labs/jbosstm/trunk/ArjunaJTS/jtax/tests/classes/com/hp/mwtests/ts/jta/jts/common/ExtendedCrashRecord.java	2010-05-24 18:34:15 UTC (rev 33056)
@@ -0,0 +1,212 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2006, Red Hat Middleware LLC, and individual contributors 
+ * as indicated by the @author tags. 
+ * See the copyright.txt in the distribution for a
+ * full listing of individual contributors. 
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License, v. 2.1.
+ * This program is distributed in the hope that it will be useful, but WITHOUT A 
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 
+ * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
+ * You should have received a copy of the GNU Lesser General Public License,
+ * v.2.1 along with this distribution; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
+ * MA  02110-1301, USA.
+ * 
+ * (C) 2005-2006,
+ * @author JBoss Inc.
+ */
+/*
+ * Copyright (C) 2004,
+ *
+ * Arjuna Technologies Limited,
+ * Newcastle upon Tyne,
+ * Tyne and Wear,
+ * UK.  
+ *
+ * $Id: BasicRecord.java 2342 2006-03-30 13:06:17Z  $
+ */
+
+package com.hp.mwtests.ts.jta.jts.common;
+
+import com.arjuna.ats.arjuna.common.Uid;
+import com.arjuna.ats.arjuna.coordinator.AbstractRecord;
+import com.arjuna.ats.arjuna.coordinator.RecordType;
+import com.arjuna.ats.arjuna.coordinator.TwoPhaseOutcome;
+import com.arjuna.ats.arjuna.state.InputObjectState;
+import com.arjuna.ats.arjuna.state.OutputObjectState;
+
+import java.io.IOException;
+
+// Mostly a duplication of com.hp.mwtests.ts.arjuna.resources.CrashRecord
+
+public class ExtendedCrashRecord extends AbstractRecord // XAResourceRecord
+{
+    public enum CrashLocation { NoCrash, CrashInPrepare, CrashInCommit, CrashInAbort }
+    public enum CrashType { Normal, HeuristicHazard }
+
+    // Need a default constructor to keep the RecordTypeManager happy
+    public ExtendedCrashRecord()
+    {
+        _cl = CrashLocation.NoCrash;
+        _ct = CrashType.Normal;
+    }
+
+    public ExtendedCrashRecord(CrashLocation cl, CrashType ct)
+    {
+        super(new Uid());
+
+        _cl = cl;
+        _ct = ct;
+    }
+
+    public void forget()
+    {
+        _forgotten = true;
+    }
+
+    public int typeIs()
+    {
+        return RecordType.USER_DEF_FIRST0;
+    }
+
+    public int nestedAbort()
+    {
+        return TwoPhaseOutcome.FINISH_OK;
+    }
+
+    public int nestedCommit()
+    {
+        return TwoPhaseOutcome.FINISH_ERROR;
+    }
+
+    public int nestedPrepare()
+    {
+        return TwoPhaseOutcome.PREPARE_NOTOK;
+    }
+
+    public int topLevelAbort()
+    {
+        if (!_forgotten && _cl == CrashLocation.CrashInAbort)
+        {
+            _forgotten = true;
+            if (_ct == CrashType.Normal)
+                return TwoPhaseOutcome.FINISH_ERROR;
+            else
+                return TwoPhaseOutcome.HEURISTIC_HAZARD;
+        }
+        else
+            return TwoPhaseOutcome.FINISH_OK;
+    }
+
+    public int topLevelCommit()
+    {
+        if (!_forgotten && _cl == CrashLocation.CrashInCommit)
+        {
+            _forgotten = true;
+            if (_ct == CrashType.Normal)
+                return TwoPhaseOutcome.FINISH_ERROR;
+            else
+                return TwoPhaseOutcome.HEURISTIC_HAZARD;
+        }
+        else
+            return TwoPhaseOutcome.FINISH_OK;
+    }
+
+    public int topLevelPrepare()
+    {
+        if (!_forgotten && _cl == CrashLocation.CrashInAbort)
+        {
+            _forgotten = true;
+            if (_ct == CrashType.Normal)
+                return TwoPhaseOutcome.PREPARE_NOTOK;
+            else
+                return TwoPhaseOutcome.HEURISTIC_HAZARD;
+        }
+        else
+            return TwoPhaseOutcome.PREPARE_OK;
+    }
+
+    public boolean doSave()
+    {
+        return true;
+    }
+
+    public boolean save_state(OutputObjectState os, int ot)
+    {
+        try {
+            os.packBoolean(_forgotten);
+        } catch (IOException e) {
+            return false;
+        }
+        return super.save_state(os, ot);
+    }
+
+    public boolean restore_state(InputObjectState os, int ot)
+    {
+        try {
+            _forgotten = os.unpackBoolean();
+        } catch (IOException e) {
+            return false;
+        }
+
+        return super.restore_state(os, ot);
+    }
+
+    public String type()
+    {
+        return "/StateManager/AbstractRecord/ExtendedCrashRecord";
+    }
+
+    public boolean shouldAdd(AbstractRecord a)
+    {
+        return false;
+    }
+
+    public boolean shouldMerge(AbstractRecord a)
+    {
+        return false;
+    }
+
+    public boolean shouldReplace(AbstractRecord a)
+    {
+        return false;
+    }
+
+    public boolean shouldAlter(AbstractRecord a)
+    {
+        return false;
+    }
+
+    public void merge(AbstractRecord a)
+    {
+    }
+
+    public void alter(AbstractRecord a)
+    {
+    }
+
+    public String toString ()
+    {
+        return "CrashRecord. forgotten: " + _forgotten + ": " + super.toString();
+    }
+
+    /**
+     * @return <code>Object</code> to be used to order.
+     */
+
+    public Object value()
+    {
+        return null;
+    }
+
+    public void setValue(Object o)
+    {
+    }
+
+    private boolean _forgotten;
+    private CrashLocation _cl;
+    private CrashType _ct;
+}
\ No newline at end of file

Added: labs/jbosstm/trunk/ArjunaJTS/jtax/tests/classes/com/hp/mwtests/ts/jta/jts/tools/JTSObjStoreBrowserTest.java
===================================================================
--- labs/jbosstm/trunk/ArjunaJTS/jtax/tests/classes/com/hp/mwtests/ts/jta/jts/tools/JTSObjStoreBrowserTest.java	                        (rev 0)
+++ labs/jbosstm/trunk/ArjunaJTS/jtax/tests/classes/com/hp/mwtests/ts/jta/jts/tools/JTSObjStoreBrowserTest.java	2010-05-24 18:34:15 UTC (rev 33056)
@@ -0,0 +1,232 @@
+package com.hp.mwtests.ts.jta.jts.tools;
+
+import com.arjuna.ats.arjuna.AtomicAction;
+import com.arjuna.ats.arjuna.common.recoveryPropertyManager;
+import com.arjuna.ats.arjuna.coordinator.AbstractRecord;
+import com.arjuna.ats.arjuna.coordinator.ActionStatus;
+import com.arjuna.ats.arjuna.coordinator.RecordType;
+import com.arjuna.ats.arjuna.coordinator.TwoPhaseCoordinator;
+import com.arjuna.ats.arjuna.coordinator.abstractrecord.RecordTypeManager;
+import com.arjuna.ats.arjuna.coordinator.abstractrecord.RecordTypeMap;
+import com.arjuna.ats.arjuna.tools.osb.mbean.*;
+import com.arjuna.ats.internal.arjuna.recovery.AtomicActionRecoveryModule;
+import com.arjuna.ats.internal.arjuna.recovery.RecoveryManagerImple;
+import com.arjuna.ats.internal.jta.recovery.jts.XARecoveryModule;
+import com.arjuna.ats.internal.jts.orbspecific.coordinator.ArjunaTransactionImple;
+import com.hp.mwtests.ts.jta.jts.common.ExtendedCrashRecord;
+import org.junit.Test;
+import org.junit.Before;
+import org.junit.After;
+
+import com.arjuna.ats.internal.arjuna.thread.ThreadActionData;
+import org.omg.CosTransactions.HeuristicHazard;
+import com.hp.mwtests.ts.jta.jts.common.TestBase;
+
+import java.util.HashMap;
+
+import static org.junit.Assert.*;
+
+/**
+ * Test the the ObjStoreBrowser MBean in a JTS environment.
+ */
+public class JTSObjStoreBrowserTest extends TestBase {
+    private RecoveryManagerImple rcm;
+
+    @Before
+    public void setUp () throws Exception
+    {
+//        recoveryPropertyManager.getRecoveryEnvironmentBean().setPeriodicRecoveryPeriod(1);
+        recoveryPropertyManager.getRecoveryEnvironmentBean().setRecoveryBackoffPeriod(1);
+
+        rcm = new RecoveryManagerImple(true);
+        rcm.addModule(new XARecoveryModule());
+        rcm.addModule(new AtomicActionRecoveryModule());
+    }
+
+    @After
+    public void tearDown () throws Exception
+    {
+        rcm.removeAllModules(false);
+        rcm.stop(false);
+    }
+
+    private ObjStoreBrowser createObjStoreBrowser() {
+        ObjStoreBrowser osb = new ObjStoreBrowser();
+
+        osb.setTypes( new HashMap<String, String>() {{
+			put("StateManager/BasicAction/TwoPhaseCoordinator/ArjunaTransactionImple", "com.arjuna.ats.arjuna.tools.osb.mbean.ActionBean");
+			put("StateManager/BasicAction/TwoPhaseCoordinator/AtomicAction", "com.arjuna.ats.arjuna.tools.osb.mbean.ActionBean");
+		}});
+
+        return osb;
+    }
+
+    /*
+         TODO JTS test-compile doesn't pull in com.arjuna.common.tests.simple
+    @Test
+    public void testXAResourceRecordBean() throws Exception {
+        com.arjuna.common.tests.simple.EnvironmentBeanTest.testBeanByReflection(new XAResourceRecordBean(new UidWrapper(Uid.nullUid())));
+    }
+    */
+
+    /**
+     * Create an atomic action with two participants, one of which will generate a heuristic during phase 2.
+     * The test will move the heuristic back into the prepared state and trigger recovery to replay phase 2.
+     * The test then asserts that the corresponding MBeans have been unregistered.
+     * @throws Exception if test fails unexpectedly
+     */
+    @Test
+    public void aaReplayTest() throws Exception {
+        AtomicAction A = new AtomicAction();
+        ExtendedCrashRecord recs[] = startTest(A);
+
+        int outcome = A.commit();
+
+		assertEquals(ActionStatus.H_HAZARD, outcome);
+
+        finishTest(A, true, recs);
+    }
+
+    /**
+     * Similar to @aaReplayTest except that the whole transaction record is removed from the object store
+     * (instead of replaying the record that generates a heuristic).
+     * @throws Exception if test fails unexpectedly
+     */
+    @Test
+    public void aaRemoveTest() throws Exception {
+        AtomicAction A = new AtomicAction();
+        ExtendedCrashRecord recs[] = startTest(A);
+
+        int outcome = A.commit();
+
+		assertEquals(ActionStatus.H_HAZARD, outcome);
+
+        finishTest(A, false, recs);
+    }
+
+    /**
+     * Similar to aaReplayTest but uses a JTS transaction instead of an AtomicAction
+     * @throws Exception if test fails unexpectedly
+     */
+    // TODO for replay to work on JTS participants ExtendedCrashReocrd wou needs to extend XAResourceRecord
+    // TODO @Test
+    public void jtsReplayTest() throws Exception {
+        ArjunaTransactionImple A = new ArjunaTransactionImple(null);
+        ExtendedCrashRecord recs[] = startTest(A);
+
+        int outcome = ActionStatus.COMMITTED;
+
+		try {
+            A.commit(true);
+        } catch (HeuristicHazard e) {
+            outcome = ActionStatus.H_HAZARD;
+        }
+
+		assertEquals(ActionStatus.H_HAZARD, outcome);
+
+        finishTest(A, true, recs);
+    }
+
+    /**
+     * Similar to aaRemoveTest but uses a JTS transaction instead of an AtomicAction
+     * @throws Exception if test fails unexpectedly
+     */
+    @Test
+    public void jtsRemoveTest() throws Exception {
+        ArjunaTransactionImple A = new ArjunaTransactionImple(null);
+        ExtendedCrashRecord recs[] = startTest(A);
+
+        int outcome = ActionStatus.COMMITTED;
+
+		try {
+            A.commit(true);
+        } catch (HeuristicHazard e) {
+            outcome = ActionStatus.H_HAZARD;
+        }
+
+		assertEquals(ActionStatus.H_HAZARD, outcome);
+
+        finishTest(A, false, recs);
+    }
+
+    private ExtendedCrashRecord[] startTest(TwoPhaseCoordinator A) throws Exception {
+        ThreadActionData.purgeActions();
+
+        ExtendedCrashRecord recs[] = {
+                new ExtendedCrashRecord(ExtendedCrashRecord.CrashLocation.NoCrash, ExtendedCrashRecord.CrashType.Normal),
+                new ExtendedCrashRecord(ExtendedCrashRecord.CrashLocation.CrashInCommit, ExtendedCrashRecord.CrashType.HeuristicHazard)
+        };
+
+        RecordTypeManager.manager().add(new RecordTypeMap() {
+            public Class<? extends AbstractRecord> getRecordClass () { return ExtendedCrashRecord.class;}
+            public int getType () {return RecordType.USER_DEF_FIRST0;}
+        });
+
+        A.start();
+
+        for (ExtendedCrashRecord rec : recs)
+			A.add(rec);
+        
+        return recs;
+    }
+
+    private void finishTest(TwoPhaseCoordinator A, boolean replay, ExtendedCrashRecord ... recs) throws Exception {
+        ObjStoreBrowser osb = createObjStoreBrowser();
+
+        // there should now be an entry in the object store containing two participants
+        osb.start();
+
+        // there should be one MBean corresponding to the AtomicAction A
+        UidWrapper w = osb.findUid(A.get_uid());
+        assertNotNull(w);
+        OSEntryBean ai = w.getMBean();
+        assertNotNull(ai);
+
+        // the MBean should wrap an ActionBean
+        assertTrue(ai instanceof ActionBean);
+        ActionBean actionBean = (ActionBean) ai;
+
+        // and there should be one MBean corresponding to the CrashRecord that got the heuristic:
+        int recCount = 0;
+        for (ExtendedCrashRecord rec : recs) {
+            LogRecordWrapper lw = actionBean.getParticipant(rec);
+
+            if (lw != null) {
+                recCount += 1;
+
+                if (lw.isHeuristic()) {
+                    if (replay) {
+                        rec.forget();
+                        lw.setStatus("PREPARED");
+                        // the participant record should no longer be on the heuristic list
+                        assertFalse(lw.isHeuristic());
+                    }
+                }
+            }
+        }
+
+        assertEquals(1, recCount);
+
+        if (!replay) {
+            actionBean.remove();
+        } else {
+            /*
+            * prompt the recovery manager to have a go at replaying the record that was
+            * moved off the heuristic list and back onto the prepared list
+            */
+            Thread.sleep(1000); // TODO why does sleep cause the scan to recognise the record can be replayed
+            rcm.scan();
+        }
+
+        // another probe should no longer find the record that got the heuristic
+        // (since it was either removed or the RecoveryManager replayed the commit
+        // phase) so its corresponding MBean will have been unregistered
+        osb.probe();
+
+        // look up the MBean and verify that it no longer exists
+        w = osb.findUid(A.get_uid());
+        assertNull(w);
+
+        osb.stop();
+    }
+}
\ No newline at end of file

Modified: labs/jbosstm/trunk/atsintegration/transaction-jboss-beans.xml
===================================================================
--- labs/jbosstm/trunk/atsintegration/transaction-jboss-beans.xml	2010-05-24 18:25:49 UTC (rev 33055)
+++ labs/jbosstm/trunk/atsintegration/transaction-jboss-beans.xml	2010-05-24 18:34:15 UTC (rev 33056)
@@ -120,16 +120,21 @@
         <property name="objectStoreDir">${jboss.server.data.dir}/tx-object-store</property>
     </bean>
 
-    <bean name="ObjectStoreBrowserBean" class="com.arjuna.ats.arjuna.tools.osb.mbean.ObjStoreBean">
-       <constructor factoryClass="com.arjuna.ats.arjuna.tools.osb.mbean.ObjStoreBean" factoryMethod="getObjectStoreBrowserBean"/>
+    <bean name="ObjectStoreBrowserBean" class="com.arjuna.ats.arjuna.tools.osb.mbean.ObjStoreBrowser">
+        <property name="types" preinstantiate="false">
+            <map keyClass="java.lang.String" valueClass="java.lang.String">
+                <entry>
+                    <key>StateManager/BasicAction/TwoPhaseCoordinator/AtomicAction</key>
+                    <value>com.arjuna.ats.internal.jta.tools.osb.mbean.jta.JTAActionBean</value>
+                </entry>
+            </map>
+        </property>
 
-       <demand state="Create">ObjectStoreEnvironmentBean</demand>
     </bean>
 
     <bean name="JTAEnvironmentBean" class="com.arjuna.ats.jta.common.JTAEnvironmentBean">
+<annotation>@org.jboss.aop.microcontainer.aspects.jmx.JMX(name="jboss.jta:name=JTAEnvironmentBean", exposedInterface=com.arjuna.ats.jta.common.JTAEnvironmentBeanMBean.class, registerDirectly=true)</annotation>
 
-        <annotation>@org.jboss.aop.microcontainer.aspects.jmx.JMX(name="jboss.jta:name=JTAEnvironmentBean", exposedInterface=com.arjuna.ats.jta.common.JTAEnvironmentBeanMBean.class, registerDirectly=true)</annotation>
-
         <constructor factoryClass="com.arjuna.ats.jta.common.jtaPropertyManager" factoryMethod="getJTAEnvironmentBean"/>
 
         <property name="lastResourceOptimisationInterface">org.jboss.tm.LastResource</property>

Modified: labs/jbosstm/trunk/atsintegration/transaction-jboss-beans.xml.jts
===================================================================
--- labs/jbosstm/trunk/atsintegration/transaction-jboss-beans.xml.jts	2010-05-24 18:25:49 UTC (rev 33055)
+++ labs/jbosstm/trunk/atsintegration/transaction-jboss-beans.xml.jts	2010-05-24 18:34:15 UTC (rev 33056)
@@ -126,9 +126,19 @@
         <property name="objectStoreDir">${jboss.server.data.dir}/tx-object-store</property>
     </bean>
 
-    <bean name="ObjectStoreBrowserBean" class="com.arjuna.ats.arjuna.tools.osb.mbean.ObjStoreBean">
-        <constructor factoryClass="com.arjuna.ats.arjuna.tools.osb.mbean.ObjStoreBean" factoryMethod="getObjectStoreBrowserBean"/>
-        <demand state="Create">ObjectStoreEnvironmentBean</demand>
+    <bean name="ObjectStoreBrowserBean" class="com.arjuna.ats.arjuna.tools.osb.mbean.ObjStoreBrowser">
+        <property name="types" preinstantiate="false">
+			<map keyClass="java.lang.String" valueClass="java.lang.String">
+				<entry>
+					<key>StateManager/BasicAction/TwoPhaseCoordinator/ArjunaTransactionImple</key>
+					<value>com.arjuna.ats.arjuna.tools.osb.mbean.ActionBean</value>
+				</entry>
+				<entry>
+					<key>StateManager/BasicAction/TwoPhaseCoordinator/AtomicAction</key>
+					<value>com.arjuna.ats.internal.jta.tools.osb.mbean.jta.JTAActionBean</value>
+				</entry>
+            </map>
+        </property>
     </bean>
 
     <bean name="JTAEnvironmentBean" class="com.arjuna.ats.jta.common.JTAEnvironmentBean">



More information about the jboss-svn-commits mailing list