![JAR search and dependency download from the Maven repository](/logo.png)
es.ree.eemws.kit.folders.InputTask Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of eemws-kit Show documentation
Show all versions of eemws-kit Show documentation
Client implementation of IEC 62325-504 technical specification. eemws-kit includes command line utilities to invoke the eem web services, as well as several GUI applications (browser, editor, ...)
The newest version!
/*
* Copyright 2024 Redeia.
*
* This program 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, version 3 of the license.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTIBIILTY or FITNESS FOR A PARTICULAR PURPOSE. See GNU Lesser General
* Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program. If not, see
* http://www.gnu.org/licenses/.
*
* Any redistribution and/or modification of this program has to make
* reference to Redeia as the copyright owner of the program.
*/
package es.ree.eemws.kit.folders;
import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;
import es.ree.eemws.client.put.PutMessage;
import es.ree.eemws.core.utils.error.EnumErrorCatalog;
import es.ree.eemws.core.utils.file.FileUtil;
import es.ree.eemws.core.utils.iec61968100.EnumMessageStatus;
import es.ree.eemws.core.utils.iec61968100.FaultUtil;
import es.ree.eemws.core.utils.operations.put.PutOperationException;
import es.ree.eemws.core.utils.xml.XMLElementUtil;
import jakarta.xml.bind.JAXBException;
/**
* InputTask. Checks for files in the input folder, read them and send to the
* server.
*
* @author Redeia.
* @version 2.1 01/01/2024
*/
public final class InputTask implements Runnable {
/** Prefix added to identify response files. */
private static final String RESPONSE_ID_PREFIX = "ack_"; //$NON-NLS-1$
/** Object for checking messages sent by another module. */
private final LockHandler lh;
/** Put message operation object. */
private PutMessage putMessage;
/** This input task configuration set. */
private InputConfigurationSet ics;
/** This input set index (get it instead of asking ics each time). */
private int icsIndex;
/** Thread log system. */
private static final Logger LOGGER = Logger.getLogger(InputTask.class.getName());
/** Number of millisconds between file size checks. */
private static final long SLEEP_BETWEEN_READS = 500;
/**
* Creates a Input task in order to sent the files in the configured folder to a
* server.
*
* @param lockHandler Lock manager to synchronize the work.
* @param ic This task configuration set.
*/
public InputTask(final LockHandler lockHandler, final InputConfigurationSet ic) {
lh = lockHandler;
ics = ic;
icsIndex = ics.getIndex();
putMessage = new PutMessage();
putMessage.setEndPoint(ic.getInputUrlEndPoint());
if (LOGGER.isLoggable(Level.INFO)) {
LOGGER.info(ic.toString());
}
}
/**
* Checks whether the given file is complete. Checks file size, waits for a
* while and checks its size again. If the size remains the same, the file is
* considered to be complete.
*
* @param file Reference to the input file.
* @return true
When complete, false
otherwise.
*/
private boolean isComplete(final File file) {
var initialSize = file.length();
long finalSize;
var complete = false;
if (initialSize > 0) {
try {
Thread.sleep(SLEEP_BETWEEN_READS);
} catch (InterruptedException e) {
LOGGER.finer("Wait interrupted"); // Don't mind! //$NON-NLS-1$
Thread.currentThread().interrupt();
}
finalSize = file.length();
complete = (finalSize == initialSize);
}
return complete;
}
/**
* Detects files in input folder. Sends them to the server
*/
@Override
public void run() {
String fileName = null;
try {
var f = new File(ics.getInputFolder());
var files = f.listFiles();
if (files != null) {
boolean lockFile;
StatusIcon.getStatus().setBusy();
for (File file : files) {
fileName = file.getName();
lockFile = lh.tryLock(fileName);
if (lockFile && isComplete(file)) {
process(file);
}
lh.releaseLock(fileName);
}
StatusIcon.getStatus().setIdle();
}
} catch (Exception ex) {
/*
* Defensive exception, if runnable task ends with exception won't be exectued
* againg!
*/
LOGGER.log(Level.SEVERE, MessageCatalog.MF_UNEXPECTED_ERROR_I.getMessage(icsIndex), ex);
} finally {
if (fileName != null) {
lh.releaseLock(fileName);
}
}
}
/**
* Process file with name and contents passed as arguments.
*
* @param file Reference to the input file.
*/
private void process(final File file) {
var fileName = file.getName();
var fullFileName = file.getAbsolutePath();
try {
/* Send. */
if (LOGGER.isLoggable(Level.INFO)) {
LOGGER.info(MessageCatalog.MF_SENDING_MESSAGE.getMessage(icsIndex, fileName));
}
StringBuilder response;
if (ics.isBinaryFolder()) {
response = new StringBuilder(putMessage.put(fileName, FileUtil.readBinary(fullFileName)));
} else {
response = new StringBuilder(putMessage.put(new StringBuilder(FileUtil.readUTF8(fullFileName))));
}
if (LOGGER.isLoggable(Level.INFO)) {
LOGGER.info(MessageCatalog.MF_SENT_MESSAGE.getMessage(icsIndex, fileName));
}
moveOnceProcessed(file);
saveAndExecuteAck(file, response);
} catch (PutOperationException ex) {
/* Set status as failed, this is an exception!. */
putMessage.getMessageMetaData().setStatus(EnumMessageStatus.FAILED);
var code = ex.getCode();
/* Soap Fault, save the fault message. */
if (code.equals(EnumErrorCatalog.HAND_010.name())) {
LOGGER.severe(MessageCatalog.MF_SERVER_RETURNS_FAULT.getMessage(icsIndex, fullFileName,
ex.getCause().getMessage()));
saveAndExecuteAck(file, new StringBuilder(putMessage.getMessageMetaData().getRejectText()));
} else {
/* Magic folder needs a file, build a "fake" fault using the exception. */
try {
var fault = XMLElementUtil.element2String(XMLElementUtil
.obj2Element(FaultUtil.getFaultMessageFromException(ex.getMessage(), ex.getCode())));
saveAndExecuteAck(file, new StringBuilder(fault));
} catch (TransformerException | ParserConfigurationException | JAXBException e) {
LOGGER.log(Level.SEVERE, MessageCatalog.MF_CANNOT_CREATE_FAULT_MSG.getMessage(icsIndex), e);
}
if (code.equals(EnumErrorCatalog.PUT_014.name())) {
LOGGER.log(Level.SEVERE, MessageCatalog.MF_RETURNS_ERROR.getMessage(icsIndex, fullFileName), ex);
} else {
LOGGER.log(Level.SEVERE, MessageCatalog.MF_SERVER_RETURNS_ERROR.getMessage(icsIndex, fullFileName),
ex);
}
}
moveOnceProcessed(file);
} catch (IOException ioe) {
LOGGER.log(Level.SEVERE, MessageCatalog.MF_CANNOT_READ_FILE.getMessage(icsIndex, fullFileName), ioe);
}
}
/**
* Moves (copy + delete) the input file to the processed folder (if configured)
* once the file is sent. Depending on the java version, if source and
* destination are in different filesystems, move is not possible (so that, this
* is implemented as copy + delete)
*
* @param file Input file to be moved.
*/
private void moveOnceProcessed(final File file) {
var execContext = ""; //$NON-NLS-1$
try {
var fileName = file.getName();
var fullFileName = file.getAbsolutePath();
if (ics.getProcessedFolder() != null) {
var processedFilePath = ics.getProcessedFolder() + File.separator + fileName;
execContext = MessageCatalog.MF_SAVING_PROCESS_FOLDER.getMessage(icsIndex, fullFileName,
processedFilePath);
FileUtil.writeUTF8(processedFilePath, FileUtil.readUTF8(fullFileName));
}
execContext = MessageCatalog.MF_UNABLE_TO_DELETE_INPUT_FILE.getMessage(icsIndex, fullFileName);
var f = new File(fullFileName);
if (!f.delete()) {
LOGGER.warning(execContext);
}
} catch (IOException ioe) {
LOGGER.log(Level.SEVERE, execContext, ioe);
}
}
/**
* Saves the given ack (could be a fault) into the configured ack folder(s).
* Then runs the configured scripts / programs
*
* @param file Input file name (for log purposes)
* @param response Server response as string.
*/
private void saveAndExecuteAck(final File file, final StringBuilder response) {
var execContext = ""; //$NON-NLS-1$
var fileName = file.getName();
var fullFileName = file.getAbsolutePath();
try {
String ackFilePath = null;
EnumMessageStatus status;
/* Response is saved in response folder. */
if (ics.getAckFolder() != null) {
ackFilePath = ics.getAckFolder() + File.separator + RESPONSE_ID_PREFIX + fileName;
execContext = MessageCatalog.MF_SAVING_ACK_FOLDER.getMessage(icsIndex, fullFileName, ackFilePath);
FileUtil.writeUTF8(ackFilePath, response.toString());
}
var metaData = putMessage.getMessageMetaData();
status = metaData.getStatus();
if (status == null) {
status = EnumMessageStatus.OK;
}
if (status.equals(EnumMessageStatus.OK)) {
/* Response is saved in response OK folder. */
if (ics.getAckOkFolder() != null) {
ackFilePath = ics.getAckOkFolder() + File.separator + RESPONSE_ID_PREFIX + fileName;
execContext = MessageCatalog.MF_SAVING_ACK_OK_FOLDER.getMessage(icsIndex, fullFileName,
ackFilePath);
FileUtil.writeUTF8(ackFilePath, response.toString());
}
} else /* Response is saved in response FAILED folder. */
if (ics.getAckFailedFolder() != null) {
ackFilePath = ics.getAckFailedFolder() + File.separator + RESPONSE_ID_PREFIX + fileName;
execContext = MessageCatalog.MF_SAVING_ACK_FAILED_FOLDER.getMessage(icsIndex, fullFileName,
ackFilePath);
FileUtil.writeUTF8(ackFilePath, response.toString());
}
/* If ack was saved and there is a program configured, run it... */
if (ackFilePath != null) {
if (status.equals(EnumMessageStatus.OK)) {
if (ics.getAckOkProgramCmdLine() != null) {
ProgramExecutor.execute(ics.getAckOkProgramCmdLine(), new File(ackFilePath), status.toString(),
null);
}
} else if (ics.getAckFailedProgramCmdLine() != null) {
ProgramExecutor.execute(ics.getAckFailedProgramCmdLine(), new File(ackFilePath), status.toString(),
null);
}
}
} catch (IOException ex) {
LOGGER.log(Level.SEVERE, execContext, ex);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy