X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=unused%2Fjavajs%2Futil%2FOC.java;fp=unused%2Fjavajs%2Futil%2FOC.java;h=a63489cfe10a793d05243ca565cc5589f563467c;hb=65740880573a48adc758bec3939ece9d9ae104dd;hp=0000000000000000000000000000000000000000;hpb=71aa78b8a7d54e5aeb6b278310dfd735efb77477;p=jalview.git diff --git a/unused/javajs/util/OC.java b/unused/javajs/util/OC.java new file mode 100644 index 0000000..a63489c --- /dev/null +++ b/unused/javajs/util/OC.java @@ -0,0 +1,451 @@ +package javajs.util; + +import java.io.BufferedWriter; +import java.io.ByteArrayOutputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +import javajs.api.BytePoster; +import javajs.api.GenericOutputChannel; +import javajs.api.js.J2SObjectInterface; + +/** + * + * A generic output method. JmolOutputChannel can be used to: + * + * add characters to a StringBuffer + * using fileName==null, append() and toString() + * + * add bytes utilizing ByteArrayOutputStream + * using writeBytes(), writeByteAsInt(), append()*, and bytesAsArray() + * *append() can be used as long as os==ByteArrayOutputStream + * or it is not used before one of the writeByte methods. + * + * output characters to a FileOutputStream + * using os==FileOutputStream, asWriter==true, append(), and closeChannel() + * + * output bytes to a FileOutputStream + * using os==FileOutputStream, writeBytes(), writeByteAsInt(), append(), and closeChannel() + * + * post characters or bytes to a remote server + * using fileName=="http://..." or "https://...", + * writeBytes(), writeByteAsInt(), append(), and closeChannel() + * + * send characters or bytes to a JavaScript function + * when JavaScript and (typeof fileName == "function") + * + * if fileName equals ";base64,", then the data are base64-encoded + * prior to writing, and closeChannel() returns the data. + * + * @author hansonr Bob Hanson hansonr@stolaf.edu 9/2013 + * + * + */ + +public class OC extends OutputStream implements GenericOutputChannel { + + private BytePoster bytePoster; // only necessary for writing to http:// or https:// + private String fileName; + private BufferedWriter bw; + private boolean isLocalFile; + private int byteCount; + private boolean isCanceled; + private boolean closed; + private OutputStream os; + private SB sb; + private String type; + private boolean isBase64; + private OutputStream os0; + private byte[] bytes; // preset bytes; output only + + public boolean bigEndian = true; + + private boolean isTemp; + + /** + * Setting isTemp=true informs OC that this is a temporary file + * and not to send it to the user as a "download". Instead, the calling + * class can use .toByteArray() to retrieve the byte[] result. + * + * @param tf + */ + public void setTemp(boolean tf) { + isTemp = tf; + } + + + + @Override + public boolean isBigEndian() { + return bigEndian; + } + + public void setBigEndian(boolean TF) { + bigEndian = TF; + } + + /** + * Set up an output channel. String or byte data can be added without problem. + * + * @param bytePoster a byte poster can take the output byte[] when closing and + * do something with them + * @param fileName TODO: It is possible that JavaScript will call this with a + * function name for fileName + * @param asWriter string-based + * @param os the desired target OutputStream - not the calling stream! + * @return + */ + public OC setParams(BytePoster bytePoster, String fileName, + boolean asWriter, OutputStream os) { + this.bytePoster = bytePoster; + isBase64 = ";base64,".equals(fileName); + if (isBase64) { + fileName = null; + os0 = os; + os = null; + } + this.fileName = fileName; + this.os = os; + isLocalFile = (fileName != null && !isRemote(fileName)); + if (asWriter && !isBase64 && os != null) + bw = Rdr.getBufferedWriter(os, null); + return this; + } + + public OC setBytes(byte[] b) { + bytes = b; + return this; + } + + public String getFileName() { + return fileName; + } + + public String getName() { + return (fileName == null ? null : fileName.substring(fileName.lastIndexOf("/") + 1)); + } + + public int getByteCount() { + return byteCount; + } + + /** + * + * @param type user-identified type (PNG, JPG, etc) + */ + public void setType(String type) { + this.type = type; + } + + public String getType() { + return type; + } + + /** + * will go to string buffer if bw == null and os == null + * + * @param s + * @return this, for chaining like a standard StringBuffer + * + */ + public OC append(String s) { + try { + if (bw != null) { + bw.write(s); + } else if (os == null) { + if (sb == null) + sb = new SB(); + sb.append(s); + } else { + byte[] b = s.getBytes(); + os.write(b, 0, b.length); + byteCount += b.length; + return this; + } + } catch (IOException e) { + // ignore + } + byteCount += s.length(); // not necessarily exactly correct if unicode + return this; + } + + @Override + public void reset() { + sb = null; + initOS(); + } + + + private void initOS() { + if (sb != null) { + String s = sb.toString(); + reset(); + append(s); + return; + } + try { + /** + * @j2sNative + * + * this.os = null; + */ + { + if (os instanceof FileOutputStream) { + os.close(); + os = new FileOutputStream(fileName); + } else { + os = null; + } + } + if (os == null) + os = new ByteArrayOutputStream(); + if (bw != null) { + bw.close(); + bw = Rdr.getBufferedWriter(os, null); + } + } catch (Exception e) { + // not perfect here. + System.out.println(e.toString()); + } + byteCount = 0; + } + + /** + * @param b + */ + @Override + public void writeByteAsInt(int b) { + if (os == null) + initOS(); + { + try { + os.write(b); + } catch (IOException e) { + } + } + byteCount++; + } + + @Override + public void write(byte[] buf, int i, int len) { + if (os == null) + initOS(); + try { + os.write(buf, i, len); + } catch (IOException e) { + } + byteCount += len; + } + + @Override + public void writeShort(short i) { + if (isBigEndian()) { + writeByteAsInt(i >> 8); + writeByteAsInt(i); + } else { + writeByteAsInt(i); + writeByteAsInt(i >> 8); + } + } + + @Override + public void writeLong(long b) { + if (isBigEndian()) { + writeInt((int) ((b >> 32) & 0xFFFFFFFFl)); + writeInt((int) (b & 0xFFFFFFFFl)); + } else { + writeByteAsInt((int) (b >> 56)); + writeByteAsInt((int) (b >> 48)); + writeByteAsInt((int) (b >> 40)); + writeByteAsInt((int) (b >> 32)); + writeByteAsInt((int) (b >> 24)); + writeByteAsInt((int) (b >> 16)); + writeByteAsInt((int) (b >> 8)); + writeByteAsInt((int) b); + } + } + + public void write(int b) { + // required by standard ZipOutputStream -- do not use, as it will break JavaScript methods + if (os == null) + initOS(); + try { + os.write(b); + } catch (IOException e) { + } + byteCount++; + } + + public void write(byte[] b) { + // not used in JavaScript due to overloading problem there + write(b, 0, b.length); + } + + public void cancel() { + isCanceled = true; + closeChannel(); + } + + @Override + @SuppressWarnings({ "unused" }) + public String closeChannel() { + if (closed) + return null; + // can't cancel file writers + try { + if (bw != null) { + bw.flush(); + bw.close(); + } else if (os != null) { + os.flush(); + os.close(); + } + if (os0 != null && isCanceled) { + os0.flush(); + os0.close(); + } + } catch (Exception e) { + // ignore closing issues + } + if (isCanceled) { + closed = true; + return null; + } + if (fileName == null) { + if (isBase64) { + String s = getBase64(); + if (os0 != null) { + os = os0; + append(s); + } + sb = new SB(); + sb.append(s); + isBase64 = false; + return closeChannel(); + } + return (sb == null ? null : sb.toString()); + } + closed = true; + J2SObjectInterface J2S = null; + Object _function = null; + /** + * @j2sNative + * + * J2S = self.J2S || self.Jmol; _function = (typeof this.fileName == "function" ? + * this.fileName : null); + * + */ + { + if (!isLocalFile) { + String ret = postByteArray(); // unsigned applet could do this + if (ret.startsWith("java.net")) + byteCount = -1; + return ret; + } + } + if (J2S != null && !isTemp) { + + // action here generally will be for the browser to display a download message + // temp files will not be sent this way. + Object data = (sb == null ? toByteArray() : sb.toString()); + if (_function == null) + J2S.doAjax(fileName, null, data, sb == null); + else + J2S.applyFunc(_function, data); + } + return null; + } + + public boolean isBase64() { + return isBase64; + } + + public String getBase64() { + return Base64.getBase64(toByteArray()).toString(); + } + + public byte[] toByteArray() { + return (bytes != null ? bytes : (bytes = os instanceof ByteArrayOutputStream ? ((ByteArrayOutputStream)os).toByteArray() : + sb == null ? null : sb.toBytes(0, sb.length()))); + } + + @Override + @Deprecated + public void close() { + closeChannel(); + } + + @Override + public String toString() { + if (bw != null) + try { + bw.flush(); + } catch (IOException e) { + // TODO + } + if (sb != null) + return closeChannel(); + return byteCount + " bytes"; + } + + /** + * We have constructed some sort of byte[] that needs to be posted to a remote site. + * We don't do that posting here -- we let the bytePoster do it. + * + * @return + */ + private String postByteArray() { + return bytePoster == null ? null : bytePoster.postByteArray(fileName, toByteArray()); + } + + public final static String[] urlPrefixes = { "http:", "https:", "sftp:", "ftp:", + "file:" }; + // note that SFTP is not supported + public final static int URL_LOCAL = 4; + + public static boolean isRemote(String fileName) { + if (fileName == null) + return false; + int itype = urlTypeIndex(fileName); + return (itype >= 0 && itype != URL_LOCAL); + } + + public static boolean isLocal(String fileName) { + if (fileName == null) + return false; + int itype = urlTypeIndex(fileName); + return (itype < 0 || itype == URL_LOCAL); + } + + public static int urlTypeIndex(String name) { + if (name == null) + return -2; // local unsigned applet + for (int i = 0; i < urlPrefixes.length; ++i) { + if (name.startsWith(urlPrefixes[i])) { + return i; + } + } + return -1; + } + + @Override + public void writeInt(int i) { + if (bigEndian) { + writeByteAsInt(i >> 24); + writeByteAsInt(i >> 16); + writeByteAsInt(i >> 8); + writeByteAsInt(i); + } else { + writeByteAsInt(i); + writeByteAsInt(i >> 8); + writeByteAsInt(i >> 16); + writeByteAsInt(i >> 24); + } + } + + public void writeFloat(float x) { + writeInt(x == 0 ? 0 : Float.floatToIntBits(x)); + } + +}