Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   *
   * Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved.
   *
   * The contents of this file are subject to the terms of either the GNU
   * General Public License Version 2 only ("GPL") or the Common Development
   * and Distribution License("CDDL") (collectively, the "License").  You
   * may not use this file except in compliance with the License.  You can
  * obtain a copy of the License at
  * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
  * or packager/legal/LICENSE.txt.  See the License for the specific
  * language governing permissions and limitations under the License.
  *
  * When distributing the software, include this License Header Notice in each
  * file and include the License file at packager/legal/LICENSE.txt.
  *
  * GPL Classpath Exception:
  * Oracle designates this particular file as subject to the "Classpath"
  * exception as provided by Oracle in the GPL Version 2 section of the License
  * file that accompanied this code.
  *
  * Modifications:
  * If applicable, add the following below the License Header, with the fields
  * enclosed by brackets [] replaced by your own identifying information:
  * "Portions Copyright [year] [name of copyright owner]"
  *
  * Contributor(s):
  * If you wish your version of this file to be governed by only the CDDL or
  * only the GPL Version 2, indicate your decision by adding "[Contributor]
  * elects to include this software in this distribution under the [CDDL or GPL
  * Version 2] license."  If you don't indicate a single choice of license, a
  * recipient has the option to distribute your version of this file under
  * either the CDDL, the GPL Version 2 or to extend the choice of license to
  * its licensees as provided above.  However, if you add GPL Version 2 code
  * and therefore, elected the GPL Version 2 license, then the option applies
  * only if the new code is made subject to such option by the copyright
  * holder.
  *
  *
  * This file incorporates work covered by the following copyright and
  * permission notice:
  *
  * Copyright 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.tomcat.util.http;
 
 /* START PWC 6057385
 import java.util.Hashtable;
 */
 // START PWC 6057385
 // END PWC 6057385

Author(s):
Costin Manolache
 
 public final class Parameters extends MultiMap {
 
     private static com.sun.org.apache.commons.logging.Log log=
         com.sun.org.apache.commons.logging.LogFactory.getLog(Parameters.class );
 
     // 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
     /* START PWC 6057385
     private Hashtable paramHashStringArray=new Hashtable();
     */
     // START PWC 6057385
     // END PWC 6057385
     private boolean didQueryParameters=false;
     private boolean didMerge=false;
     
     MimeHeaders  headers;
    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;
    String queryStringEncoding=null;
    
    
    public Parameters() {
	super );
    }
    public void setQueryMessageBytes queryMB ) {
	this.=queryMB;
    }
    public void setHeadersMimeHeaders headers ) {
	this.=headers;
    }
    public void setEncodingString s ) {
	if(>0) log"Set encoding to " + s );
    }
    public void setQueryStringEncodingString s ) {
	if(>0) log"Set query string encoding to " + s );
    }
    public void recycle() {
	super.recycle();
	=false;
    }
    
    // -------------------- Sub-request support --------------------
    public Parameters getCurrentSet() {
	if==null )
	    return this;
	return ;
    }
    
    
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==null ) {
	    =new Parameters();
	    .=this;
	    return;
	}
	if.==null ) {
// 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.
    }

    
Discard the last child. This happens when we return from a sub-request and the parameters are locally modified.
    public void pop() {
	if==null ) {
	    throw new RuntimeException"Attempt to pop without a push" );
	}
	// 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 void addParameterValuesString keyString[] newValues) {
        if ( key==null ) return;
        String values[];
        if (.containsKey(key)) {
            String oldValues[] = (String[]).get(key);
            values = new String[oldValues.length + newValues.length];
            for (int i = 0; i < oldValues.lengthi++) {
                values[i] = oldValues[i];
            }
            for (int i = 0; i < newValues.lengthi++) {
                values[ioldValues.length] = newValues[i];
            }
        } else {
            values = newValues;
        }
        .put(keyvalues);
    }
    public String[] getParameterValues(String name) {
	// sub-request
	if!=null ) {
	    return (String[])..get(name);
	}
	// no "facade"
	return values;
    }
 
    public Enumeration getParameterNames() {
	// Slow - the original code
	if!=null ) {
            /* START PWC 6057385
            return currentChild.paramHashStringArray.keys();
            */
            // START PWC 6057385
            return Collections.enumeration(
                ..keySet());
            // END PWC 6057385
	}
	// merge in child
        /* START PWC 6057385
        return paramHashStringArray.keys();
        */
        // START PWC 6057385
        return Collections.enumeration(.keySet());
        // END PWC 6057385
    }

    
