blob: e16f7aa794eeb6e8a7eec8abde3cf78ceb4cff75 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.apache.hop.workflow.actions.checkfilelocked;
import org.apache.commons.vfs2.FileObject;
import org.apache.commons.vfs2.FileSelectInfo;
import org.apache.commons.vfs2.FileSelector;
import org.apache.commons.vfs2.FileType;
import org.apache.hop.core.Const;
import org.apache.hop.core.ICheckResult;
import org.apache.hop.core.Result;
import org.apache.hop.core.RowMetaAndData;
import org.apache.hop.core.annotations.Action;
import org.apache.hop.core.exception.HopException;
import org.apache.hop.core.exception.HopXmlException;
import org.apache.hop.core.util.Utils;
import org.apache.hop.core.variables.IVariables;
import org.apache.hop.core.vfs.HopVfs;
import org.apache.hop.core.xml.XmlHandler;
import org.apache.hop.i18n.BaseMessages;
import org.apache.hop.metadata.api.IHopMetadataProvider;
import org.apache.hop.workflow.WorkflowMeta;
import org.apache.hop.workflow.action.ActionBase;
import org.apache.hop.workflow.action.IAction;
import org.apache.hop.workflow.action.validator.AbstractFileValidator;
import org.apache.hop.workflow.action.validator.ActionValidatorUtils;
import org.apache.hop.workflow.action.validator.AndValidator;
import org.apache.hop.workflow.action.validator.ValidatorContext;
import org.w3c.dom.Node;
import java.io.IOException;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* This defines a 'check files locked' action.
*
* @author Samatar Hassan
* @since 06-05-2007
*/
@Action(
id = "CHECK_FILES_LOCKED",
name = "i18n::ActionCheckFilesLocked.Name",
description = "i18n::ActionCheckFilesLocked.Description",
image = "CheckFilesLocked.svg",
categoryDescription = "i18n:org.apache.hop.workflow:ActionCategory.Category.Conditions",
documentationUrl = "https://hop.apache.org/manual/latest/workflow/actions/checkfilelocked.html")
public class ActionCheckFilesLocked extends ActionBase implements Cloneable, IAction {
private static final Class<?> PKG = ActionCheckFilesLocked.class; // For Translator
public boolean argFromPrevious;
public boolean includeSubfolders;
public String[] arguments;
public String[] filemasks;
private boolean oneFileLocked;
public ActionCheckFilesLocked(String n) {
super(n, "");
argFromPrevious = false;
arguments = null;
includeSubfolders = false;
}
public ActionCheckFilesLocked() {
this("");
}
public Object clone() {
ActionCheckFilesLocked je = (ActionCheckFilesLocked) super.clone();
if (arguments != null) {
int nrFields = arguments.length;
je.allocate(nrFields);
System.arraycopy(arguments, 0, je.arguments, 0, nrFields);
System.arraycopy(filemasks, 0, je.filemasks, 0, nrFields);
}
return je;
}
public void allocate(int nrFields) {
arguments = new String[nrFields];
filemasks = new String[nrFields];
}
public String getXml() {
StringBuilder xml = new StringBuilder(300);
xml.append(super.getXml());
xml.append(" ").append(XmlHandler.addTagValue("arg_from_previous", argFromPrevious));
xml.append(" ").append(XmlHandler.addTagValue("include_subfolders", includeSubfolders));
xml.append(" <fields>").append(Const.CR);
if (arguments != null) {
for (int i = 0; i < arguments.length; i++) {
xml.append(" <field>").append(Const.CR);
xml.append(" ").append(XmlHandler.addTagValue("name", arguments[i]));
xml.append(" ").append(XmlHandler.addTagValue("filemask", filemasks[i]));
xml.append(" </field>").append(Const.CR);
}
}
xml.append(" </fields>").append(Const.CR);
return xml.toString();
}
public void loadXml(Node entrynode, IHopMetadataProvider metadataProvider, IVariables variables)
throws HopXmlException {
try {
super.loadXml(entrynode);
argFromPrevious =
"Y".equalsIgnoreCase(XmlHandler.getTagValue(entrynode, "arg_from_previous"));
includeSubfolders =
"Y".equalsIgnoreCase(XmlHandler.getTagValue(entrynode, "include_subfolders"));
Node fields = XmlHandler.getSubNode(entrynode, "fields");
// How many field arguments?
int nrFields = XmlHandler.countNodes(fields, "field");
allocate(nrFields);
// Read them all...
for (int i = 0; i < nrFields; i++) {
Node fnode = XmlHandler.getSubNodeByNr(fields, "field", i);
arguments[i] = XmlHandler.getTagValue(fnode, "name");
filemasks[i] = XmlHandler.getTagValue(fnode, "filemask");
}
} catch (HopXmlException xe) {
throw new HopXmlException(
BaseMessages.getString(PKG, "ActionCheckFilesLocked.UnableToLoadFromXml"), xe);
}
}
public Result execute(Result previousResult, int nr) {
Result result = previousResult;
List<RowMetaAndData> rows = result.getRows();
RowMetaAndData resultRow = null;
oneFileLocked = false;
result.setResult(true);
try {
if (argFromPrevious) {
if (isDetailed()) {
logDetailed(
BaseMessages.getString(
PKG,
"ActionCheckFilesLocked.FoundPreviousRows",
String.valueOf((rows != null ? rows.size() : 0))));
}
}
if (argFromPrevious && rows != null) {
// Copy the input row to the (command line) arguments
for (int iteration = 0;
iteration < rows.size() && !parentWorkflow.isStopped();
iteration++) {
resultRow = rows.get(iteration);
// Get values from previous result
String fileFolderPrevious = resultRow.getString(0, "");
String fileMasksPrevious = resultRow.getString(1, "");
// ok we can process this file/folder
if (isDetailed()) {
logDetailed(
BaseMessages.getString(
PKG,
"ActionCheckFilesLocked.ProcessingRow",
fileFolderPrevious,
fileMasksPrevious));
}
ProcessFile(fileFolderPrevious, fileMasksPrevious);
}
} else if (arguments != null) {
for (int i = 0; i < arguments.length && !parentWorkflow.isStopped(); i++) {
// ok we can process this file/folder
if (isDetailed()) {
logDetailed(
BaseMessages.getString(
PKG, "ActionCheckFilesLocked.ProcessingArg", arguments[i], filemasks[i]));
}
ProcessFile(arguments[i], filemasks[i]);
}
}
if (oneFileLocked) {
result.setResult(false);
result.setNrErrors(1);
}
} catch (Exception e) {
logError(BaseMessages.getString(PKG, "ActionCheckFilesLocked.ErrorRunningAction", e));
}
return result;
}
private void ProcessFile(String filename, String wildcard) {
FileObject filefolder = null;
String realFilefoldername = resolve(filename);
String realwilcard = resolve(wildcard);
try {
filefolder = HopVfs.getFileObject(realFilefoldername);
FileObject[] files = new FileObject[] {filefolder};
if (filefolder.exists()) {
// the file or folder exists
if (filefolder.getType() == FileType.FOLDER) {
// It's a folder
if (isDetailed()) {
logDetailed(
BaseMessages.getString(
PKG, "ActionCheckFilesLocked.ProcessingFolder", realFilefoldername));
}
// Retrieve all files
files = filefolder.findFiles(new TextFileSelector(filefolder.toString(), realwilcard));
if (isDetailed()) {
logDetailed(
BaseMessages.getString(
PKG, "ActionCheckFilesLocked.TotalFilesToCheck", String.valueOf(files.length)));
}
} else {
// It's a file
if (isDetailed()) {
logDetailed(
BaseMessages.getString(
PKG, "ActionCheckFilesLocked.ProcessingFile", realFilefoldername));
}
}
// Check files locked
checkFilesLocked(files);
} else {
// We can not find thsi file
logBasic(
BaseMessages.getString(PKG, "ActionCheckFilesLocked.FileNotExist", realFilefoldername));
}
} catch (Exception e) {
logError(
BaseMessages.getString(
PKG, "ActionCheckFilesLocked.CouldNotProcess", realFilefoldername, e.getMessage()));
} finally {
if (filefolder != null) {
try {
filefolder.close();
} catch (IOException ex) {
// Ignore
}
}
}
}
private void checkFilesLocked(FileObject[] files) throws HopException {
for (int i = 0; i < files.length && !oneFileLocked; i++) {
FileObject file = files[i];
String filename = HopVfs.getFilename(file);
LockFile locked = new LockFile(filename);
if (locked.isLocked()) {
oneFileLocked = true;
logError(BaseMessages.getString(PKG, "ActionCheckFilesLocked.Log.FileLocked", filename));
} else {
if (isDetailed()) {
logDetailed(
BaseMessages.getString(PKG, "ActionCheckFilesLocked.Log.FileNotLocked", filename));
}
}
}
}
private class TextFileSelector implements FileSelector {
String fileWildcard = null;
String sourceFolder = null;
public TextFileSelector(String sourcefolderin, String filewildcard) {
if (!Utils.isEmpty(sourcefolderin)) {
sourceFolder = sourcefolderin;
}
if (!Utils.isEmpty(filewildcard)) {
fileWildcard = filewildcard;
}
}
public boolean includeFile(FileSelectInfo info) {
boolean returncode = false;
FileObject filename = null;
try {
if (!info.getFile().toString().equals(sourceFolder)) {
// Pass over the Base folder itself
String shortFilename = info.getFile().getName().getBaseName();
if (!info.getFile().getParent().equals(info.getBaseFolder())) {
// Not in the Base Folder..Only if include sub folders
if (includeSubfolders
&& (info.getFile().getType() == FileType.FILE)
&& GetFileWildcard(shortFilename, fileWildcard)) {
if (isDetailed()) {
logDetailed(
BaseMessages.getString(
PKG, "ActionCheckFilesLocked.CheckingFile", info.getFile().toString()));
}
returncode = true;
}
} else {
// In the Base Folder...
if ((info.getFile().getType() == FileType.FILE)
&& GetFileWildcard(shortFilename, fileWildcard)) {
if (isDetailed()) {
logDetailed(
BaseMessages.getString(
PKG, "ActionCheckFilesLocked.CheckingFile", info.getFile().toString()));
}
returncode = true;
}
}
}
} catch (Exception e) {
logError(
BaseMessages.getString(PKG, "ActionCheckFilesLocked.Error.Exception.ProcessError"),
BaseMessages.getString(
PKG,
"JobCheckFilesLocked.Error.Exception.Process",
info.getFile().toString(),
e.getMessage()));
returncode = false;
} finally {
if (filename != null) {
try {
filename.close();
} catch (IOException ex) {
/* Ignore */
}
}
}
return returncode;
}
public boolean traverseDescendents(FileSelectInfo info) {
return info.getDepth() == 0 || includeSubfolders;
}
}
/**********************************************************
*
* @param selectedfile
* @param wildcard
* @return True if the selectedfile matches the wildcard
**********************************************************/
private boolean GetFileWildcard(String selectedfile, String wildcard) {
Pattern pattern = null;
boolean getIt = true;
if (!Utils.isEmpty(wildcard)) {
pattern = Pattern.compile(wildcard);
// First see if the file matches the regular expression!
if (pattern != null) {
Matcher matcher = pattern.matcher(selectedfile);
getIt = matcher.matches();
}
}
return getIt;
}
public void setIncludeSubfolders(boolean includeSubfolders) {
this.includeSubfolders = includeSubfolders;
}
public void setargFromPrevious(boolean argFromPrevious) {
this.argFromPrevious = argFromPrevious;
}
public boolean isEvaluation() {
return true;
}
public boolean isArgFromPrevious() {
return argFromPrevious;
}
public String[] getArguments() {
return arguments;
}
public String[] getFilemasks() {
return filemasks;
}
public boolean isIncludeSubfolders() {
return includeSubfolders;
}
public void check(
List<ICheckResult> remarks,
WorkflowMeta workflowMeta,
IVariables variables,
IHopMetadataProvider metadataProvider) {
boolean res =
ActionValidatorUtils.andValidator()
.validate(
this,
"arguments",
remarks,
AndValidator.putValidators(ActionValidatorUtils.notNullValidator()));
if (res == false) {
return;
}
ValidatorContext ctx = new ValidatorContext();
AbstractFileValidator.putVariableSpace(ctx, getVariables());
AndValidator.putValidators(
ctx, ActionValidatorUtils.notNullValidator(), ActionValidatorUtils.fileExistsValidator());
for (int i = 0; i < arguments.length; i++) {
ActionValidatorUtils.andValidator().validate(this, "arguments[" + i + "]", remarks, ctx);
}
}
}