TransportUtils.java

  1. /*
  2.  * GovWay - A customizable API Gateway
  3.  * https://govway.org
  4.  *
  5.  * Copyright (c) 2005-2025 Link.it srl (https://link.it).
  6.  *
  7.  * This program is free software: you can redistribute it and/or modify
  8.  * it under the terms of the GNU General Public License version 3, as published by
  9.  * the Free Software Foundation.
  10.  *
  11.  * This program is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  * GNU General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU General Public License
  17.  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  18.  *
  19.  */
  20. package org.openspcoop2.utils.transport;

  21. import java.net.URLDecoder;
  22. import java.util.ArrayList;
  23. import java.util.Collection;
  24. import java.util.Enumeration;
  25. import java.util.HashMap;
  26. import java.util.Iterator;
  27. import java.util.List;
  28. import java.util.Map;

  29. import javax.servlet.http.Cookie;
  30. import javax.servlet.http.HttpServletRequest;
  31. import javax.servlet.http.HttpServletResponse;

  32. import org.openspcoop2.utils.LoggerWrapperFactory;
  33. import org.openspcoop2.utils.UtilsRuntimeException;
  34. import org.openspcoop2.utils.resources.Charset;
  35. import org.slf4j.Logger;
  36. import org.springframework.web.util.UriUtils;

  37. /**
  38.  * TransportUtils
  39.  *
  40.  *
  41.  * @author Andrea Poli (apoli@link.it)
  42.  * @author $Author$
  43.  * @version $Rev$, $Date$
  44.  */
  45. public class TransportUtils {
  46.    
  47.     private TransportUtils() {}

  48.     public static final String LDAP_PREFIX = "ldap://";
  49.     public static final String HTTP_PREFIX = "http://";
  50.     public static final String HTTPS_PREFIX = "https://";
  51.     public static final String FILE_PREFIX = "file://";
  52.     public static boolean isRemoteResource(String r) {
  53.         return r!=null &&
  54.                 (r.trim().startsWith(LDAP_PREFIX)
  55.                         ||
  56.                         r.trim().startsWith(HTTP_PREFIX)
  57.                         ||
  58.                         r.trim().startsWith(HTTPS_PREFIX)
  59.                         ||
  60.                         r.trim().startsWith(FILE_PREFIX) );
  61.     }
  62.     public static boolean isLdapResource(String r) {
  63.         return r!=null &&
  64.                 (r.trim().startsWith(LDAP_PREFIX) );
  65.     }
  66.     public static boolean isHttpResource(String r) {
  67.         return r!=null &&
  68.                 (r.trim().startsWith(HTTP_PREFIX) );
  69.     }
  70.     public static boolean isHttpsResource(String r) {
  71.         return r!=null &&
  72.                 (r.trim().startsWith(HTTPS_PREFIX) );
  73.     }
  74.     public static boolean isFileResource(String r) {
  75.         return r!=null &&
  76.                 (r.trim().startsWith(FILE_PREFIX) );
  77.     }
  78.    
  79.     /* Gestione CaseInsensitive per Properties */

  80.     public static boolean containsKey(Map<String, List<String>> p, String name) {
  81.         return hasKeyEngine(p, name);
  82.     }
  83.     @Deprecated
  84.     public static boolean hasKey(Map<String, String> p, String name) {
  85.         return hasKeyEngine(p, name);
  86.     }
  87.     private static boolean hasKeyEngine(Map<String, ?> p, String name) {
  88.        
  89.         // rfc7230#page-22: Each header field consists of a case-insensitive field name followed by a colon (":")
  90.        
  91.         if(p==null || p.isEmpty()) {
  92.             return false;
  93.         }
  94.         if(name==null) {
  95.             return false;
  96.         }
  97.         if(p.containsKey(name)) {
  98.             return true;
  99.         }
  100.         String lowerName = name.toLowerCase();
  101.         if(p.containsKey(lowerName)) {
  102.             return true;
  103.         }
  104.         if(p.containsKey(name.toUpperCase())) {
  105.             return true;
  106.         }
  107.         Iterator<String> keys = p.keySet().iterator();
  108.         while (keys.hasNext()) {
  109.             String key = keys.next();
  110.             String keyCaseInsensitive = key.toLowerCase();
  111.             if(keyCaseInsensitive.equals( lowerName )) {
  112.                 return true;
  113.             }
  114.         }
  115.         return false;
  116.        
  117.     }
  118.    
  119.     // Usare i metodi sottostanti come getRawObject e getObjectAsString
  120.     @Deprecated
  121.     public static String get(Map<String, String> p, String name) {
  122.         Object o = propertiesEngine(p, name, true);
  123.         return (o instanceof String) ? ((String)o) : null;
  124.     }
  125.     @Deprecated
  126.     public static Object remove(Map<String, String> p, String name) {
  127.         return propertiesEngine(p, name, false);
  128.     }
  129.     private static <T> T propertiesEngine(Map<String, T> p, String name, boolean get) {
  130.        
  131.         // rfc7230#page-22: Each header field consists of a case-insensitive field name followed by a colon (":")
  132.        
  133.         if(p==null || p.isEmpty()) {
  134.             return null;
  135.         }
  136.         if(name==null) {
  137.             return null;
  138.         }
  139.         T value = get ? p.get(name) : p.remove(name);
  140.         String lowerName = null;
  141.         if(value==null){
  142.             lowerName = name.toLowerCase();
  143.             value = get ? p.get( lowerName ) : p.remove( lowerName );
  144.         }
  145.         if(value==null){
  146.             value = get ? p.get(name.toUpperCase()) : p.remove(name.toUpperCase());
  147.         }
  148.         if(value==null){
  149.             List<String> keysFound = new ArrayList<>();
  150.             Iterator<String> keys = p.keySet().iterator();
  151.             while (keys.hasNext()) {
  152.                 String key = keys.next();
  153.                 String keyCaseInsensitive = key.toLowerCase();
  154.                 if ( lowerName == null )
  155.                     lowerName = name.toLowerCase();
  156.                 String nameCaseInsensitive = lowerName;
  157.                 if(keyCaseInsensitive.equals(nameCaseInsensitive)) {
  158.                     keysFound.add(key);
  159.                 }
  160.             }
  161.             if(!keysFound.isEmpty()) {
  162.                 for (String keyFound : keysFound) {
  163.                     T v = get? p.get(keyFound) : p.remove(keyFound);
  164.                     if(value==null) {
  165.                         value=v;
  166.                     }
  167.                 }
  168.             }
  169.         }
  170.         return value;
  171.        
  172.     }
  173.    
  174.    
  175.    
  176.     /* Gestione CaseInsensitive per Map */
  177.    
  178.     public static boolean mapHasKey(Map<String, Object> map, String name) {
  179.        
  180.         // rfc7230#page-22: Each header field consists of a case-insensitive field name followed by a colon (":")
  181.        
  182.         if(map==null || map.isEmpty()) {
  183.             return false;
  184.         }
  185.         if(name==null) {
  186.             return false;
  187.         }
  188.         if(map.containsKey(name)) {
  189.             return true;
  190.         }
  191.         String lowerName = name.toLowerCase();
  192.         if(map.containsKey( lowerName )) {
  193.             return true;
  194.         }
  195.         if(map.containsKey(name.toUpperCase())) {
  196.             return true;
  197.         }
  198.         Iterator<String> keys = map.keySet().iterator();
  199.         while (keys.hasNext()) {
  200.             String key = keys.next();
  201.             if(key!=null) {
  202.                 String keyCaseInsensitive = key.toLowerCase();
  203.                 if(keyCaseInsensitive.equals( lowerName )) {
  204.                     return true;
  205.                 }
  206.             }
  207.         }
  208.         return false;
  209.        
  210.     }
  211.     public static String getObjectAsString(Map<String, ?> map, String name) {
  212.         return (String) mapEngine(map, name, true, true);
  213.     }
  214.     public static String removeObjectAsString(Map<String, ?> map, String name) {
  215.         return (String) mapEngine(map, name, false, true);
  216.     }
  217.     @SuppressWarnings("unchecked")
  218.     public static <T> T getRawObject(Map<String, T> map, String name) {
  219.         return (T) mapEngine(map, name, true, false);
  220.     }
  221.     @SuppressWarnings("unchecked")
  222.     public static <T> T removeRawObject(Map<String, T> map, String name) {
  223.         return (T) mapEngine(map, name, false, false);
  224.     }
  225.     public static void removeObject(Map<String, ?> map, String name) {
  226.         mapEngine(map, name, false, false);
  227.     }
  228.     private static Object mapEngine(Map<String, ?> map, String name, boolean get, boolean returnAsString) {
  229.        
  230.         // rfc7230#page-22: Each header field consists of a case-insensitive field name followed by a colon (":")
  231.        
  232.         if(map==null || map.isEmpty()) {
  233.             return null;
  234.         }
  235.         if(name==null) {
  236.             return null;
  237.         }
  238.         String lowerName = null;
  239.         Object value = get? map.get(name) : map.remove(name);
  240.         if(value==null){
  241.             lowerName = name.toLowerCase();
  242.             value = get? map.get( lowerName ) : map.remove( lowerName );
  243.         }
  244.         if(value==null){
  245.             value = get? map.get(name.toUpperCase()) : map.remove(name.toUpperCase());
  246.         }
  247.         if(value==null){
  248.             List<String> keysFound = new ArrayList<>();
  249.             Iterator<String> keys = map.keySet().iterator();
  250.             while (keys.hasNext()) {
  251.                 String key = keys.next();
  252.                 if(key!=null) {
  253.                     String keyCaseInsensitive = key.toLowerCase();
  254.                     if ( lowerName == null )
  255.                         lowerName = name.toLowerCase();
  256.                     String nameCaseInsensitive = lowerName;
  257.                     if(keyCaseInsensitive.equals(nameCaseInsensitive)) {
  258.                         keysFound.add(key);
  259.                     }
  260.                 }
  261.             }
  262.             if(!keysFound.isEmpty()) {
  263.                 for (String keyFound : keysFound) {
  264.                     Object v = get? map.get(keyFound) : map.remove(keyFound);
  265.                     if(value==null) {
  266.                         value=v;
  267.                     }
  268.                 }
  269.             }
  270.         }
  271.         if(value==null) {
  272.             return null;
  273.         }
  274.         if(!returnAsString) {
  275.             return value;
  276.         }
  277.         else {
  278.             if(value instanceof String) {
  279.                 return value;
  280.             }
  281.             else if(value instanceof List<?>) {
  282.                 List<?> l = (List<?>) value;
  283.                 return convertToSingleValue(l);
  284.             }
  285.             else {
  286.                 return value.toString();
  287.             }
  288.         }
  289.        
  290.     }
  291.    
  292.    
  293.    
  294.     /* HttpServlet */
  295.    
  296.     @Deprecated
  297.     public static String getParameter(HttpServletRequest request, String name) {
  298.         return getParameterFirstValue(request, name);
  299.     }
  300.     public static String getParameterFirstValue(HttpServletRequest request, String name) {
  301.         List<String> l = getParameterValues(request, name);
  302.         if(l!=null) {
  303.             return l.get(0);
  304.         }
  305.         return null;
  306.     }
  307.     public static List<String> getParameterValues(HttpServletRequest request, String name) {
  308.         // rfc7230#page-22: Each header field consists of a case-insensitive field name followed by a colon (":")
  309.        
  310.         List<String> lNullReturn = null;
  311.        
  312.         if(request==null) {
  313.             return lNullReturn;
  314.         }
  315.         if(name==null) {
  316.             return lNullReturn;
  317.         }
  318.         String lowerName = null;
  319.         String exactKeyName = null;
  320.         Enumeration<String> keys = request.getParameterNames();
  321.         if(keys!=null) {
  322.             while (keys.hasMoreElements()) {
  323.                 String key = keys.nextElement();
  324.                 String keyCaseInsensitive = key.toLowerCase();
  325.                 if ( lowerName == null )
  326.                     lowerName = name.toLowerCase();
  327.                 String nameCaseInsensitive = lowerName;
  328.                 if(keyCaseInsensitive.equals(nameCaseInsensitive)) {
  329.                     exactKeyName = key;
  330.                     break;
  331.                 }
  332.             }
  333.         }
  334.         if(exactKeyName==null) {
  335.             return lNullReturn;
  336.         }
  337.        
  338.         String [] s = request.getParameterValues(exactKeyName);
  339.         List<String> values = new ArrayList<>();
  340.         if(s!=null && s.length>0) {
  341.             for (int i = 0; i < s.length; i++) {
  342.                 String value = s[i];
  343.                 values.add(value);
  344.                 /**System.out("Parameter ["+nomeProperty+"] valore-"+i+" ["+value+"]");*/
  345.             }
  346.         }
  347.         else {
  348.             /**System.out("Parameter ["+nomeProperty+"] valore ["+req.getParameter(nomeProperty)+"]");*/
  349.             values.add(request.getParameter(exactKeyName));
  350.         }
  351.        
  352.         return values;
  353.        
  354.     }
  355.    
  356.     @Deprecated
  357.     public static String getHeader(HttpServletRequest request, String name) {
  358.         return getHeaderFirstValue(request, name);
  359.     }
  360.     public static String getHeaderFirstValue(HttpServletRequest request, String name) {
  361.         List<String> l = getHeaderValues(request, name);
  362.         if(l!=null) {
  363.             return l.get(0);
  364.         }
  365.         return null;
  366.     }
  367.     public static List<String> getHeaderValues(HttpServletRequest request, String name) {
  368.        
  369.         // rfc7230#page-22: Each header field consists of a case-insensitive field name followed by a colon (":")
  370.        
  371.         List<String> lNullReturn = null;
  372.        
  373.         if(request==null) {
  374.             return lNullReturn;
  375.         }
  376.         if(name==null) {
  377.             return lNullReturn;
  378.         }
  379.         String lowerName = null;
  380.         String exactKeyName = null;
  381.         Enumeration<String> keys = request.getHeaderNames();
  382.         if(keys!=null) {
  383.             while (keys.hasMoreElements()) {
  384.                 String key = keys.nextElement();
  385.                 String keyCaseInsensitive = key.toLowerCase();
  386.                 if ( lowerName == null )
  387.                     lowerName = name.toLowerCase();
  388.                 String nameCaseInsensitive = lowerName;
  389.                 if(keyCaseInsensitive.equals(nameCaseInsensitive)) {
  390.                     exactKeyName = key;
  391.                     break;
  392.                 }
  393.             }
  394.         }
  395.         if(exactKeyName==null) {
  396.             return lNullReturn;
  397.         }
  398.        
  399.         Enumeration<String> enValues = request.getHeaders(exactKeyName);
  400.         List<String> values = new ArrayList<>();
  401.         if(enValues!=null) {
  402.             @SuppressWarnings("unused")
  403.             int i = 0;
  404.             while (enValues.hasMoreElements()) {
  405.                 String value = enValues.nextElement();
  406.                 values.add(value);
  407.                 /**System.out("Header ["+nomeHeader+"] valore-"+i+" ["+value+"]");*/
  408.                 i++;
  409.             }
  410.         }
  411.         if(values.isEmpty()) {
  412.             /**System.out("Header ["+nomeHeader+"] valore ["+req.getHeader(nomeHeader)+"]");*/
  413.             values.add(request.getHeader(exactKeyName));
  414.         }
  415.        
  416.         return values;
  417.        
  418.     }
  419.    
  420.     @Deprecated
  421.     public static String getHeader(HttpServletResponse response, String name) {
  422.         return getHeaderFirstValue(response, name);
  423.     }
  424.     public static String getHeaderFirstValue(HttpServletResponse response, String name) {
  425.         List<String> l = getHeaderValues(response, name);
  426.         if(l!=null) {
  427.             return l.get(0);
  428.         }
  429.         return null;
  430.     }
  431.     public static List<String> getHeaderValues(HttpServletResponse response, String name) {
  432.                
  433.         // rfc7230#page-22: Each header field consists of a case-insensitive field name followed by a colon (":")
  434.        
  435.         List<String> lNullReturn = null;
  436.        
  437.         if(response==null) {
  438.             return lNullReturn;
  439.         }
  440.         if(name==null) {
  441.             return lNullReturn;
  442.         }
  443.         String lowerName = null;
  444.         String exactKeyName = null;
  445.         if(response.getHeaderNames()!=null && !response.getHeaderNames().isEmpty()) {
  446.             Iterator<String> keys = response.getHeaderNames().iterator();
  447.             if(keys!=null) {
  448.                 while (keys.hasNext()) {
  449.                     String key = keys.next();
  450.                     String keyCaseInsensitive = key.toLowerCase();
  451.                     if ( lowerName == null )
  452.                         lowerName = name.toLowerCase();
  453.                     String nameCaseInsensitive = lowerName;
  454.                     if(keyCaseInsensitive.equals(nameCaseInsensitive)) {
  455.                         exactKeyName = key;
  456.                     }
  457.                 }
  458.             }
  459.         }
  460.         if(exactKeyName==null) {
  461.             return lNullReturn;
  462.         }
  463.        
  464.         Collection<String> enValues = response.getHeaders(exactKeyName);
  465.         List<String> values = new ArrayList<>();
  466.         if(enValues!=null && !enValues.isEmpty()) {
  467.             @SuppressWarnings("unused")
  468.             int i = 0;
  469.             for (String value : enValues) {
  470.                 values.add(value);
  471.                 /**System.out("Header ["+nomeHeader+"] valore-"+i+" ["+value+"]");*/
  472.                 i++;
  473.             }
  474.         }
  475.         if(values.isEmpty()) {
  476.             /**System.out("Header ["+nomeHeader+"] valore ["+req.getHeader(nomeHeader)+"]");*/
  477.             values.add(response.getHeader(exactKeyName));
  478.         }
  479.        
  480.         return values;
  481.        
  482.     }
  483.    
  484.     public static String getCookie(HttpServletRequest request, String name) {
  485.        
  486.         // rfc7230#page-22: Each header field consists of a case-insensitive field name followed by a colon (":")
  487.        
  488.         if(request==null) {
  489.             return null;
  490.         }
  491.         if(name==null) {
  492.             return null;
  493.         }
  494.         Cookie[] c = request.getCookies();
  495.         if(c==null || c.length<=0) {
  496.             return null;
  497.         }
  498.         for (Cookie cookie : c) {
  499.             if(cookie!=null && cookie.getName()!=null) {
  500.                 if(cookie.getName().equalsIgnoreCase(name)) {
  501.                     try {
  502.                         return URLDecoder.decode(cookie.getValue(), Charset.UTF_8.getValue());
  503.                     }catch(Exception e) {
  504.                         throw new UtilsRuntimeException(e.getMessage(),e);
  505.                     }
  506.                 }
  507.             }
  508.         }
  509.         return null;

  510.     }
  511.    
  512.    
  513.    
  514.    
  515.    
  516.     /* Gestione URL */
  517.    
  518.     @Deprecated
  519.     public static String buildLocationWithURLBasedParameter(Map<String, String> propertiesURLBased, String location){
  520.         return buildLocationWithURLBasedParameter(propertiesURLBased, location, false, LoggerWrapperFactory.getLogger(TransportUtils.class));
  521.     }
  522.     @Deprecated
  523.     public static String buildLocationWithURLBasedParameter(Map<String, String> propertiesURLBased, String location, Logger log){
  524.         return buildLocationWithURLBasedParameter(propertiesURLBased, location, false, log);
  525.     }
  526.     @Deprecated
  527.     public static String buildLocationWithURLBasedParameter(Map<String, String> propertiesURLBased, String location, boolean encodeLocation){
  528.         return buildLocationWithURLBasedParameter(propertiesURLBased, location, encodeLocation, LoggerWrapperFactory.getLogger(TransportUtils.class));
  529.     }
  530.     @Deprecated
  531.     public static String buildLocationWithURLBasedParameter(Map<String, String> propertiesURLBased, String location, boolean encodeLocation, Logger log){
  532.         Map<String, List<String>> parameters = convertToMapListValues(propertiesURLBased);
  533.         return buildUrlWithParameters(parameters, location, encodeLocation, log);
  534.     }
  535.    
  536.     public static String buildUrlWithParameters(Map<String, List<String>> parameters, String location){
  537.         return buildUrlWithParameters(parameters, location, false, LoggerWrapperFactory.getLogger(TransportUtils.class));
  538.     }
  539.     public static String buildUrlWithParameters(Map<String, List<String>> parameters, String location, Logger log){
  540.         return buildUrlWithParameters(parameters, location, false, log);
  541.     }
  542.     public static String buildUrlWithParameters(Map<String, List<String>> parameters, String location, boolean encodeLocation){
  543.         return buildUrlWithParameters(parameters, location, encodeLocation, LoggerWrapperFactory.getLogger(TransportUtils.class));
  544.     }
  545.     public static String buildUrlWithParameters(Map<String, List<String>> parameters, String location, boolean encodeLocation, Logger log){
  546.         String locationEncoded = location;
  547.         if(encodeLocation) {
  548.             locationEncoded = UriUtils.encodeQuery(location,Charset.UTF_8.getValue());
  549.         }
  550.        
  551.         if(parameters != null && parameters.size()>0){
  552.             StringBuilder urlBuilder = new StringBuilder(locationEncoded);
  553.             Iterator<String> keys = parameters.keySet().iterator();
  554.             while (keys.hasNext()) {
  555.                
  556.                 String key = keys.next();
  557.                 List<String> list = parameters.get(key);
  558.                 if(list!=null && !list.isEmpty()) {
  559.                
  560.                     for (String value : list) {
  561.                        
  562.                         if(!urlBuilder.toString().contains("?"))
  563.                             urlBuilder.append("?");
  564.                         else
  565.                             urlBuilder.append("&");
  566.                        
  567.                         try{
  568.                             key = urlEncodeParam(key,Charset.UTF_8.getValue());
  569.                         }catch(Exception e){
  570.                             if(log!=null) {
  571.                                 log.error("URLEncode key["+key+"] error: "+e.getMessage(),e);
  572.                             }
  573.                             else {
  574.                                 LoggerWrapperFactory.getLogger(TransportUtils.class).error("URLEncode key["+key+"] error: "+e.getMessage(),e);
  575.                             }
  576.                         }
  577.                        
  578.                         try{
  579.                             value = urlEncodeParam(value,Charset.UTF_8.getValue());
  580.                         }catch(Exception e){
  581.                             if(log!=null) {
  582.                                 log.error("URLEncode value:["+value+"] error: "+e.getMessage(),e);
  583.                             }
  584.                             else {
  585.                                 LoggerWrapperFactory.getLogger(TransportUtils.class).error("URLEncode value:["+value+"] error: "+e.getMessage(),e);
  586.                             }
  587.                         }
  588.                        
  589.                         String keyValue = key+"="+value;
  590.                         urlBuilder.append(keyValue);
  591.                        
  592.                     }
  593.                    
  594.                 }
  595.             }
  596.             return urlBuilder.toString();
  597.         }
  598.         else{
  599.             return locationEncoded;
  600.         }
  601.     }

  602.     public static String limitLocation255Character(String location){
  603.         if(location.length()>255){
  604.             return location.substring(0,251)+" ...";
  605.         }
  606.         else{
  607.             return location;
  608.         }
  609.     }
  610.    
  611.    
  612.     public static String urlEncodeParam(String value, String charset) {
  613.        
  614.         // Note that Java’s URLEncoder class encodes space character(" ") into a + sign.
  615.         // This is contrary to other languages like Javascript that encode space character into %20.
  616.        
  617.         /*
  618.          *  URLEncoder is not for encoding URLs, but for encoding parameter names and values for use in GET-style URLs or POST forms.
  619.          *  That is, for transforming plain text into the application/x-www-form-urlencoded MIME format as described in the HTML specification.
  620.          **/
  621.                
  622.         /**return java.net.URLEncoder.encode(value,"UTF8");*/
  623.        
  624.         // fix
  625.         String p = UriUtils.encodeQueryParam(value, charset);
  626.         int index = 0;
  627.         while(p.contains("+") && index<1000) {
  628.             p = p.replace("+", "%2B");
  629.             index++;
  630.         }
  631.         return p;
  632.     }
  633.    
  634.     public static String urlEncodePath(String value, String charset) {
  635.         return UriUtils.encode(value, charset);
  636.     }
  637.    
  638.    
  639.     /* ************** UTILITIES *************/
  640.    
  641.     public static String convertToSingleValue(List<?> l) {
  642.         if(l!=null && !l.isEmpty()) {
  643.             StringBuilder sb = new StringBuilder();
  644.             for (Object value : l) {
  645.                 if(value==null) {
  646.                     continue;
  647.                 }
  648.                 if(sb.length()>0) {
  649.                     sb.append(",");
  650.                 }
  651.                 sb.append(value);
  652.             }
  653.             if(sb.length()>0) {
  654.                 return sb.toString();
  655.             }
  656.             else {
  657.                 return null;
  658.             }
  659.         }
  660.         return null;
  661.     }
  662.    
  663.     public static Map<String, List<String>> convertToMapListValues(Map<String, String> mapSingleValue) {
  664.         Map<String, List<String>> mapMultipleValues = null;
  665.         if(mapSingleValue!=null && !mapSingleValue.isEmpty()) {
  666.             mapMultipleValues = new HashMap<>();
  667.             Iterator<String> keys = mapSingleValue.keySet().iterator();
  668.             while (keys.hasNext()) {
  669.                 String key = keys.next();
  670.                 String value = mapSingleValue.get(key);
  671.                 List<String> l = new ArrayList<>();
  672.                 l.add(value);
  673.                 mapMultipleValues.put(key, l);
  674.             }
  675.         }
  676.         return mapMultipleValues;
  677.     }
  678.    
  679.     public static Map<String, String> convertToMapSingleValue(Map<String, List<String>> mapMultipleValues) {
  680.         Map<String, String> mapSingleValue = null;
  681.         if(mapMultipleValues!=null && !mapMultipleValues.isEmpty()) {
  682.             mapSingleValue = new HashMap<>();
  683.             Iterator<String> keys = mapMultipleValues.keySet().iterator();
  684.             while (keys.hasNext()) {
  685.                 String key = keys.next();
  686.                 List<String> values = mapMultipleValues.get(key);
  687.                 String v = convertToSingleValue(values);
  688.                 if(v!=null) {
  689.                     mapSingleValue.put(key, v);
  690.                 }
  691.             }
  692.         }
  693.         return mapSingleValue;
  694.     }
  695.    
  696.     public static void addHeader(Map<String, List<String>> headers, String name, String value) {
  697.         put(headers, name, value, true);
  698.     }
  699.     public static void setHeader(Map<String, List<String>> headers, String name, String value) {
  700.         put(headers, name, value, false);
  701.     }
  702.    
  703.     public static void addParameter(Map<String, List<String>> parameters, String name, String value) {
  704.         put(parameters, name, value, true);
  705.     }
  706.     public static void setParameter(Map<String, List<String>> parameters, String name, String value) {
  707.         put(parameters, name, value, false);
  708.     }
  709.    
  710.     public static void put(Map<String, List<String>> map, String name, String value, boolean add) {
  711.        
  712.         if(value==null) {
  713.             return;
  714.         }
  715.        
  716.         List<String> l = map.get(name);
  717.         if(add) {
  718.             if(l==null) {
  719.                 l = new ArrayList<>();
  720.                 map.put(name, l);
  721.             }
  722.         }
  723.         else {
  724.             if(l==null) {
  725.                 l = new ArrayList<>();
  726.                 map.put(name, l);
  727.             }
  728.             else {
  729.                 l.clear();
  730.             }
  731.         }
  732.         l.add(value);
  733.     }
  734.    
  735.    
  736.    
  737.     public static List<String> getValues(Map<String, List<String>> map, String key) {
  738.         List<String> lReturn = null;
  739.         if(map!=null && !map.isEmpty()) {
  740.             List<String> l = getRawObject(map, key);
  741.             if(l!=null && !l.isEmpty()) {
  742.                 return l;
  743.             }
  744.         }
  745.         return lReturn;
  746.     }
  747.    
  748.     public static String getFirstValue(Map<String, List<String>> map, String key) {
  749.         if(map!=null && !map.isEmpty()) {
  750.             List<String> l = getRawObject(map, key);
  751.             if(l!=null && !l.isEmpty()) {
  752.                 return l.get(0);
  753.             }
  754.         }
  755.         return null;
  756.     }
  757.     public static String getFirstValue(List<String> list) {
  758.         if(list!=null && !list.isEmpty()) {
  759.             return list.get(0);
  760.         }
  761.         return null;
  762.     }
  763. }