RegexpPeerHeaderDescriptor.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.pdd.core.integrazione.peer;

  21. import java.util.Collection;
  22. import java.util.HashMap;
  23. import java.util.LinkedList;
  24. import java.util.List;
  25. import java.util.Map;
  26. import java.util.Queue;
  27. import java.util.concurrent.ConcurrentHashMap;
  28. import java.util.concurrent.ConcurrentMap;
  29. import java.util.regex.Matcher;
  30. import java.util.regex.Pattern;


  31. import org.openspcoop2.utils.Semaphore;
  32. import org.openspcoop2.utils.SemaphoreLock;
  33. import org.openspcoop2.utils.UtilsException;
  34. import org.openspcoop2.utils.regexp.RegExpException;
  35. import org.openspcoop2.utils.regexp.RegExpNotFoundException;
  36. import org.openspcoop2.utils.regexp.RegularExpressionEngine;


  37. /**
  38.  * Classe utilizzata per descrivere un headers peer di tipo regexp
  39.  *
  40.  * @author Tommaso Burlon (tommaso.burlon@link.it)
  41.  * @author $Author$
  42.  * @version $Rev$, $Date$
  43.  */
  44. public class RegexpPeerHeaderDescriptor implements PeerHeaderDescriptor {
  45.     private Pattern pattern = null;
  46.     private String headerName;
  47.    
  48.    
  49.     // cache utilizzata per non dover ricompilare i pattern ad ogni richiesta
  50.     private static ConcurrentMap<String, Pattern> compiledCache;
  51.     private static Queue<String> lruRecord;
  52.     private static int cacheSize;
  53.    
  54.     private static final Semaphore lockCache = new Semaphore("PeerHeaderPatternLock");
  55.     public static void initCache(int cacheSize) {
  56.         RegexpPeerHeaderDescriptor.cacheSize = cacheSize;
  57.         RegexpPeerHeaderDescriptor.lruRecord = new LinkedList<>();
  58.         RegexpPeerHeaderDescriptor.compiledCache = new ConcurrentHashMap<>();
  59.     }
  60.    
  61.    
  62.     public RegexpPeerHeaderDescriptor(String key, String value) {
  63.         this.headerName = key;
  64.         if (compiledCache != null) {
  65.            
  66.             // cerco prima il valore del pattern nella cache
  67.             this.pattern = compiledCache.get(value);
  68.             if (this.pattern == null) {
  69.                 try {
  70.                    
  71.                     // se il valore non e' in cache entro in un blocco sincronizzato
  72.                     SemaphoreLock lock = lockCache.acquire("RegexpPeerHeaderDescriptor");
  73.                     try {
  74.                         this.pattern = compiledCache.get(value);
  75.                         if (this.pattern == null) {
  76.                             this.pattern = RegularExpressionEngine.createPatternEngine("^" + value + "$");
  77.                             compiledCache.put(value, this.pattern);
  78.                            
  79.                             if (compiledCache.size() > cacheSize) {
  80.                                 String firstElement = lruRecord.remove();
  81.                                 compiledCache.remove(firstElement);
  82.                             }
  83.                             lruRecord.add(value);
  84.                         }
  85.                     } finally {
  86.                         lockCache.release(lock, "RegexpPeerHeaderDescriptor");
  87.                     }
  88.                 } catch (UtilsException e) {
  89.                     // ignoro l'eccezione il pattern verra compilato successivamente se necessario
  90.                 }
  91.             }
  92.         }
  93.        
  94.         // se la cache non e' stata inizializzata o qualocsa e' andato storto lo compilo
  95.         if (this.pattern == null)
  96.             this.pattern = RegularExpressionEngine.createPatternEngine("^" + value + "$");
  97.     }
  98.    
  99.    
  100.     private static final Pattern NAME_PARAM_PATTERN = Pattern.compile("\\$\\{(\\d+)\\}");
  101.     @Override
  102.     public Map<String, String> computeHeaders(Collection<String> headers) {
  103.         Map<String, String> newHdrs = new HashMap<>();
  104.        
  105.         for (String header : headers) {
  106.             try {
  107.                 List<String> groups = RegularExpressionEngine.getAllStringMatchPattern(header, this.pattern);
  108.                 Matcher m = NAME_PARAM_PATTERN.matcher(this.headerName);
  109.                 String name = m.replaceAll(g -> {
  110.                     String id = g.group(1);
  111.                     int index = Integer.parseInt(id) - 1;
  112.                     if (index < 0)
  113.                         return header;
  114.                     return groups.get(index);
  115.                 });
  116.                 String value = header;
  117.                 newHdrs.put(name, value);
  118.             } catch (RegExpException | RegExpNotFoundException e) {
  119.                 // regexp non trovata
  120.             }
  121.         }
  122.        
  123.         return newHdrs;
  124.     }
  125. }