Combine the parameters from parent with our local ones
    private void merge() {
	// recursive
	if > 0 ) {
	    log("Before merging " + this + " " +  + " " +  );
	    log(  paramsAsString());
	}
	// Local parameters first - they take precedence as in spec.
	// we already merged with the parent
	if ) return;
	// we are the top level
	if==null ) return;
	// Add the parent props to the child ( lower precedence )
        /* START PWC 6057385
        Hashtable parentProps=parent.paramHashStringArray;
        */
        // START PWC 6057385
        // END PWC 6057385
	merge2 , parentProps);
	if( > 0 )
	    log("After " + paramsAsString());
    }
    // Shortcut.
    public String getParameter(String name ) {
        String[] values = getParameterValues(name);
        if (values != null) {
	    ifvalues.length==0 ) return "";
            return values[0];
        } else {
            return null;
        }
    }
  
 
    
Return undecoded params.
    public String getUndecodedParameter(String name) {
        processParameters(name);
                
	if!=null ) {
	}
	// no "facade"
        
        if (values != null) {
	    ifvalues.length==0 ) return "";
            return values[0];
        } else {
	    return null;
        }
    }
    
    
    // -------------------- Processing --------------------
    
Process the query string into parameters
    public void handleQueryParameters() {
	if ) return;
	if==null || .isNull() )
	    return;
	if > 0  )
	    log"Decoding query " +  + " " + );
        try {
            .duplicate );
        } catch (IOException e) {
            // Can't happen, as decodedQuery can't overflow
            e.printStackTrace();
        }
    }
    // --------------------
    
    
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 )
    /* START PWC 6057385
    private static void merge2(Hashtable one, Hashtable two ) {
        Enumeration e = two.keys();
        while (e.hasMoreElements()) {
            String name = (String) e.nextElement();
    */
    // START PWC 6057385
    private static void merge2(LinkedHashMap oneLinkedHashMap two ) {
        Iterator<Stringe = two.keySet().iterator();
        while (e.hasNext()) {
            String name = e.next();
    // END PWC 6057385
	    String[] oneValue = (String[]) one.get(name);
	    String[] twoValue = (String[]) two.get(name);
	    String[] combinedValue;
	    if (twoValue == null) {
		continue;
	    } else {
		ifoneValue==null ) {
		    combinedValue = new String[twoValue.length];
		    System.arraycopy(twoValue, 0, combinedValue,
				     0, twoValue.length);
else {
		    combinedValue = new String[oneValue.length +
					       twoValue.length];
		    System.arraycopy(oneValue, 0, combinedValue, 0,
				     oneValue.length);
		    System.arraycopy(twoValue, 0, combinedValue,
				     oneValue.lengthtwoValue.length);
		}
		one.put(namecombinedValue);
	    }
	}
    }
    // incredibly inefficient data representation for parameters,
    // until we test the new one
    private void addParamString keyString value ) {
	ifkey==null ) return;
	String values[];
	    String oldValues[] = (String[]).
		get(key);
	    values = new String[oldValues.length + 1];
	    for (int i = 0; i < oldValues.lengthi++) {
		values[i] = oldValues[i];
	    }
	    values[oldValues.length] = value;
