/*
* JBoss, Home of Professional Open Source.
* Copyright 2014, Red Hat Middleware LLC, and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY 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 along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package com.arjuna.ats.arjuna.tools.osb.mbean;
import javax.management.MBeanException;
import com.arjuna.ats.arjuna.common.Uid;
import com.arjuna.ats.arjuna.common.arjPropertyManager;
import com.arjuna.ats.arjuna.coordinator.AbstractRecord;
import com.arjuna.ats.arjuna.coordinator.HeuristicInformation;
import com.arjuna.ats.arjuna.coordinator.RecordList;
import com.arjuna.ats.arjuna.logging.tsLogger;
/**
* An MBean implementation for representing a participant in an Atomic Action or transaction
*
* @author Mike Musgrove
*/
/**
* @deprecated as of 5.0.5.Final In a subsequent release we will change packages names in order to
* provide a better separation between public and internal classes.
*/
@Deprecated // in order to provide a better separation between public and internal classes.
public class LogRecordWrapper extends OSEntryBean implements LogRecordWrapperMBean {
protected ActionBean parent;
protected AbstractRecord rec;
protected boolean activated;
protected ParticipantStatus listType;
protected boolean removed;
protected boolean forgetRec;
public LogRecordWrapper(Uid uid) {
super(null);
_uidWrapper.setName("jboss.jta:type=ObjectStore,itype=uninitialised,puid=" + uid.fileStringForm());
}
public LogRecordWrapper(ActionBean parent, AbstractRecord rec, ParticipantStatus listType, UidWrapper wrapper) {
super(wrapper);
init(parent, rec, listType);
}
public LogRecordWrapper(ActionBean parent, AbstractRecord rec, ParticipantStatus listType) {
this(parent, rec, listType, makeWrapper(parent, rec, LogRecordWrapper.class.getName()));
}
private static UidWrapper makeWrapper(ActionBean parent, AbstractRecord rec, String beanType) {
UidWrapper w = new UidWrapper(parent._uidWrapper.getBrowser(), beanType, rec.type(), rec.getClass().getName(), rec.order(), false);
// TODO look up the hander for rec.type() and use that to create the wrapper
w.setName(parent.getName() + ",puid=" + rec.order().fileStringForm());
return w;
}
public void init(ActionBean parent, AbstractRecord rec, ParticipantStatus listType) {
this.parent = parent;
this.rec = rec;
this.listType = listType;
_uidWrapper.setName(parent.getName() + ",puid=" + rec.order().fileStringForm());
}
public boolean isParticipant() {
return true;
}
public String getStatus() {
if (isHeuristic()) {
String type = getHeuristicStatus();
if (!type.equals(HeuristicStatus.UNKNOWN.name()))
return type;
}
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 (getListType().equals(newState))
return "participant is prepared for recovery";
/*
* Only move a heuristic to the prepared list if it hasn't already committed or rolled back
*/
if (newState.equals(ParticipantStatus.PREPARED) && getListType().equals(ParticipantStatus.HEURISTIC)) {
HeuristicStatus heuristicStatus = HeuristicStatus.valueOf(getHeuristicStatus());
if (heuristicStatus.equals(HeuristicStatus.HEURISTIC_COMMIT) ||
heuristicStatus.equals(HeuristicStatus.HEURISTIC_ROLLBACK)) {
return "participant has already committed or rolled back";
}
}
if (parent != null && parent.setStatus(this, newState)) {
listType = newState;
if (newState == ParticipantStatus.PREPARED )
return "participant recovery will be attempted during the next recovery pass";
return "participant status change was successful";
} else {
return "participant status change 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)
try {
activated = rec.activate();
} catch (Exception e) {
activated = false;
tsLogger.logger.warn("Activate of " + rec + " failed: " + e.getMessage());
}
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(_uidWrapper.getName());
}
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);
}
@Override
public String getHeuristicStatus() {
Object heuristicInformation = rec.value();
HeuristicStatus hs;
if (heuristicInformation != null && heuristicInformation instanceof HeuristicInformation) {
HeuristicInformation hi = (HeuristicInformation) heuristicInformation;
hs = HeuristicStatus.intToStatus(hi.getHeuristicType());
} else {
hs = HeuristicStatus.UNKNOWN;
}
return hs.name();
}
public String remove(boolean reprobe) throws MBeanException {
if (parent != null) {
parent.remove(this);
_uidWrapper.unregister();
if (reprobe)
_uidWrapper.probe();
}
return "Record successfully removed";
}
@Override
public String remove() throws MBeanException {
return remove(true);
}
public boolean isRemoved() {
return removed;
}
public boolean removeFromList(RecordList rl) {
if (rl != null && rl.size() > 0 && rec != null) {
boolean forgotten = forgetRec || rec.forgetHeuristic();
boolean removeAllowed = arjPropertyManager.getObjectStoreEnvironmentBean().isIgnoreMBeanHeuristics();
if (forgotten || removeAllowed) {
// remove the transaction log for the record
if (rl.remove(rec)) {
removed = true;
return true;
}
}
}
return false;
}
}