/*
* JBoss, Home of Professional Open Source.
* Copyright 2013, Red Hat, Inc., 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 org.jboss.as.test.integration.batch.common;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import javax.batch.runtime.BatchStatus;
import javax.batch.runtime.Metric;
import javax.batch.runtime.Metric.MetricType;
import javax.batch.runtime.StepExecution;
import javax.json.Json;
import javax.json.stream.JsonGenerator;
import javax.json.stream.JsonParser;
import javax.json.stream.JsonParser.Event;
/**
* @author <a href="mailto:jperkins@redhat.com">James R. Perkins</a>
*/
public class StepExecutionMarshaller {
static final String ID = "id";
static final String NAME = "name";
static final String STATUS = "status";
static final String START_TIME = "startTime";
static final String END_TIME = "endTime";
static final String EXIT_STATUS = "exitStatus";
static final String PERSISTENT_USER_DATA = "persistentUserData";
static final String METRICS = "METRICS";
private static final String METRIC = "metric";
private static final String METRIC_TYPE = "type";
private static final String METRIC_VALUE = "value";
public static String marshall(final StepExecution stepExecution) throws IOException {
final StringWriter writer = new StringWriter();
final JsonGenerator generator = Json.createGenerator(writer);
generator.writeStartObject()
.write(ID, stepExecution.getStepExecutionId())
.write(NAME, stepExecution.getStepName())
.write(STATUS, stepExecution.getBatchStatus().toString())
.write(START_TIME, stepExecution.getStartTime().getTime())
.write(END_TIME, stepExecution.getEndTime().getTime())
.write(EXIT_STATUS, stepExecution.getExitStatus())
.write(PERSISTENT_USER_DATA, serialize(stepExecution.getPersistentUserData()));
generator.writeStartObject(METRICS);
for (Metric metric : stepExecution.getMetrics()) {
generator.writeStartObject(METRIC);
generator.write(METRIC_TYPE, metric.getType().toString());
generator.write(METRIC_VALUE, metric.getValue());
generator.writeEnd();
}
generator.writeEnd();
// End main object
generator.writeEnd();
generator.close();
return writer.toString();
}
public static StepExecution unmarshall(final String json) throws IOException, ClassNotFoundException {
final JsonParser parser = Json.createParser(new StringReader(json));
final StepExecutionBuilder builder = StepExecutionBuilder.create();
String key = null;
while (parser.hasNext()) {
final Event event = parser.next();
switch (event) {
case KEY_NAME:
key = parser.getString();
break;
case VALUE_FALSE:
case VALUE_NULL:
case VALUE_NUMBER:
case VALUE_STRING:
case VALUE_TRUE:
final String value = parser.getString();
if (key == null) {
throw new IllegalStateException(String.format("No key for value '%s'. Parsing position: %s%n\t%s", value, parser.getLocation(), json));
}
switch (key) {
case ID:
if (value != null) {
builder.setId(Long.parseLong(value));
}
break;
case NAME:
builder.setName(value);
break;
case STATUS:
if (value != null) {
builder.setStatus(BatchStatus.valueOf(value));
}
break;
case EXIT_STATUS:
builder.setExitStatus(value);
break;
case END_TIME:
if (value != null) {
builder.setEndTime(Long.parseLong(value));
}
break;
case START_TIME:
if (value != null) {
builder.setStartTime(Long.parseLong(value));
}
break;
case PERSISTENT_USER_DATA:
builder.setPersistentUserData(deserialize(value));
case METRICS:
String k = null;
String metricType = null;
String metricValue = null;
while (parser.hasNext()) {
final Event e = parser.next();
switch (e) {
case KEY_NAME:
k = parser.getString();
break;
case VALUE_FALSE:
case VALUE_NULL:
case VALUE_NUMBER:
case VALUE_STRING:
case VALUE_TRUE:
if (k == null) {
throw new IllegalStateException(String.format("No key for value '%s'. Parsing position: %s%n\t%s", value, parser.getLocation(), json));
}
switch (k) {
case METRIC_TYPE:
metricType = parser.getString();
break;
case METRIC_VALUE:
metricValue = parser.getString();
break;
}
if (metricType != null && metricValue != null) {
final MetricType type = MetricType.valueOf(metricType);
final long v = Long.parseLong(parser.getString());
final Metric m = new Metric() {
@Override
public MetricType getType() {
return type;
}
@Override
public long getValue() {
return v;
}
};
builder.addMetric(m);
}
break;
}
}
break;
}
break;
}
}
parser.close();
return builder.build();
}
private static String serialize(final Serializable serializable) throws IOException {
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
final ObjectOutputStream out = new ObjectOutputStream(baos);
out.writeObject(serializable);
out.flush();
return baos.toString();
}
private static Serializable deserialize(final String data) throws IOException, ClassNotFoundException {
if (data == null) {
return null;
}
final ByteArrayInputStream bais = new ByteArrayInputStream(data.getBytes());
final ObjectInputStream in = new ObjectInputStream(bais);
return (Serializable) in.readObject();
}
static class StepExecutionBuilder {
private long id;
private String name;
private BatchStatus status;
private long startTime;
private long endTime;
private String exitStatus;
private Serializable persistentUserData;
private final Collection<Metric> metrics;
private StepExecutionBuilder() {
id = -1L;
name = null;
status = null;
startTime = 0L;
endTime = 0L;
exitStatus = null;
persistentUserData = null;
metrics = new ArrayList<Metric>();
}
public static StepExecutionBuilder create() {
return new StepExecutionBuilder();
}
public StepExecutionBuilder setId(final long id) {
this.id = id;
return this;
}
public StepExecutionBuilder setName(final String name) {
this.name = name;
return this;
}
public StepExecutionBuilder setStatus(final BatchStatus status) {
this.status = status;
return this;
}
public StepExecutionBuilder setStartTime(final long startTime) {
this.startTime = startTime;
return this;
}
public StepExecutionBuilder setEndTime(final long endTime) {
this.endTime = endTime;
return this;
}
public StepExecutionBuilder setExitStatus(final String exitStatus) {
this.exitStatus = exitStatus;
return this;
}
public StepExecutionBuilder setPersistentUserData(final Serializable persistentUserData) {
this.persistentUserData = persistentUserData;
return this;
}
public StepExecutionBuilder addMetric(final Metric metric) {
metrics.add(metric);
return this;
}
public StepExecution build() {
final long id = this.id;
final String name = this.name;
final BatchStatus status = this.status;
final long startTime = this.startTime;
final long endTime = this.endTime;
final String exitStatus = this.exitStatus;
final Serializable persistentUserData = this.persistentUserData;
final Metric[] metrics = this.metrics.toArray(new Metric[this.metrics.size()]);
return new StepExecution() {
@Override
public long getStepExecutionId() {
return id;
}
@Override
public String getStepName() {
return name;
}
@Override
public BatchStatus getBatchStatus() {
return status;
}
@Override
public Date getStartTime() {
return new Date(startTime);
}
@Override
public Date getEndTime() {
return new Date(endTime);
}
@Override
public String getExitStatus() {
return exitStatus;
}
@Override
public Serializable getPersistentUserData() {
return persistentUserData;
}
@Override
public Metric[] getMetrics() {
return Arrays.copyOf(metrics, metrics.length);
}
};
}
}
}