/* ************************************************************************ # # 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.filestore.zip; public class ArchiveFile { /* extends RecordStruct implements IFileStoreFile { protected ArchiveDriver driver = null; protected ArchiveEntry file = null; protected FileInputStream input = null; protected long offset = 0; public ArchiveFile() { this.setType(Hub.instance.getSchema().getType("dciArchiveFile")); } public ArchiveFile(ArchiveDriver driver, ArchiveEntry file) { this(); this.driver = driver; this.file = file; String name = file.getName(); int pos = name.lastIndexOf('/'); this.setField("Name", (pos == -1) ? name : name.substring(pos + 1)); this.setField("Size", file.getSize()); this.setField("Modified", new DateTime(file.getLastModifiedDate())); // TODO enhance for "absolute" String cwd = driver.getFieldAsString("RootFolder"); String fpath = file.getName(); this.setField("Path", fpath.substring(cwd.length() + 1).replace('\\', '/')); this.setField("FullPath", fpath.replace('\\', '/')); this.setField("IsFolder", file.isDirectory()); } public ArchiveFile(ArchiveDriver driver, RecordStruct rec) { this(); this.driver = driver; ((RecordStruct) this).copyFields(rec); String cwd = driver.getFieldAsString("RootFolder"); this.driver.getEntry(cwd + "/" + this.getFieldAsString("Path"), new FuncCallback<ArchiveEntry>() { @Override public void callback() { ArchiveFile.this.file = this.getResult(); ArchiveFile.this.setField("Size", file.getSize()); ArchiveFile.this.setField("Modified", new DateTime(file.getLastModifiedDate())); ArchiveFile.this.setField("FullPath", file.getName().replace('\\', '/')); ArchiveFile.this.setField("IsFolder", file.isDirectory()); } }); } @Override protected void doCopy(Struct n) { super.doCopy(n); ArchiveFile nn = (ArchiveFile)n; nn.driver = this.driver; } @Override public Struct deepCopy() { ArchiveFile cp = new ArchiveFile(); this.doCopy(cp); return cp; } @Override public void dispose() { // TODO support this!!! super.dispose(); } @Override public void operation(final StackEntry stack, XElement code) { if ("Hash".equals(code.getName())) { String meth = stack.stringFromElement(code, "Method"); // TODO support other methods if (StringUtil.isEmpty(meth) || !"Sha2".equals(meth)) { // TODO log stack.resume(); return; } final Struct var = stack.refFromElement(code, "Target"); if (var instanceof ScalarStruct) { this.hash(meth, new FuncCallback<String>() { @Override public void callback() { ((ScalarStruct)var).adaptValue(this.getResult()); stack.resume(); } }); return; } else { // TODO log } stack.resume(); return; } super.operation(stack, code); } @Override public void copyTo(final OutputStream out, final OperationCallback callback) { this.getInputStream(new FuncCallback<InputStream>() { @Override public void callback() { // TODO check for errors InputStream in = this.getResult(); try { CopyUtils.copy(in, out); } catch (IOException x) { callback.error(1, "Unable to write file"); // TODO codes } finally { IOUtils.closeQuietly(in); IOUtils.closeQuietly(out); } callback.completed(); } }); } public class DestinationDriver implements IDestinationDriver { protected FileOutputStream out = null; protected ISessionStream source = null; protected Session session = null; @Override public void setSource(ISessionStream v) { this.source = v; } public DestinationDriver(Session session) { this.session = session; /* TODO try { this.out = new FileOutputStream(ArchiveFile.this.file); } catch (FileNotFoundException x) { // TODO System.out.println("Error while creating consumer"); } * / } @Override public void present(Block data) { try { if (data.isAbort()) { this.session.getAdapter().releaseSource(); this.source = null; System.out.println("Error while uploading, aborted!"); // TODO this.out.close(); return; } Memory mem = data.getData(); if (mem != null) this.out.write(mem.toArray()); if (data.isDone()) { this.out.flush(); this.out.close(); } /* TODO we need to restore this #NETTY Message rmsg = new Message(); rmsg.setField("Op", data.isDone() ? "Done" : "Next"); this.source.reaction(rmsg); // give me more * / if (data.isDone()) { this.session.getAdapter().releaseSource(); this.source = null; } } catch (IOException x) { // TODO System.out.println("Error while uploading"); } } } public class SourceDriver implements ISourceDriver { protected FileInputStream in = null; protected ISessionStream dest = null; protected long offset = 0; @Override public void setDestination(ISessionStream v) { this.dest = v; } public SourceDriver(Session session) { /* TODO try { this.in = new FileInputStream(ArchiveFile.this.file); } catch (FileNotFoundException x) { // TODO System.out.println("Error while creating consumer"); } * / } @Override public void collect(FuncCallback<Block> callback) { try { Block b = new Block(); Memory mem = new Memory(16384); // TODO config b.setData(mem); b.setOffset(this.offset); int amt = mem.copyFromStream(this.in, 16384); if (amt < 16384) { b.setDone(true); this.in.close(); } this.offset += amt; mem.setPosition(0); callback.setResult(b); } catch (IOException x) { // TODO System.out.println("Error while downloading"); } callback.completed(); } @Override public void abort() { try { this.in.close(); } catch (IOException x) { // TODO System.out.println("Error while downloading"); } } } @Override public void openRead(Session session, final FuncCallback<ISourceDriver> callback) { callback.setResult(new SourceDriver(session)); callback.completed(); } @Override public void openWrite(Session session, final FuncCallback<IDestinationDriver> callback) { callback.setResult(new DestinationDriver(session)); callback.completed(); } @Override public void hash(String method, final FuncCallback<String> callback) { // TODO support something other than Sha2 - see params this.getInputStream(new FuncCallback<InputStream>() { @Override public void callback() { callback.copyMessages(this); InputStream in = this.getResult(); if (!callback.hasErrors()) callback.setResult(HashUtil.getSha2(in)); if (in != null) IOUtils.closeQuietly(in); callback.completed(); } }); } @Override public void getInputStream(final FuncCallback<InputStream> callback) { this.driver.archive.getInputStream(new FuncCallback<InputStream>() { @Override public void callback() { // TODO dumping everything into memory not a good idea with big files - make those secure temp files try { ZipArchiveInputStream zin = new ZipArchiveInputStream(this.getResult()); // TODO not just ZIP ArchiveEntry entry = zin.getNextEntry(); String path = ArchiveFile.this.getFieldAsString("FullPath"); while(entry != null) { String ename = entry.getName(); if (ename.equals(path)) { int esize = (int) entry.getSize(); if (esize > 0) { int eleft = esize; byte[] buff = new byte[esize]; int offset = 0; // TODO sometimes it takes more than on read to get an entry - who knows why // anyway, there is probably an nicer way to do this (see also JarLibLoader) while (offset < esize) { int d = zin.read(buff, offset, eleft); offset += d; eleft -= d; } //Memory treem = new Memory(buff); //treem.setPosition(0); callback.setResult(new ByteArrayInputStream(buff)); break; } } entry = zin.getNextEntry(); } } catch (Exception x) { // TODO log } callback.completed(); } }); } @Override public String getName() { // TODO Auto-generated method stub return null; } @Override public String getPath() { // TODO Auto-generated method stub return null; } @Override public String getExtension() { // TODO Auto-generated method stub return null; } @Override public String getFullPath() { // TODO Auto-generated method stub return null; } @Override public DateTime getMofificationTime() { // TODO Auto-generated method stub return null; } @Override public long getSize() { // TODO Auto-generated method stub return 0; } @Override public boolean isFolder() { // TODO Auto-generated method stub return false; } @Override public void rename(String name, OperationCallback callback) { // TODO Auto-generated method stub } @Override public void remove(OperationCallback callback) { // TODO Auto-generated method stub } @Override public void setModificationTime(DateTime time, OperationCallback callback) { // TODO Auto-generated method stub } @Override public void getAttribute(String name, FuncCallback<Struct> callback) { // TODO Auto-generated method stub } @Override public void setAttribute(String name, Struct value, OperationCallback callback) { // TODO Auto-generated method stub } */ }