📄 parameters.java
字号:
/* * ==================================================================== * * The Apache Software License, Version 1.1 * * Copyright (c) 1999 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, if * any, must include the following acknowlegement: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowlegement may appear in the software itself, * if and wherever such third-party acknowlegements normally appear. * * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software * Foundation" must not be used to endorse or promote products derived * from this software without prior written permission. For written * permission, please contact apache@apache.org. * * 5. Products derived from this software may not be called "Apache" * nor may "Apache" appear in their names without prior written * permission of the Apache Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. * * [Additional notices, if required by prior licensing conditions] * */ package org.apache.tomcat.util.http;import org.apache.tomcat.util.buf.*;import org.apache.tomcat.util.collections.MultiMap;import java.io.*;import java.util.*;import java.text.*;/** * * @author Costin Manolache */public final class Parameters extends MultiMap { // Transition: we'll use the same Hashtable( String->String[] ) // for the beginning. When we are sure all accesses happen through // this class - we can switch to MultiMap private Hashtable paramHashStringArray=new Hashtable(); private boolean didQueryParameters=false; private boolean didMerge=false; MessageBytes queryMB; MimeHeaders headers; UDecoder urlDec; MessageBytes decodedQuery=MessageBytes.newInstance(); public static final int INITIAL_SIZE=4; // Garbage-less parameter merging. // In a sub-request with parameters, the new parameters // will be stored in child. When a getParameter happens, // the 2 are merged togheter. The child will be altered // to contain the merged values - the parent is allways the // original request. private Parameters child=null; private Parameters parent=null; private Parameters currentChild=null; String encoding=null; /** * */ public Parameters() { super( INITIAL_SIZE ); } public void setQuery( MessageBytes queryMB ) { this.queryMB=queryMB; } public void setHeaders( MimeHeaders headers ) { this.headers=headers; } public void setEncoding( String s ) { encoding=s; if(debug>0) log( "Set encoding to " + s ); } public void recycle() { super.recycle(); paramHashStringArray.clear(); didQueryParameters=false; currentChild=null; didMerge=false; encoding=null; decodedQuery.recycle(); } // -------------------- Sub-request support -------------------- public Parameters getCurrentSet() { if( currentChild==null ) return this; return currentChild; } /** Create ( or reuse ) a child that will be used during a sub-request. All future changes ( setting query string, adding parameters ) will affect the child ( the parent request is never changed ). Both setters and getters will return the data from the deepest child, merged with data from parents. */ public void push() { // We maintain a linked list, that will grow to the size of the // longest include chain. // The list has 2 points of interest: // - request.parameters() is the original request and head, // - request.parameters().currentChild() is the current set. // The ->child and parent<- links are preserved ( currentChild is not // the last in the list ) // create a new element in the linked list // note that we reuse the child, if any - pop will not // set child to null ! if( currentChild==null ) { currentChild=new Parameters(); currentChild.setURLDecoder( urlDec ); currentChild.parent=this; return; } if( currentChild.child==null ) { currentChild.child=new Parameters(); currentChild.setURLDecoder( urlDec ); currentChild.child.parent=currentChild; } // it is not null if this object already had a child // i.e. a deeper include() ( we keep it ) // the head will be the new element. currentChild=currentChild.child; currentChild.setEncoding( encoding ); } /** Discard the last child. This happens when we return from a sub-request and the parameters are locally modified. */ public void pop() { if( currentChild==null ) { throw new RuntimeException( "Attempt to pop without a push" ); } currentChild.recycle(); currentChild=currentChild.parent; // don't remove the top. } // -------------------- Data access -------------------- // Access to the current name/values, no side effect ( processing ). // You must explicitely call handleQueryParameters and the post methods. // This is the original data representation ( hash of String->String[]) public String[] getParameterValues(String name) { handleQueryParameters(); // sub-request if( currentChild!=null ) { currentChild.merge(); return (String[])currentChild.paramHashStringArray.get(name); } // no "facade" String values[]=(String[])paramHashStringArray.get(name); return values; } public Enumeration getParameterNames() { handleQueryParameters(); // Slow - the original code if( currentChild!=null ) { currentChild.merge(); return currentChild.paramHashStringArray.keys(); } // merge in child return paramHashStringArray.keys(); } /** Combine the parameters from parent with our local ones */ private void merge() { // recursive if( debug > 0 ) { log("Before merging " + this + " " + parent + " " + didMerge ); log( paramsAsString()); } // Local parameters first - they take precedence as in spec. handleQueryParameters(); // we already merged with the parent if( didMerge ) return; // we are the top level if( parent==null ) return; // Add the parent props to the child ( lower precedence ) parent.merge(); Hashtable parentProps=parent.paramHashStringArray; merge2( paramHashStringArray , parentProps); didMerge=true; if(debug > 0 ) log("After " + paramsAsString()); } // Shortcut. public String getParameter(String name ) { String[] values = getParameterValues(name); if (values != null) { if( values.length==0 ) return ""; return values[0]; } else { return null; } } // -------------------- Processing -------------------- /** Process the query string into parameters */ public void handleQueryParameters() { if( didQueryParameters ) return; if( queryMB != null) queryMB.setEncoding( encoding ); didQueryParameters=true; if( debug > 0 ) log( "Decoding query " + queryMB + " " + encoding); if( queryMB==null || queryMB.isNull() ) return; try { decodedQuery.duplicate( queryMB ); decodedQuery.setEncoding(encoding); } catch( IOException ex ) { } if( debug > 0 ) log( "Decoding query " + decodedQuery + " " + encoding); processParameters( decodedQuery ); } // -------------------- /** Combine 2 hashtables into a new one. * ( two will be added to one ). * Used to combine child parameters ( RequestDispatcher's query ) * with parent parameters ( original query or parent dispatcher ) */ private static void merge2(Hashtable one, Hashtable two ) { Enumeration e = two.keys(); while (e.hasMoreElements()) { String name = (String) e.nextElement(); String[] oneValue = (String[]) one.get(name); String[] twoValue = (String[]) two.get(name); String[] combinedValue; if (twoValue == null) { continue; } else { if( oneValue==null ) { combinedValue = new String[twoValue.length];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -