FileDocCategorySizeDatePackage
ManagedMemoryDataSource.javaAPI DocApache Axis 1.427603Sat Apr 22 18:57:28 BST 2006org.apache.axis.attachments

ManagedMemoryDataSource

public class ManagedMemoryDataSource extends Object implements DataSource
This class allows small attachments to be cached in memory, while large ones are cached out. It implements a Java Activiation Data source interface.
author
Rick Rineholt

Fields Summary
protected static Log
log
Field log
protected String
contentType
The content type. This defaults to application/octet-stream.
InputStream
ss
The incoming source stream.
public static final int
MIN_MEMORY_DISK_CACHED
Field MIN_MEMORY_DISK_CACHED
public static final int
MAX_MEMORY_DISK_CACHED
Field MAX_MEMORY_DISK_CACHED
protected int
maxCached
Field maxCached
protected File
diskCacheFile
Field diskCacheFile
protected WeakHashMap
readers
Field readers
protected boolean
deleted
Flag to show if the resources behind this have been deleted.
public static final int
READ_CHUNK_SZ
Field READ_CHUNK_SZ
protected boolean
debugEnabled
Field debugEnabled
protected LinkedList
memorybuflist
The linked list to hold the in memory buffers.
protected byte[]
currentMemoryBuf
Hold the last memory buffer.
protected int
currentMemoryBufSz
The number of bytes written to the above buffer.
protected long
totalsz
The total size in bytes in this data source.
protected BufferedOutputStream
cachediskstream
This is the cached disk stream.
protected boolean
closed
If true the source input stream is now closed.
protected static Log
is_log
Field is_log
Constructors Summary
protected ManagedMemoryDataSource()
Constructor ManagedMemoryDataSource.

    // Log debugging if true.

    // Should not be called;

           
      
    
public ManagedMemoryDataSource(InputStream ss, int maxCached, String contentType)
Create a new boundary stream.

param
ss is the source input stream that is used to create this data source.
param
maxCached This is the max memory that is to be used to cache the data.
param
contentType the mime type for this data stream. by buffering you can some effiency in searching.
throws
java.io.IOException

        this(ss, maxCached, contentType, false);
    
public ManagedMemoryDataSource(InputStream ss, int maxCached, String contentType, boolean readall)
Create a new boundary stream.

param
ss is the source input stream that is used to create this data source.
param
maxCached This is the max memory that is to be used to cache the data.
param
contentType the mime type for this data stream. by buffering you can some effiency in searching.
param
readall if true will read in the whole source.
throws
java.io.IOException


        if(ss instanceof BufferedInputStream) {
            this.ss = ss;
        } else {
            this.ss = new BufferedInputStream(ss);
        }
        this.maxCached = maxCached;

        if ((null != contentType) && (contentType.length() != 0)) {
            this.contentType = contentType;
        }

        if (maxCached < MIN_MEMORY_DISK_CACHED) {
            throw new IllegalArgumentException(
                    Messages.getMessage("badMaxCached", "" + maxCached));
        }

        if (log.isDebugEnabled()) {
            debugEnabled = true;    // Logging should be initialized by time;
        }

        // for now read all in to disk.
        if (readall) {
            byte[] readbuffer = new byte[READ_CHUNK_SZ];
            int read = 0;

            do {
                read = ss.read(readbuffer);

                if (read > 0) {
                    write(readbuffer, read);
                }
            } while (read > -1);

            close();
        }
    
Methods Summary
protected synchronized voidclose()
This method is a low level write. Close the stream.

throws
java.io.IOException


        if (!closed) {
            closed = true;                    // Markit as closed.

            if (null != cachediskstream) {    // close the disk cache.
                cachediskstream.close();

                cachediskstream = null;
            }

            if (null != memorybuflist) {      // There is a memory buffer.
                if (currentMemoryBufSz > 0) {
                    byte[] tmp =
                            new byte[currentMemoryBufSz];    // Get the last buffer and make it the sizeof the actual data.

                    System.arraycopy(currentMemoryBuf, 0, tmp, 0,
                            currentMemoryBufSz);
                    memorybuflist.set(
                            memorybuflist.size() - 1,
                            tmp);                 // Now replace the last buffer with this size.
                }

                currentMemoryBuf = null;      // No need for this anymore.
            }
        }
    
public synchronized booleandelete()


        boolean ret = false;

        deleted = true;

        memorybuflist = null;

        if (diskCacheFile != null) {
            if (cachediskstream != null) {
                try {
                    cachediskstream.close();
                } catch (Exception e) {
                }

                cachediskstream = null;
            }

            Object[] array = readers.keySet().toArray();
            for (int i = 0; i < array.length; i++) {
                Instream stream = (Instream) array[i];
                if (null != stream) {
                    try {
                        stream.close();
                    } catch (Exception e) {
                    }
                }
            }
            readers.clear();

            try {
                diskCacheFile.delete();

                ret = true;
            } catch (Exception e) {

                // Give it our best shot.
                diskCacheFile.deleteOnExit();
            }
        }


        return ret;
    
protected voidfinalize()


        if (null != cachediskstream) {    // close the disk cache.
            cachediskstream.close();

            cachediskstream = null;
        }
    
protected voidflushToDisk()
Routine to flush data to disk if is in memory.

throws
java.io.IOException
throws
java.io.FileNotFoundException


        java.util.LinkedList ml = memorybuflist;

        log.debug(Messages.getMessage("maxCached", "" + maxCached,
                "" + totalsz));

        if (ml != null) {
            if (null == cachediskstream) {    // Need to create a disk cache
                try {
                    MessageContext mc = MessageContext.getCurrentContext();
                    String attdir = (mc == null)
                            ? null
                            : mc.getStrProp(
                                    MessageContext.ATTACHMENTS_DIR);

                    diskCacheFile = java.io.File.createTempFile("Axis", ".att",
                            (attdir == null)
                            ? null
                            : new File(
                                    attdir));

                    if(log.isDebugEnabled()) {
                        log.debug(
                            Messages.getMessage(
                                    "diskCache", diskCacheFile.getAbsolutePath()));
                     }

                    cachediskstream = new java.io.BufferedOutputStream(
                            new java.io.FileOutputStream(diskCacheFile));

                    int listsz = ml.size();

                    // Write out the entire memory held store to disk.
                    for (java.util.Iterator it = ml.iterator();
                         it.hasNext();) {
                        byte[] rbuf = (byte[]) it.next();
                        int bwrite = (listsz-- == 0)
                                ? currentMemoryBufSz
                                : rbuf.length;

                        cachediskstream.write(rbuf, 0, bwrite);

                        if (closed) {
                            cachediskstream.close();

                            cachediskstream = null;
                        }
                    }

                    memorybuflist = null;
                } catch (java.lang.SecurityException se) {
                    diskCacheFile = null;
                    cachediskstream = null;
                    maxCached = java.lang.Integer.MAX_VALUE;

                    log.info(Messages.getMessage("nodisk00"), se);
                }
            }
        }
    
public java.lang.StringgetContentType()
This method returns the MIME type of the data in the form of a string.

return
The mime type.

        return contentType;
    
public java.io.FilegetDiskCacheFile()
get the filename of the content if it is cached to disk.

return
file object pointing to file, or null for memory-stored content

        return diskCacheFile;
    
public synchronized java.io.InputStreamgetInputStream()
This method returns an InputStream representing the the data and throws the appropriate exception if it can not do so.

return
the java.io.InputStream for the data source.
throws
java.io.IOException


        /*
         * if (memorybuflist == null) {
         *   return  new java.io.FileInputStream(diskCacheFile);
         * }
         * else
         */
        return new Instream();    // Return the memory held stream.
    
public java.lang.StringgetName()
This will flush any memory source to disk and provide the name of the file if desired.

return
the name of the file of the stream


        String ret = null;

        try {
            flushToDisk();

            if (diskCacheFile != null) {
                ret = diskCacheFile.getAbsolutePath();
            }
        } catch (Exception e) {
            diskCacheFile = null;
        }

        return ret;
    
public java.io.OutputStreamgetOutputStream()
This method returns an OutputStream where the data can be written and throws the appropriate exception if it can not do so. NOT SUPPORTED, not need for axis, data sources are create by constructors.

return
always null
throws
java.io.IOException

        return null;
    
public static voidmain(java.lang.String[] arg)
Method main

param
arg

    // test

        try {
            String readFile = arg[0];
            String writeFile = arg[1];
            java.io.FileInputStream ss =
                    new java.io.FileInputStream(readFile);
            ManagedMemoryDataSource ms =
                    new ManagedMemoryDataSource(ss, 1024 * 1024, "foo/data", true);
            javax.activation.DataHandler dh =
                    new javax.activation.DataHandler(ms);
            java.io.InputStream is = dh.getInputStream();
            java.io.FileOutputStream fo =
                    new java.io.FileOutputStream(writeFile);
            byte[] buf = new byte[512];
            int read = 0;

            do {
                read = is.read(buf);

                if (read > 0) {
                    fo.write(buf, 0, read);
                }
            } while (read > -1);

            fo.close();
            is.close();
        } catch (java.lang.Exception e) {
            log.error(Messages.getMessage("exception00"), e);
        }
    
protected voidwrite(byte[] data)
Write bytes to the stream.

param
data all bytes of this array are written to the stream
throws
java.io.IOException if there was a problem writing the data


                                    
          
        write(data, data.length);
    
protected synchronized voidwrite(byte[] data, int length)
This method is a low level write. Note it is designed to in the future to allow streaming to both memory AND to disk simultaneously.

param
data
param
length
throws
java.io.IOException


        if (closed) {
            throw new java.io.IOException(Messages.getMessage("streamClosed"));
        }

        int writesz = length;
        int byteswritten = 0;

        if ((null != memorybuflist)
                && (totalsz + writesz > maxCached)) {    // Cache to disk.
            if (null == cachediskstream) {               // Need to create a disk cache
                flushToDisk();
            }
        }

        if (memorybuflist != null) {    // Can write to memory.
            do {
                if (null == currentMemoryBuf) {
                    currentMemoryBuf = new byte[READ_CHUNK_SZ];
                    currentMemoryBufSz = 0;

                    memorybuflist.add(currentMemoryBuf);
                }

                // bytes to write is the min. between the remaining bytes and what is left in this buffer.
                int bytes2write = Math.min((writesz - byteswritten),
                        (currentMemoryBuf.length
                        - currentMemoryBufSz));

                // copy the data.
                System.arraycopy(data, byteswritten, currentMemoryBuf,
                        currentMemoryBufSz, bytes2write);

                byteswritten += bytes2write;
                currentMemoryBufSz += bytes2write;

                if (byteswritten
                        < writesz) {    // only get more if we really need it.
                    currentMemoryBuf = new byte[READ_CHUNK_SZ];
                    currentMemoryBufSz = 0;

                    memorybuflist.add(currentMemoryBuf);    // add it to the chain.
                }
            } while (byteswritten < writesz);
        }

        if (null != cachediskstream) {    // Write to the out going stream.
            cachediskstream.write(data, 0, length);
        }

        totalsz += writesz;

        return;