Java tutorial
/* * Copyright (c) 1994, 2003, Oracle and/or its affiliates. All rights reserved. * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. */ package org.adidac.io; import java.io.FilterOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.commons.io.IOUtils; /** * The class implements a buffered output stream. By setting up such * an output stream, an application can write bytes to the underlying * output stream without necessarily causing a call to the underlying * system for each byte written. * * @author Will Jones */ public class EmbededOutputStream extends FilterOutputStream { /** * The internal buffer where data is stored. */ protected byte buf[]; /** * The number of valid bytes in the buffer. This value is always * in the range <tt>0</tt> through <tt>buf.length</tt>; elements * <tt>buf[0]</tt> through <tt>buf[count-1]</tt> contain valid * byte data. */ protected int count; /** * Creates a new buffered output stream to write data to the * specified underlying output stream. * * @param out the underlying output stream. */ public EmbededOutputStream(OutputStream out) { this(out, 8192); } /** * Creates a new buffered output stream to write data to the * specified underlying output stream with the specified buffer * size. * * @param out the underlying output stream. * @param size the buffer size. * @exception IllegalArgumentException if size <= 0. */ public EmbededOutputStream(OutputStream out, int size) { super(out); if (size <= 0) { throw new IllegalArgumentException("Buffer size <= 0"); } buf = new byte[size]; } // ************************** // Modified in order to embed content // ************************** private final Pattern EMBED_PATTERN = Pattern.compile("\\{\\s*EMBED\\s*:\\s*([^}]*)\\s*\\}"); /** Flush the internal buffer */ private void flushBuffer() throws IOException { String s = new String(buf, 0, count); // Uses system encoding. Matcher m = EMBED_PATTERN.matcher(s); String fileName; StringBuffer sb = new StringBuffer(); while (m.find()) { fileName = m.group(1); String content = getContent(fileName); m.appendReplacement(sb, content); } m.appendTail(sb); out.write(sb.toString().getBytes()); count = 0; } private String getContent(String fileName) throws IOException { InputStream in = this.getClass().getResourceAsStream(fileName.trim()); if (in == null) { throw new IOException("Unable to load file [" + fileName + "]"); } return IOUtils.toString(in); } // END OF MODIFICATION /** * Writes the specified byte to this buffered output stream. * * @param b the byte to be written. * @exception IOException if an I/O error occurs. */ public synchronized void write(int b) throws IOException { if (count >= buf.length) { flushBuffer(); } buf[count++] = (byte) b; } /** * Writes <code>len</code> bytes from the specified byte array * starting at offset <code>off</code> to this buffered output stream. * * <p> Ordinarily this method stores bytes from the given array into this * stream's buffer, flushing the buffer to the underlying output stream as * needed. If the requested length is at least as large as this stream's * buffer, however, then this method will flush the buffer and write the * bytes directly to the underlying output stream. Thus redundant * <code>BufferedOutputStream</code>s will not copy data unnecessarily. * * @param b the data. * @param off the start offset in the data. * @param len the number of bytes to write. * @exception IOException if an I/O error occurs. */ public synchronized void write(byte b[], int off, int len) throws IOException { if (len >= buf.length) { /* If the request length exceeds the size of the output buffer, flush the output buffer and then write the data directly. In this way buffered streams will cascade harmlessly. */ flushBuffer(); out.write(b, off, len); return; } if (len > buf.length - count) { flushBuffer(); } System.arraycopy(b, off, buf, count, len); count += len; } /** * Flushes this buffered output stream. This forces any buffered * output bytes to be written out to the underlying output stream. * * @exception IOException if an I/O error occurs. * @see java.io.FilterOutputStream#out */ public synchronized void flush() throws IOException { flushBuffer(); out.flush(); } }