title: java.util.Collections$UnmodifiableMap problem : code included
body: <p>I am building a facebook platform web app using GWT and hosting it on App Engine.</p>
  
  <p>I am adding validation code that uses supplied query string parameters in the callback url. GWT allows me to get these parameters by calling Window.Location.getParameterMap() and the returned Map is immutable.</p>
  
  <p>I may be wrong however I think this problem has nothing to do with FB, GWT or App Engine specifically and is more down to my misunderstanding something about Map objects.    </p>
  
  <p>I don't think that my code attempts to modify the supplied Map but the error I get seems to suggest that my code is trying to modify an immutable Map.</p>
  
  <p>Can someone please take a look and let me know where I am modifying an unmodifiable Map?</p>
  
  <p>I would supply a stack trace but I can't find a way to get a stack trace for this to display in App Engine logs.</p>
  
  <p>Thanks in advance for any and all help :-)</p>
  
  <pre><code>/**
   * Validation Test
   * To generate the signature for these arguments:
   * 1. Remove the fb_sig key and value pair.
   * 2. Remove the "fb_sig_" prefix from all of the keys.
   * 3. Sort the array alphabetically by key.
   * 4. Concatenate all key/value pairs together in the format "k=v".
   * 5. Append your secret key.
   * 6. Take the md5 hash of the whole string.
   * @param fbQueryStringParams
   * @return String
   */
  public String test(Map&lt;String,List&lt;java.lang.String&gt;&gt; fbQueryStringParams) {
  
      String appSecret = TinyFBClient.APP_SECRET;
      String fbSig = fbQueryStringParams.get("fb_sig").get(0);
      StringBuilder sb = new StringBuilder();     
      TreeMap&lt;String,String&gt; sortedMap = new TreeMap&lt;String,String&gt;();
  
      // Get a Set view of the Map of query string parameters.
      Set&lt;Map.Entry&lt;String,List&lt;java.lang.String&gt;&gt;&gt; mapEntries = fbQueryStringParams.entrySet();
  
      // Iterate through the Set view, inserting into a SortedMap all Map.Entry's
      // that do not have a Key value of "fb_sig".
      Iterator&lt;Map.Entry&lt;String,List&lt;java.lang.String&gt;&gt;&gt; i = mapEntries.iterator();
      while(i.hasNext()) {
  
          Map.Entry&lt;String,List&lt;java.lang.String&gt;&gt; mapEntry = i.next();
  
          if(!mapEntry.getKey().equals("fb_sig")) { // 1. Remove the fb_sig key and value pair.
  
              sortedMap.put(mapEntry.getKey(),mapEntry.getValue().get(0)); // 3. Sort the array alphabetically by key.
  
          }
  
      }
  
      // Get a Set view of the Map of alphabetically sorted Map.Entry objects.
      Set&lt;Map.Entry&lt;String,String&gt;&gt; sortedMapEntries = sortedMap.entrySet();
  
      // Iterate through the Set view, appending the concatenated key's and value's
      // to a StringBuilder object.
      Iterator&lt;Map.Entry&lt;String,String&gt;&gt; ii = sortedMapEntries.iterator();
      while(ii.hasNext()) {
  
          Map.Entry&lt;String,String&gt; mapEntry = ii.next();
  
          // 4. Concatenate all key/value pairs together in the format "k=v".
          sb.append(mapEntry.getKey().replaceAll("fb_sig_","")); // 2. Remove the "fb_sig_" prefix from all of the keys.
          sb.append("=");
          sb.append(mapEntry.getValue());
  
      }
  
      sb.append(appSecret); // 5. Append your secret key.
  
      String md5 = DigestUtils.md5Hex(sb.toString()); // 6. Take the md5 hash of the whole string.
  
      // Build and return an output String for display.
      StringBuilder output = new StringBuilder();
      output.append("fbSig = "+fbSig);
      output.append("&lt;br/&gt;");
      output.append("md5 = "+md5);
      return output.toString();
  
  }
  </code></pre>