private Class<?> getClassFromStream( final InputStream stream, final String classname, final File container) throws IOException, SecurityException { final ByteArrayOutputStream baos = new ByteArrayOutputStream(); int bytesRead = -1; final byte[] buffer = new byte[8192]; while ((bytesRead = stream.read(buffer, 0, 8192)) != -1) { baos.write(buffer, 0, bytesRead); } final byte[] classData = baos.toByteArray(); return this.defineClassFromData(container, classData, classname); }
/** Write certficate bytes into a PEM encoded string */ public static String writePEM(byte[] bytes, String hdr, String ftr) throws IOException { ByteArrayOutputStream bos = new ByteArrayOutputStream(); Base64OutputStream b64os = new Base64OutputStream(bos); b64os.write(bytes); b64os.flush(); b64os.close(); ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray()); InputStreamReader irr = new InputStreamReader(bis); BufferedReader r = new BufferedReader(irr); StringBuffer buff = new StringBuffer(); String line; buff.append(hdr); while ((line = r.readLine()) != null) { buff.append(line + "\n"); } buff.append(ftr); return buff.toString(); }
/** * Read from the stream until length bytes have been read or EOF has been reached. Return the * number of bytes actually read. */ private static int readFully(InputStream in, ByteArrayOutputStream bout, int length) throws IOException { int read = 0; byte[] buffer = new byte[2048]; while (length > 0) { int n = in.read(buffer, 0, length < 2048 ? length : 2048); if (n <= 0) { break; } bout.write(buffer, 0, n); read += n; length -= n; } return read; }
/** * Generates a Payment message based on the information in the PaymentRequest. Provide * transactions built by the wallet. If the PaymentRequest did not specify a payment_url, returns * null. * * @param txns list of transactions to be included with the Payment message. * @param refundAddr will be used by the merchant to send money back if there was a problem. * @param memo is a message to include in the payment message sent to the merchant. */ public @Nullable Protos.Payment getPayment( List<Transaction> txns, @Nullable Address refundAddr, @Nullable String memo) throws IOException { if (!paymentDetails.hasPaymentUrl()) return null; Protos.Payment.Builder payment = Protos.Payment.newBuilder(); if (paymentDetails.hasMerchantData()) payment.setMerchantData(paymentDetails.getMerchantData()); if (refundAddr != null) { Protos.Output.Builder refundOutput = Protos.Output.newBuilder(); refundOutput.setAmount(totalValue.longValue()); refundOutput.setScript( ByteString.copyFrom(ScriptBuilder.createOutputScript(refundAddr).getProgram())); payment.addRefundTo(refundOutput); } if (memo != null) { payment.setMemo(memo); } for (Transaction txn : txns) { txn.verify(); ByteArrayOutputStream o = new ByteArrayOutputStream(); txn.bitcoinSerialize(o); payment.addTransactions(ByteString.copyFrom(o.toByteArray())); } return payment.build(); }
/** * Read one BER data block. This method is aware of indefinite-length BER encoding and will read * all of the sub-sections in a recursive way * * @param is Read from this InputStream * @param bout Write into this OutputStream * @param tag Tag already read (-1 mean not read) * @returns The current tag, used to check EOC in indefinite-length BER * @throws IOException Any parsing error */ private static int readBERInternal(InputStream is, ByteArrayOutputStream bout, int tag) throws IOException { if (tag == -1) { // Not read before the call, read now tag = is.read(); if (tag == -1) { throw new IOException("BER/DER tag info absent"); } if ((tag & 0x1f) == 0x1f) { throw new IOException("Multi octets tag not supported"); } bout.write(tag); } int n = is.read(); if (n == -1) { throw new IOException("BER/DER length info ansent"); } bout.write(n); int length; if (n == 0x80) { // Indefinite-length encoding if ((tag & 0x20) != 0x20) { throw new IOException("Non constructed encoding must have definite length"); } while (true) { int subTag = readBERInternal(is, bout, -1); if (subTag == 0) { // EOC, end of indefinite-length section break; } } } else { if (n < 0x80) { length = n; } else if (n == 0x81) { length = is.read(); if (length == -1) { throw new IOException("Incomplete BER/DER length info"); } bout.write(length); } else if (n == 0x82) { int highByte = is.read(); int lowByte = is.read(); if (lowByte == -1) { throw new IOException("Incomplete BER/DER length info"); } bout.write(highByte); bout.write(lowByte); length = (highByte << 8) | lowByte; } else if (n == 0x83) { int highByte = is.read(); int midByte = is.read(); int lowByte = is.read(); if (lowByte == -1) { throw new IOException("Incomplete BER/DER length info"); } bout.write(highByte); bout.write(midByte); bout.write(lowByte); length = (highByte << 16) | (midByte << 8) | lowByte; } else if (n == 0x84) { int highByte = is.read(); int nextByte = is.read(); int midByte = is.read(); int lowByte = is.read(); if (lowByte == -1) { throw new IOException("Incomplete BER/DER length info"); } if (highByte > 127) { throw new IOException("Invalid BER/DER data (a little huge?)"); } bout.write(highByte); bout.write(nextByte); bout.write(midByte); bout.write(lowByte); length = (highByte << 24) | (nextByte << 16) | (midByte << 8) | lowByte; } else { // ignore longer length forms throw new IOException("Invalid BER/DER data (too huge?)"); } if (readFully(is, bout, length) != length) { throw new IOException("Incomplete BER/DER data"); } } return tag; }
/** * Returns an ASN.1 SEQUENCE from a stream, which might be a BER-encoded binary block or a * PEM-style BASE64-encoded ASCII data. In the latter case, it's de-BASE64'ed before return. * * <p>After the reading, the input stream pointer is after the BER block, or after the newline * character after the -----END SOMETHING----- line. * * @param is the InputStream * @returns byte block or null if end of stream * @throws IOException If any parsing error */ private static byte[] readOneBlock(InputStream is) throws IOException { // The first character of a BLOCK. int c = is.read(); if (c == -1) { return null; } if (c == DerValue.tag_Sequence) { ByteArrayOutputStream bout = new ByteArrayOutputStream(2048); bout.write(c); readBERInternal(is, bout, c); return bout.toByteArray(); } else { // Read BASE64 encoded data, might skip info at the beginning char[] data = new char[2048]; int pos = 0; // Step 1: Read until header is found int hyphen = (c == '-') ? 1 : 0; // count of consequent hyphens int last = (c == '-') ? -1 : c; // the char before hyphen while (true) { int next = is.read(); if (next == -1) { // We accept useless data after the last block, // say, empty lines. return null; } if (next == '-') { hyphen++; } else { hyphen = 0; last = next; } if (hyphen == 5 && (last == -1 || last == '\r' || last == '\n')) { break; } } // Step 2: Read the rest of header, determine the line end int end; StringBuffer header = new StringBuffer("-----"); while (true) { int next = is.read(); if (next == -1) { throw new IOException("Incomplete data"); } if (next == '\n') { end = '\n'; break; } if (next == '\r') { next = is.read(); if (next == -1) { throw new IOException("Incomplete data"); } if (next == '\n') { end = '\n'; } else { end = '\r'; data[pos++] = (char) next; } break; } header.append((char) next); } // Step 3: Read the data while (true) { int next = is.read(); if (next == -1) { throw new IOException("Incomplete data"); } if (next != '-') { data[pos++] = (char) next; if (pos >= data.length) { data = Arrays.copyOf(data, data.length + 1024); } } else { break; } } // Step 4: Consume the footer StringBuffer footer = new StringBuffer("-"); while (true) { int next = is.read(); // Add next == '\n' for maximum safety, in case endline // is not consistent. if (next == -1 || next == end || next == '\n') { break; } if (next != '\r') footer.append((char) next); } checkHeaderFooter(header.toString(), footer.toString()); return Base64.getMimeDecoder().decode(new String(data, 0, pos)); } }