saajdatasource.java

来自「开源的axis2框架的源码。用于开发WEBSERVER」· Java 代码 · 共 640 行 · 第 1/2 页

JAVA
640
字号
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you 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.axis2.saaj.util;

import org.apache.axis2.Constants;
import org.apache.axis2.context.MessageContext;
import org.apache.axis2.description.Parameter;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.LinkedList;
import java.util.List;

/**
 * 
 */
public class SAAJDataSource implements javax.activation.DataSource {

    /** The content type. This defaults to <code>application/octet-stream</code>. */
    protected String contentType = "application/octet-stream";

    /** The incoming source stream. */
    private InputStream ss;

    /** 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.

    /** 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;

    /** Field READ_CHUNK_SZ */
    public static final int READ_CHUNK_SZ = 32 * 1024;


    /** 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;

    /** The total size in bytes in this data source. */
    protected long totalsz;

    /** This is the cached disk stream. */
    protected java.io.BufferedOutputStream cachediskstream;

    /** If true the source input stream is now closed. */
    protected boolean closed = false;

    /** Constructor SAAJDataSource. */
    protected SAAJDataSource() {
    }

    /**
     * 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 SAAJDataSource(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 SAAJDataSource(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("badMaxCached " + maxCached);
        }

        // 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) {
                    writeToMemory(readbuffer, read);
                }
            } while (read > -1);
            close();
        }
    }

    /**
     * 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.
            }
        }
    }

    /**
     * Routine to flush data to disk if is in memory.
     *
     * @throws java.io.IOException
     * @throws java.io.FileNotFoundException
     */
    protected void flushToDisk() throws IOException, FileNotFoundException {
        LinkedList ml = memorybuflist;
        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);*/


                    MessageContext messageContext = MessageContext.getCurrentMessageContext();
                    String attachementDir = "";
                    attachementDir = (String)messageContext.getProperty
                            (Constants.Configuration.ATTACHMENT_TEMP_DIR);

                    if (attachementDir.equals("")) {
                        Parameter param = (Parameter)messageContext.getParameter
                                (Constants.Configuration.ATTACHMENT_TEMP_DIR);
                        if (param != null) {
                            attachementDir = (String)param.getValue();
                        }
                    }

                    diskCacheFile = java.io.File.createTempFile("Axis", ".att",
                                                                (attachementDir == null)
                                                                        ? null
                                                                        : new File(
                                                                        attachementDir));
                    cachediskstream = new BufferedOutputStream(new 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;
                }
            }
        }
    }

    /**
     * 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("streamClosed");
        }

        int byteswritten = 0;

        if ((null != memorybuflist)
                && (totalsz + length > 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((length - byteswritten),
                                           (currentMemoryBuf.length
                                                   - currentMemoryBufSz));

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

                byteswritten += bytes2write;
                currentMemoryBufSz += bytes2write;

                if (byteswritten
                        < length) {    // 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 < length);
        }

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


    /**
     * This method is a low level write. Writes only to memory
     *
     * @param data
     * @param length
     * @throws java.io.IOException
     */
    protected synchronized void writeToMemory(byte[] data, int length) throws java.io.IOException {

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?