📄 managedmemorydatasource.java
字号:
/* * Copyright 2001-2004 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package org.apache.axis.attachments;import org.apache.axis.InternalException;import org.apache.axis.MessageContext;import org.apache.axis.components.logger.LogFactory;import org.apache.axis.utils.Messages;import org.apache.commons.logging.Log;import java.io.File;import java.io.BufferedInputStream;/** * 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 */public class ManagedMemoryDataSource implements javax.activation.DataSource { /** Field log */ protected static Log log = LogFactory.getLog(ManagedMemoryDataSource.class.getName()); /** * The content type. This defaults to * <code>application/octet-stream</code>. */ protected String contentType = "application/octet-stream"; /** The incoming source stream. */ java.io.InputStream ss = null; /** Field MIN_MEMORY_DISK_CACHED */ public static final int MIN_MEMORY_DISK_CACHED = -1; /** Field MAX_MEMORY_DISK_CACHED */ public static final int MAX_MEMORY_DISK_CACHED = 16 * 1024; /** Field maxCached */ protected int maxCached = MAX_MEMORY_DISK_CACHED; // max in memory cached. Default. // If set the file the disk is cached to. /** Field diskCacheFile */ protected java.io.File diskCacheFile = null; // A list of open input Streams. /** Field readers */ protected java.util.WeakHashMap readers = new java.util.WeakHashMap(); /** * Flag to show if the resources behind this have been deleted. */ protected boolean deleted = false; // Memory is allocated in these size chunks. /** Field READ_CHUNK_SZ */ public static final int READ_CHUNK_SZ = 32 * 1024; /** Field debugEnabled */ protected boolean debugEnabled = false; // Log debugging if true. // Should not be called; /** * Constructor ManagedMemoryDataSource. */ protected ManagedMemoryDataSource() { } /** * 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 */ public ManagedMemoryDataSource( java.io.InputStream ss, int maxCached, String contentType) throws java.io.IOException { this(ss, maxCached, contentType, false); } /** * 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 */ public ManagedMemoryDataSource( java.io.InputStream ss, int maxCached, String contentType, boolean readall) 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(); } } /* javax.activation.Interface DataSource implementation */ /** * This method returns the MIME type of the data in the form of a string. * @return The mime type. */ public java.lang.String getContentType() { return contentType; } /** * 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 */ public synchronized java.io.InputStream getInputStream() throws java.io.IOException { /* * if (memorybuflist == null) { * return new java.io.FileInputStream(diskCacheFile); * } * else */ return new Instream(); // Return the memory held stream. } /** * 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 */ public java.lang.String getName() { String ret = null; try { flushToDisk(); if (diskCacheFile != null) { ret = diskCacheFile.getAbsolutePath(); } } catch (Exception e) { diskCacheFile = null; } return ret; } /** * 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 <code>null</code> * * @throws java.io.IOException */ public java.io.OutputStream getOutputStream() throws java.io.IOException { return null; } /** The linked list to hold the in memory buffers. */ protected java.util.LinkedList memorybuflist = new java.util.LinkedList(); /** Hold the last memory buffer. */ protected byte[] currentMemoryBuf = null; /** The number of bytes written to the above buffer. */ protected int currentMemoryBufSz = 0; /** The total size in bytes in this data source. */ protected long totalsz = 0; /** This is the cached disk stream. */ protected java.io.BufferedOutputStream cachediskstream = null; /** If true the source input stream is now closed. */ protected boolean closed = false; /** * 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 */ protected void write(byte[] data) throws java.io.IOException { write(data, data.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 */ protected synchronized void write(byte[] data, int 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; } /** * This method is a low level write. * Close the stream. * * @throws java.io.IOException */ protected synchronized void close() 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. } } } protected void finalize() throws Throwable { if (null != cachediskstream) { // close the disk cache. cachediskstream.close(); cachediskstream = null; } } /** * Routine to flush data to disk if is in memory. * * @throws java.io.IOException * @throws java.io.FileNotFoundException */ protected void flushToDisk() throws java.io.IOException, 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 synchronized boolean delete() { boolean ret = false; deleted = true; memorybuflist = null; if (diskCacheFile != null) { if (cachediskstream != null) { try { cachediskstream.close(); } catch (Exception e) { } cachediskstream = null; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -