+++ /dev/null
-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));
- }
-
-}