package org.jboss.as.ejb3.timerservice.persistence.filestore;
import org.jboss.as.ejb3.timerservice.CalendarTimer;
import org.jboss.as.ejb3.timerservice.TimerImpl;
import org.jboss.as.ejb3.timerservice.TimerServiceImpl;
import org.jboss.as.ejb3.timerservice.persistence.CalendarTimerEntity;
import org.jboss.as.ejb3.timerservice.persistence.TimerEntity;
import org.jboss.marshalling.InputStreamByteInput;
import org.jboss.marshalling.MarshallerFactory;
import org.jboss.marshalling.MarshallingConfiguration;
import org.jboss.marshalling.Unmarshaller;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import static org.jboss.as.ejb3.logging.EjbLogger.EJB3_TIMER_LOGGER;
/**
* Contains the code needed to load timers from the legacy persistent format.
*
* The old format was based on jboss marshalling, and as such it was almost impossible to maintain
* compatibility, as class changes to the serialized classes would result in old persistent timers
* being unreadable.
*
* This class will load old style timers, and then create a marker file to indicate to the system
* that these timers have already been read.
*
* @author Stuart Douglas
*/
public class LegacyFileStore {
public static final String MIGRATION_MARKER = "migrated-to-xml.marker";
static Map<String, TimerImpl> loadTimersFromFile(final String timedObjectId, final TimerServiceImpl timerService, String directory, MarshallerFactory factory, MarshallingConfiguration configuration) {
final Map<String, TimerImpl> timers = new HashMap<String, TimerImpl>();
try {
final File file = new File(directory);
if (!file.exists()) {
//no timers exist yet
return timers;
} else if (!file.isDirectory()) {
EJB3_TIMER_LOGGER.failToRestoreTimers(file);
return timers;
}
File marker = new File(file, MIGRATION_MARKER);
if (marker.exists()) {
return timers;
}
Unmarshaller unmarshaller = factory.createUnmarshaller(configuration);
for (File timerFile : file.listFiles()) {
if(timerFile.getName().endsWith(".xml")) {
continue;
}
FileInputStream in = null;
try {
in = new FileInputStream(timerFile);
unmarshaller.start(new InputStreamByteInput(in));
final TimerEntity entity = unmarshaller.readObject(TimerEntity.class);
//we load the legacy timer entity class, and turn it into a timer state
TimerImpl.Builder builder;
if (entity instanceof CalendarTimerEntity) {
CalendarTimerEntity c = (CalendarTimerEntity) entity;
builder = CalendarTimer.builder()
.setScheduleExprSecond(c.getSecond())
.setScheduleExprMinute(c.getMinute())
.setScheduleExprHour(c.getHour())
.setScheduleExprDayOfWeek(c.getDayOfWeek())
.setScheduleExprDayOfMonth(c.getDayOfMonth())
.setScheduleExprMonth(c.getMonth())
.setScheduleExprYear(c.getYear())
.setScheduleExprStartDate(c.getStartDate())
.setScheduleExprEndDate(c.getEndDate())
.setScheduleExprTimezone(c.getTimezone())
.setAutoTimer(c.isAutoTimer())
.setTimeoutMethod(CalendarTimer.getTimeoutMethod(c.getTimeoutMethod(), timerService.getTimedObjectInvoker().getValue().getClassLoader()));
} else {
builder = TimerImpl.builder();
}
builder.setId(entity.getId())
.setTimedObjectId(entity.getTimedObjectId())
.setInitialDate(entity.getInitialDate())
.setRepeatInterval(entity.getInterval())
.setNextDate(entity.getNextDate())
.setPreviousRun(entity.getPreviousRun())
.setInfo(entity.getInfo())
.setPrimaryKey(entity.getPrimaryKey())
.setTimerState(entity.getTimerState())
.setPersistent(true);
timers.put(entity.getId(), builder.build(timerService));
unmarshaller.finish();
} catch (Exception e) {
EJB3_TIMER_LOGGER.failToRestoreTimersFromFile(timerFile, e);
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
EJB3_TIMER_LOGGER.failToCloseFile(e);
}
}
}
}
if (!timers.isEmpty()) {
FileOutputStream out = new FileOutputStream(marker);
try {
out.write(new Date().toString().getBytes());
} finally {
out.close();
}
}
} catch (Exception e) {
EJB3_TIMER_LOGGER.failToRestoreTimersForObjectId(timedObjectId, e);
}
return timers;
}
}