else {
	    values = new String[1];
	    values[0] = value;
	}
    }
    public void setURLDecoderUDecoder u ) {
    }
    // -------------------- Parameter parsing --------------------
    // This code is not used right now - it's the optimized version
    // of the above.
    // we are called from a single thread - we can do it the hard way
    // if needed
    ByteChunk tmpName=new ByteChunk();
    CharChunk tmpNameC=new CharChunk(1024);
    CharChunk tmpValueC=new CharChunk(1024);
    
    public void processParametersbyte bytes[], int startint len ) {
        processParameters(bytesstartlen);
    }
    public void processParametersbyte bytes[], int startint len
                                   String enc ) {
	int end=start+len;
	int pos=start;
	if>0 ) 
	    log"Bytes: " + new Stringbytesstartlen ));
        do {
	    boolean noEq=false;
	    int valStart=-1;
	    int valEnd=-1;
	    
	    int nameStart=pos;
	    int nameEnd=ByteChunk.indexOf(bytesnameStartend'=' );
	    // Workaround for a&b&c encoding
	    int nameEnd2=ByteChunk.indexOf(bytesnameStartend'&' );
	    if( (nameEnd2!=-1 ) &&
nameEnd==-1 || nameEnd > nameEnd2) ) {
		nameEnd=nameEnd2;
		noEq=true;
		valStart=nameEnd;
		valEnd=nameEnd;
		if>0) log("no equal " + nameStart + " " + nameEnd + " " + new String(bytesnameStartnameEnd-nameStart) );
	    }
	    ifnameEnd== -1 ) 
		nameEnd=end;
	    if( ! noEq ) {
		valStart= (nameEnd < end) ? nameEnd+1 : end;
		valEnd=ByteChunk.indexOf(bytesvalStartend'&');
		ifvalEnd== -1 ) valEnd = (valStart < end) ? end : valStart;
	    }
	    
	    pos=valEnd+1;
	    
	    ifnameEnd<=nameStart ) {
		continue;
		// invalid chunk - it's better to ignore
		// XXX log it ?
	    }
	    .setBytesbytesnameStartnameEnd-nameStart );
	    .setBytesbytesvalStartvalEnd-valStart );
            try {
                addParamurlDecode(enc), urlDecode(enc) );
            } catch (IOException e) {
                // Exception during character decoding: skip parameter
            }
	    .recycle();
	    .recycle();
whilepos<end );
    }
    private String urlDecode(ByteChunk bcString enc)
        throws IOException {
        if==null ) {
            =new UDecoder();   
        }
        .convert(bc);
        String result = null;
        if (enc != null) {
            bc.setEncoding(enc);
            result = bc.toString();
        } else {
            CharChunk cc = ;
            int length = bc.getLength();
            cc.allocate(length, -1);
            // Default encoding: fast conversion
            byte[] bbuf = bc.getBuffer();
            char[] cbuf = cc.getBuffer();
            int start = bc.getStart();
            for (int i = 0; i < lengthi++) {
                cbuf[i] = (char) (bbuf[i + start] & 0xff);
            }
            cc.setChars(cbuf, 0, length);
            result = cc.toString();
            cc.recycle();
        }
        
        return result;
    }
    public void processParameterschar chars[], int startint len ) {
	int end=start+len;
	int pos=start;
	if>0 ) 
	    log"Chars: " + new Stringcharsstartlen ));
        do {
	    boolean noEq=false;
	    int nameStart=pos;
	    int valStart=-1;
	    int valEnd=-1;
	    
	    int nameEnd=CharChunk.indexOf(charsnameStartend'=' );
	    int nameEnd2=CharChunk.indexOf(charsnameStartend'&' );
	    if( (nameEnd2!=-1 ) &&
nameEnd==-1 || nameEnd > nameEnd2) ) {
		nameEnd=nameEnd2;
		noEq=true;
		valStart=nameEnd;
		valEnd=nameEnd;
		if>0) log("no equal " + nameStart + " " + nameEnd + " " + new String(charsnameStartnameEnd-nameStart) );
	    }
	    ifnameEnd== -1 ) nameEnd=end;
	    
	    if( ! noEq ) {
		valStart= (nameEnd < end) ? nameEnd+1 : end;
		valEnd=CharChunk.indexOf(charsvalStartend'&');
		ifvalEnd== -1 ) valEnd = (valStart < end) ? end : valStart;
	    }
	    
	    pos=valEnd+1;
	    
	    ifnameEnd<=nameStart ) {
		continue;
		// invalid chunk - no name, it's better to ignore
		// XXX log it ?
	    }
	    
	    try {
		.appendcharsnameStartnameEnd-nameStart );
		.appendcharsvalStartvalEnd-valStart );
		if > 0 )
		    log + "= " + );
		if==null ) {
		    =new UDecoder();   
		}
		if > 0 )
		    log + "= " + );
	    } catchIOException ex ) {
	    }
	    .recycle();
	    .recycle();
whilepos<end );
    }
    public void processParametersMessageBytes data ) {
        processParameters(data);
    }
    public void processParametersMessageBytes dataString encoding ) {
	ifdata==null || data.isNull() || data.getLength() <= 0 ) return;
	ifdata.getType() == . ) {
	    ByteChunk bc=data.getByteChunk();
	    processParametersbc.getBytes(), bc.getOffset(),
			       bc.getLength(), encoding);
else {
	    if (data.getType()!= . ) 
		data.toChars();
	    CharChunk cc=data.getCharChunk();
	    processParameterscc.getChars(), cc.getOffset(),
			       cc.getLength());
	}
    }

    
