/**
* Copyright 2014 SAP AG
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.aim.artifacts.measurement.collector;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Properties;
import org.aim.api.exceptions.MeasurementException;
import org.aim.api.measurement.AbstractRecord;
import org.aim.api.measurement.MeasurementData;
import org.aim.api.measurement.collector.AbstractDataSource;
import org.aim.logging.AIMLogger;
import org.aim.logging.AIMLoggerFactory;
/**
* The {@link FileDataSource} writes collected monitoring records to a CSV file
* on the hard disk.
*
* @author Alexander Wert
*
*/
public class FileDataSource extends AbstractDataSource {
private static final AIMLogger LOGGER = AIMLoggerFactory.getLogger(FileDataSource.class);
/**
* Property key for the sink directory (directory where to write the CSV
* files).
*/
public static final String SINK_DIRECTORY = "org.aim.fileDataSource.sinkDirectory";
public static final String FILE_PREFIX = "LPE-Collector";
public static final String ADDITIONAL_FILE_PREFIX_KEY = "org.lpe.measurement.fileWriter.prefix";
private static final String LINE_SEPARATOR = System.getProperty("line.separator");
private FileReader fileReader;
private Writer fileWriter = null;
private String pathToFile = null;
private String sink;
private String prefix;
@Override
protected void process(AbstractRecord record) {
try {
fileWriter.append(record.toString());
fileWriter.append(LINE_SEPARATOR);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Override
protected void cleanUp() {
try {
fileWriter.flush();
fileWriter.close();
} catch (IOException e) {
LOGGER.error("Monitoring error! Reason: {}", e);
}
}
@Override
protected void init() throws MeasurementException {
LOGGER.debug("Initializing file writer ...");
removePreviousFile();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss-mm");
Date resultdate = new Date(System.currentTimeMillis());
sink = pathToFile + FILE_PREFIX + "_" + prefix + "_" + this.getClass().getSimpleName() + "_"
+ sdf.format(resultdate) + ".txt";
try {
fileWriter = new FileWriter(sink);
} catch (IOException e) {
throw new MeasurementException("Measurement error! Failed creating FileDataWriter.", e);
}
LOGGER.debug("data sink: {}", sink);
LOGGER.debug("File writer initialized");
}
/**
* Removes collector files from previous monitoring phase.
*/
private void removePreviousFile() {
if (sink == null) {
return;
}
File file = new File(sink);
if (file.exists() && file.canWrite()) {
file.delete();
}
}
/**
* Reads monitoring data from the CSV file.
*
* @return A list of records wrapped in the {@link MeasurementData} object
*
* @throws MeasurementException
* thrown if data cannot be read from the data sink
*/
@Override
public MeasurementData read() throws MeasurementException {
try {
if (sink == null) {
throw new MeasurementException("Sink is not specified!");
}
List<AbstractRecord> result = new ArrayList<AbstractRecord>();
fileReader = new FileReader(sink);
BufferedReader bReader = new BufferedReader(fileReader);
String line = bReader.readLine();
while (line != null) {
AbstractRecord record = AbstractRecord.fromString(line);
if (record != null) {
result.add(record);
}
line = bReader.readLine();
}
MeasurementData data = new MeasurementData();
data.setRecords(result);
return data;
} catch (IOException e) {
throw new MeasurementException("Failed reading measurement data!", e);
} finally {
if (fileReader != null) {
try {
fileReader.close();
} catch (IOException e) {
throw new MeasurementException(e);
}
}
}
}
@Override
public void pipeToOutputStream(OutputStream oStream) throws MeasurementException {
if (sink == null) {
throw new MeasurementException("Sink is not specified!");
}
BufferedReader br = null;
BufferedWriter writer = null;
try {
FileReader fReader = new FileReader(sink);
br = new BufferedReader(fReader, BUFFER_SIZE);
writer = new BufferedWriter(new OutputStreamWriter(oStream), BUFFER_SIZE);
String line;
while ((line = br.readLine()) != null) {
writer.write(line);
writer.newLine();
}
writer.flush();
} catch (IOException e) {
throw new MeasurementException(e);
} finally {
try {
if (br != null) {
br.close();
}
if (writer != null) {
writer.close();
}
} catch (IOException e) {
throw new MeasurementException(e);
}
}
}
@Override
public void initialize(Properties properties) {
String tmpPrefix = null;
if (properties != null) {
this.pathToFile = properties.getProperty(SINK_DIRECTORY);
tmpPrefix = properties.getProperty(ADDITIONAL_FILE_PREFIX_KEY);
}
prefix = tmpPrefix == null ? "" : tmpPrefix;
if (pathToFile == null || pathToFile.isEmpty()) {
pathToFile = System.getProperty("java.io.tmpdir");
}
if (!pathToFile.endsWith(System.getProperty("file.separator"))) {
pathToFile = pathToFile + System.getProperty("file.separator");
}
LOGGER.debug("Created data collector. Writing data to directory: {}", pathToFile);
}
}