/* ************************************************************************
#
# DivConq
#
# http://divconq.com/
#
# Copyright:
# Copyright 2014 eTimeline, LLC. All rights reserved.
#
# License:
# See the license.txt file in the project's top-level directory for details.
#
# Authors:
# * Andy White
#
************************************************************************ */
package divconq.script.inst.file;
import divconq.ctp.stream.FileSourceStream;
import divconq.ctp.stream.FunnelStream;
import divconq.ctp.stream.GzipStream;
import divconq.ctp.stream.IStreamDest;
import divconq.ctp.stream.IStreamSource;
import divconq.ctp.stream.JoinStream;
import divconq.ctp.stream.NullStream;
import divconq.ctp.stream.PgpEncryptStream;
import divconq.ctp.stream.SplitStream;
import divconq.ctp.stream.StreamWork;
import divconq.ctp.stream.TarStream;
import divconq.ctp.stream.UngzipStream;
import divconq.ctp.stream.UntarStream;
import divconq.filestore.IFileCollection;
import divconq.filestore.IFileStoreDriver;
import divconq.filestore.IFileStoreFile;
import divconq.hub.Hub;
import divconq.lang.op.OperationCallback;
import divconq.lang.op.OperationContext;
import divconq.script.Ops;
import divconq.script.StackEntry;
import divconq.struct.Struct;
import divconq.struct.scalar.NullStruct;
import divconq.struct.scalar.StringStruct;
import divconq.util.StringUtil;
import divconq.work.IWork;
import divconq.work.Task;
import divconq.work.TaskRun;
import divconq.xml.XElement;
public class FileOps extends Ops {
@Override
public void prepTarget(StackEntry stack) {
this.nextOpResume(stack);
}
@Override
public void runOp(StackEntry stack, XElement op, Struct target) {
if ("Copy".equals(op.getName()))
this.copy(stack, op);
else if ("XCopy".equals(op.getName()))
this.xcopy(stack, op);
else if ("Tar".equals(op.getName()))
this.injectStream(stack, op, new TarStream());
else if ("Untar".equals(op.getName()))
this.injectStream(stack, op, new UntarStream());
else if ("Gzip".equals(op.getName()))
this.injectStream(stack, op, new GzipStream());
else if ("Ungzip".equals(op.getName()))
this.injectStream(stack, op, new UngzipStream());
else if ("Funnel".equals(op.getName()))
this.injectStream(stack, op, new FunnelStream());
else if ("Split".equals(op.getName()))
this.injectStream(stack, op, new SplitStream());
else if ("Join".equals(op.getName()))
this.injectStream(stack, op, new JoinStream());
else if ("PGPEncrypt".equals(op.getName()))
this.injectStream(stack, op, new PgpEncryptStream());
else {
OperationContext.get().error("Unknown FileOp: " + op.getName());
this.nextOpResume(stack);
}
}
protected void copy(StackEntry stack, XElement el) {
IStreamSource streamin = this.getSourceStream(stack, el);
if (streamin != null)
this.executeDest(stack, el, streamin, false, true);
}
protected void xcopy(StackEntry stack, XElement el) {
IStreamSource streamin = this.getSourceStream(stack, el);
if (streamin != null)
this.executeDest(stack, el, streamin, true, true);
}
protected void injectStream(StackEntry stack, XElement el, IStreamSource add) {
IStreamSource streamin = this.getSourceStream(stack, el);
if (streamin == null)
return;
add.init(stack, el);
add.setUpstream(streamin);
this.registerSourceStream(stack, el, add);
this.executeDest(stack, el, add, true, false);
}
protected IStreamSource getSourceStream(StackEntry stack, XElement el) {
Struct src = stack.refFromElement(el, "Source");
if ((src == null) || (src instanceof NullStruct)) {
src = stack.queryVariable("_LastStream");
if ((src == null) || (src instanceof NullStruct)) {
OperationContext.get().error("Missing source");
this.nextOpResume(stack);
return null;
}
}
if (src instanceof IStreamSource)
return (IStreamSource) src;
if (!(src instanceof IFileStoreFile) && !(src instanceof IFileStoreDriver) && !(src instanceof IFileCollection)) {
OperationContext.get().error("Invalid source type");
this.nextOpResume(stack);
return null;
}
IStreamSource filesrc = null;
if (src instanceof IFileStoreFile)
filesrc = ((IFileStoreFile)src).allocSrc();
else if (src instanceof IFileStoreDriver)
filesrc = ((IFileStoreDriver)src).rootFolder().allocSrc();
else
filesrc = new FileSourceStream((IFileCollection) src);
if (filesrc == null) {
OperationContext.get().error("Invalid source type");
this.nextOpResume(stack);
return null;
}
filesrc.init(stack, el);
return filesrc;
}
protected IStreamDest getDestStream(StackEntry stack, XElement el, boolean autorelative) {
Struct dest = stack.refFromElement(el, "Dest");
if ((dest == null) || (dest instanceof NullStruct))
return null;
if ((dest instanceof StringStruct) && "NULL".equals(((StringStruct)dest).getValue()))
return new NullStream();
if (dest instanceof IStreamDest)
return (IStreamDest) dest;
if (!(dest instanceof IFileStoreFile) && !(dest instanceof IFileStoreDriver)) {
OperationContext.get().error("Invalid dest type");
this.nextOpResume(stack);
return null;
}
IStreamDest deststrm = null;
if (dest instanceof IFileStoreDriver)
deststrm = ((IFileStoreDriver)dest).rootFolder().allocDest();
else
deststrm = ((IFileStoreFile)dest).allocDest();
if (deststrm == null) {
OperationContext.get().error("Unable to create destination stream");
this.nextOpResume(stack);
return null;
}
deststrm.init(stack, el, autorelative);
return deststrm;
}
protected void executeDest(StackEntry stack, XElement el, IStreamSource src, boolean autorelative, boolean destRequired) {
stack.addVariable("_LastStream", (Struct)src);
IStreamDest streamout = this.getDestStream(stack, el, autorelative);
if (streamout != null) {
streamout.setUpstream(src);
IWork sw = new StreamWork(streamout);
Task t = Task.subtask(OperationContext.get().getTaskRun(), "Streaming", new OperationCallback() {
@Override
public void callback() {
FileOps.this.nextOpResume(stack);
return;
}
});
t.withWork(sw);
TaskRun run = new TaskRun(t);
run.addCloseable(streamout);
Hub.instance.getWorkPool().submit(run);
}
else {
if (destRequired)
OperationContext.get().error("Missing dest for " + el.getName());
this.nextOpResume(stack);
return;
}
}
protected void registerSourceStream(StackEntry stack, XElement el, IStreamSource src) {
String name = stack.stringFromElement(el, "Name");
if (StringUtil.isEmpty(name))
name = "Stream_" + stack.getActivity().tempVarName();
// to be sure we cleanup the stream, all variables added will later be disposed of
stack.addVariable(name, (Struct)src);
}
@Override
public void cancel(StackEntry stack) {
// TODO review after we make operations
}
}