Debug purpose
    public String paramsAsString() {
        /* START PWC 6057385
        Enumeration en= paramHashStringArray.keys();
        while( en.hasMoreElements() ) {
            String k=(String)en.nextElement();
        */
        // START PWC 6057385
        Iterator<Stringen = .keySet().iterator();
        whileen.hasNext() ) {
            String k = en.next();
        // END PWC 6057385
	    sb.appendk ).append("=");
	    String v[]=(String[]).getk );
	    forint i=0; i<v.lengthi++ )
		sb.appendv[i] ).append(",");
	    sb.append("\n");
	}
	return sb.toString();
    }
    private static int debug=0;
    private void log(String s ) {
        if (.isDebugEnabled())
	    .debug("Parameters: " + s );
    }
   
    // -------------------- Old code, needs rewrite --------------------
    
    
Used by RequestDispatcher
    public void processSingleParametersString str ) {
	int end=str.length();
	int pos=0;
	if > 0)
	    log("String: " + str );
        do {
	    boolean noEq=false;
	    int valStart=-1;
	    int valEnd=-1;
	    
	    int nameStart=pos;
	    int nameEnd=str.indexOf('='nameStart );
	    int nameEnd2=str.indexOf('&'nameStart );
	    ifnameEnd2== -1 ) nameEnd2=end;
	    if( (nameEnd2!=-1 ) &&
nameEnd==-1 || nameEnd > nameEnd2) ) {
		nameEnd=nameEnd2;
		noEq=true;
		valStart=nameEnd;
		valEnd=nameEnd;
		if>0) log("no equal " + nameStart + " " + nameEnd + " " + str.substring(nameStartnameEnd) );
	    }
	    ifnameEnd== -1 ) nameEnd=end;
	    if( ! noEq ) {
		valStart=nameEnd+1;
		valEnd=str.indexOf('&'valStart);
		ifvalEnd== -1 ) valEnd = (valStart < end) ? end : valStart;
	    }
	    
	    pos=valEnd+1;
	    
	    ifnameEnd<=nameStart ) {
		continue;
	    }
	    if>0)
		log"XXX " + nameStart + " " + nameEnd + " "
		     + valStart + " " + valEnd );
	    
	    try {
		.append(strnameStartnameEnd-nameStart );
		.append(strvalStartvalEnd-valStart );
	    
		if > 0 )
		    log + "= " + );
		if==null ) {
		    =new UDecoder();   
		}
		if > 0 )
		    log + "= " + );
                if (str.compareTo(.toString()) == 0)
                    addParam.toString(), .toString() );
	    } catchIOException ex ) {
	    }
	    .recycle();
	    .recycle();
whilepos<end );
    }
    
    public void processParametersString str ) {
	int end=str.length();
	int pos=0;
	if > 0)
	    log("String: " + str );
        do {
	    boolean noEq=false;
	    int valStart=-1;
	    int valEnd=-1;
	    
	    int nameStart=pos;
	    int nameEnd=str.indexOf('='nameStart );
	    int nameEnd2=str.indexOf('&'nameStart );
	    ifnameEnd2== -1 ) nameEnd2=end;
	    if( (nameEnd2!=-1 ) &&
nameEnd==-1 || nameEnd > nameEnd2) ) {
		nameEnd=nameEnd2;
		noEq=true;
		valStart=nameEnd;
		valEnd=nameEnd;
		if>0) log("no equal " + nameStart + " " + nameEnd + " " + str.substring(nameStartnameEnd) );
	    }
	    ifnameEnd== -1 ) nameEnd=end;
	    if( ! noEq ) {
		valStart=nameEnd+1;
		valEnd=str.indexOf('&'valStart);
		ifvalEnd== -1 ) valEnd = (valStart < end) ? end : valStart;
	    }
	    
	    pos=valEnd+1;
	    
	    ifnameEnd<=nameStart ) {
		continue;
	    }
	    if>0)
		log"XXX " + nameStart + " " + nameEnd + " "
		     + valStart + " " + valEnd );
	    
	    try {
		.append(strnameStartnameEnd-nameStart );
		.append(strvalStartvalEnd-valStart );
	    
		if > 0 )
		    log + "= " + );
		if==null ) {
		    =new UDecoder();   
		}
		if > 0 )
		    log + "= " + );
	    } catchIOException ex ) {
	    }
	    .recycle();
	    .recycle();
whilepos<end );
    }
New to GrepCode? Check out our FAQ X