⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cmsflexresponse.java

📁 内容管理
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
        m_includeList.add(target);
    }
    
    /**
     * Is used to check if the response has an include list, 
     * which indicates a) it is probalbly processing a JSP element 
     * and b) it can never be streamed and alwys must be buffered.<p>
     *
     * @return true if this response has an include list, false otherwise
     */
    boolean hasIncludeList() {
        return m_includeList != null;
    }    

    /**
     * This method is needed to process pages that can NOT be analyzed
     * directly during delivering (like JSP) because they write to 
     * their own buffer.<p>
     *
     * So in this case, we don't actually write output of
     * include calls to the stream.
     * Where there are include calls we write a C_FLEX_CACHE_DELIMITER char on the stream to indicate
     * that at this point the output of the include must be placed later.
     * The include targets (resource names) are then saved in the m_includeList.<p>
     *
     * This method must be called after the complete page has been processed.
     * It will contain the output of the page only (no includes), 
     * with C_FLEX_CACHE_DELIMITER chars were the include calls should be placed. 
     * What we do here is analyze the output and cut it in parts 
     * of byte[] arrays which then are saved in the resulting cache entry.
     * For the includes, we just save the name of the resource in
     * the cache entry.<p>
     *  
     * If caching is disabled this method is just not called.<p>
     */
    private void processIncludeList() {
        byte[] result = getWriterBytes();            
        if (! hasIncludeList()) {
            // No include list, so no includes and we just use the bytes as they are in one block
            m_cachedEntry.add(result);
        } else {
            // Process the include list
            int max = result.length;
            int pos = 0;
            int last = 0;
            int size = 0;
            int count = 0;
            // Work through result and split this with include list calls
            java.util.Iterator i = m_includeList.iterator();
            java.util.Iterator j = m_includeListParameters.iterator();
            while (i.hasNext() && (pos<max)) {
                // Look for the first C_FLEX_CACHE_DELIMITER char
                while ((pos<max) && (result[pos] != C_FLEX_CACHE_DELIMITER)) {
                    pos++;
                }
                if (result[pos] == C_FLEX_CACHE_DELIMITER) {      
                    count++;
                    // A byte value of C_FLEX_CACHE_DELIMITER in our (string) output list indicates that the next include call
                    // must be placed here
                    size = pos - last;
                    if (size > 0) {
                        // If not (it might be 0) there would be 2 include calls back 2 back
                        byte[] piece = new byte[size];
                        System.arraycopy(result, last, piece, 0, size);
                        // Add the byte array to the cache entry
                        m_cachedEntry.add(piece);
                    }
                    last = ++pos;
                    // Add an include call to the cache entry
                    m_cachedEntry.add((String)i.next(), (java.util.HashMap)j.next());
                }
            } 
            // Is there something behind the last include call?
            if (pos<max) {
                // Yes!
                size = max - pos;
                byte[] piece = new byte[size];
                System.arraycopy(result, pos, piece, 0, size);                
                m_cachedEntry.add(piece);
            }           
            if (! i.hasNext()) {
                // Delete the include list if all include calls are handled
                m_includeList = null;
                m_includeListParameters = null;
            } else {
                // If something is left, remove the processed entries
                m_includeList = m_includeList.subList(count, m_includeList.size());
                m_includeListParameters = m_includeListParameters.subList(count, m_includeListParameters.size());
            }
        }
    }
    
    /** 
     * This delivers cached sub-elements back to the stream.
     * Needed to overcome JSP buffering.<p>
     *
     * @param res the response to write the cached results to
     * @throws IOException in case something goes wrong writing to the responses output stream
     */
    private void writeCachedResultToStream(HttpServletResponse res) throws IOException {        
        java.util.List elements = m_cachedEntry.elements();
        int count = 0;
        if (elements != null) {
            java.util.Iterator i = elements.iterator();
            while (i.hasNext()) {
                Object o = i.next();                
                if (o instanceof byte[]) {
                    res.getOutputStream().write((byte[])o);
                } else {
                    if ((m_includeResults != null) && (m_includeResults.size() > count)) {
                        // Make sure that we don't run behind end of list (should never happen, though)
                        res.getOutputStream().write((byte[])m_includeResults.get(count));
                        count++;
                    }
                    // Skip next entry, which is the parameter list for this incluce call
                    o = i.next();
                }
            }
        }
    }
    
    /**
     * Generates a CmsFlexCacheEntry from the current response using the 
     * stored include results.<p>
     * 
     * In case the results were written only to the buffer until now, 
     * they are now re-written on the output stream, with all included 
     * elements.<p>
     *
     * @throws IOException tn case something goes wrong while writing to the output stream
     * @return  the generated cache entry
     */    
    CmsFlexCacheEntry processCacheEntry() throws IOException {    
        if (isSuspended() && (m_buffer_redirect == null)) 
            // An included element redirected this response, no cache entry must be produced
            return null;
        
        if (m_cachingRequired) {
            // Cache entry must only be calculated if it's actually needed (always true if we write only to buffer)
            m_cachedEntry = new CmsFlexCacheEntry();    
            if (m_buffer_redirect != null) {
                // Only set et cached redirect target
                m_cachedEntry.setRedirect(m_buffer_redirect);
            } else {
                // Add cached headers
                m_cachedEntry.addHeaders(m_buffer_headers);
                // Add cached output 
                if (m_includeList != null) {
                    // Probably JSP: We must analyze out stream for includes calls
                    // Also, m_writeOnlyToBuffer must be "true" or m_includeList can not be != null
                    processIncludeList();   
                } else {
                    // Output is delivered directly, no include call parsing required
                    m_cachedEntry.add(getWriterBytes());
                }
            }
            m_cachedEntry.complete();
        }        
        // In case the output was only bufferd we have to re-write it to the "right" stream       
        if (m_writeOnlyToBuffer) {
            
            // Since we are processing a cache entry caching is not required
            m_cachingRequired = false;    
                        
            if (m_buffer_redirect != null) {
                // Send buffered redirect, will trigger redirect of top response
                sendRedirect(m_buffer_redirect);
            } else {  
                // Process the output               
                if (m_parentWritesOnlyToBuffer) {                                               
                    // Write results back to own stream, headers are already in buffer
                    if (m_out != null) {
                        try {
                            m_out.clear(); 
                        } catch (Exception e) {
                            if (DEBUG) System.err.println("FlexResponse: caught exception while calling m_out.clear() in processCacheEntry()\nException: " + e);                            
                        }
                    } else {
                        if (DEBUG) System.err.println("FlexResponse: m_out == null in processCacheEntry()");
                    }
                    writeCachedResultToStream(this);                 
                } else {
                    // We can use the parent stream
                    processHeaders(m_headers, m_res);
                    writeCachedResultToStream(m_res);  
                }
            }
        }        
        return m_cachedEntry;
    }
    
    /**
     * Returns the bytes that have been written on the current writers output stream.<p>
     *
     * @return the bytes that have been written on the current writers output stream
     */    
    public byte[] getWriterBytes() {
        if (isSuspended()) 
            // No output whatsoever if the response is suspended
            return new byte[0];
        if (m_cacheBytes != null)
            // Optimization for cached "leaf" nodes, here I re-use the array from the cache
            return m_cacheBytes;
        if (m_out == null) 
            // No output was written so far, just return an empty array
            return new byte[0];
        if (m_writer != null) 
            // Flush the writer in case something was written on it
            m_writer.flush();
        return m_out.getBytes();
    }
    
    /**
     * Initializes the current responses output stream 
     * and the corrosponding print writer.<p>
     *
     * @throws IOException in case something goes wrong while initializing
     */    
    private void initStream() throws IOException {        
        if (m_out == null) {
            if (! m_writeOnlyToBuffer) {
                // We can use the parents output stream
                if (m_cachingRequired || (m_controller.getResponseQueueSize() > 1)) {
                    // We are allowed to cache our results (probably to contruct a new cache entry)
                    m_out = new CmsFlexResponse.CmsServletOutputStream(m_res.getOutputStream());        
                } else {
                    // We are not allowed to cache so we just use the parents output stream
                    m_out = (CmsFlexResponse.CmsServletOutputStream)m_res.getOutputStream();
                }
            } else {
                // Construct a "buffer only" output stream
                m_out = new CmsFlexResponse.CmsServletOutputStream();
            }
        }
        if (m_writer == null) {
            // Encoding project:
            // Create a PrintWriter that uses the OpenCms default encoding
            m_writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(m_out, A_OpenCms.getDefaultEncoding())), false);
        }
    }
    
    /** 
     * Writes some bytes to the current output stream,
     * this method should be called from CmsFlexCacheEntry.service() only.<p>
     *
     * @param bytes an array of bytes
     * @param useArray indicates that the byte array should be used directly
     * @throws IOException in case something goes wrong while writing to the stream
     */
    void writeToOutputStream(byte[] bytes, boolean useArray) throws IOException {
        if (isSuspended()) return;        
        if (m_writeOnlyToBuffer) {
            if (useArray) {
                // This cached entry has no sub-elements (it a "leaf") and so we can just use it's bytes
                m_cacheBytes = bytes;                                  
            } else {
                if (m_out == null) initStream();
                // In this case the buffer will not write to the servlet stream, but to it's internal buffer only
                m_out.write(bytes);
            }
        } else {
            if (DEBUG) System.err.println("FlexResponse.writeToOutputStream(): Writing directly to wrapped output stream!");
            // The request is not buffered, so we can write directly to it's parents output stream 
            m_res.getOutputStream().write(bytes);
            m_res.getOutputStream().flush();
        }    
    }

    /**
     * Returns the cache key for to this response.<p>
     *
     * @return the cache key for to this response
     */
    CmsFlexCacheKey getCmsCacheKey() {
        return m_key;
    }
    
    /** 
     * Sets the cache key for this response, which is calculated
     * from the provided parameters.<p>
     *
     * @param target the target resouce for which to create the cache key
     * @param value the value of the cache property of the resource
     * @param online indicates if this resource is online or offline
     * @return the generated cache key
     * @throws CmsException in case the value String had a parse error
     */
    CmsFlexCacheKey setCmsCacheKey(String target, String value, boolean online) throws com.opencms.core.CmsException {
        m_key = new CmsFlexCacheKey(target, value, online);
        if (m_key.hadParseError()) {
            // We throw the exception here to make sure this response has a valid key (cache=never)
            throw new com.opencms.core.CmsException(com.opencms.core.CmsException.C_FLEX_CACHE);            
        }
        return m_key;
    }
    
    /**
     * Sets the cache key for this response from 
     * a pre-calculated cache key.<p>
     *
     * @param value the cache key to set
     */
    void setCmsCacheKey(CmsFlexCacheKey value) {
        m_key = value;

⌨️ 快捷键说明

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