RegexpPeerHeaderDescriptor.java
/*
* GovWay - A customizable API Gateway
* https://govway.org
*
* Copyright (c) 2005-2025 Link.it srl (https://link.it).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3, as published by
* the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package org.openspcoop2.pdd.core.integrazione.peer;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.openspcoop2.utils.Semaphore;
import org.openspcoop2.utils.SemaphoreLock;
import org.openspcoop2.utils.UtilsException;
import org.openspcoop2.utils.regexp.RegExpException;
import org.openspcoop2.utils.regexp.RegExpNotFoundException;
import org.openspcoop2.utils.regexp.RegularExpressionEngine;
/**
* Classe utilizzata per descrivere un headers peer di tipo regexp
*
* @author Tommaso Burlon (tommaso.burlon@link.it)
* @author $Author$
* @version $Rev$, $Date$
*/
public class RegexpPeerHeaderDescriptor implements PeerHeaderDescriptor {
private Pattern pattern = null;
private String headerName;
// cache utilizzata per non dover ricompilare i pattern ad ogni richiesta
private static ConcurrentMap<String, Pattern> compiledCache;
private static Queue<String> lruRecord;
private static int cacheSize;
private static final Semaphore lockCache = new Semaphore("PeerHeaderPatternLock");
public static void initCache(int cacheSize) {
RegexpPeerHeaderDescriptor.cacheSize = cacheSize;
RegexpPeerHeaderDescriptor.lruRecord = new LinkedList<>();
RegexpPeerHeaderDescriptor.compiledCache = new ConcurrentHashMap<>();
}
public RegexpPeerHeaderDescriptor(String key, String value) {
this.headerName = key;
if (compiledCache != null) {
// cerco prima il valore del pattern nella cache
this.pattern = compiledCache.get(value);
if (this.pattern == null) {
try {
// se il valore non e' in cache entro in un blocco sincronizzato
SemaphoreLock lock = lockCache.acquire("RegexpPeerHeaderDescriptor");
try {
this.pattern = compiledCache.get(value);
if (this.pattern == null) {
this.pattern = RegularExpressionEngine.createPatternEngine("^" + value + "$");
compiledCache.put(value, this.pattern);
if (compiledCache.size() > cacheSize) {
String firstElement = lruRecord.remove();
compiledCache.remove(firstElement);
}
lruRecord.add(value);
}
} finally {
lockCache.release(lock, "RegexpPeerHeaderDescriptor");
}
} catch (UtilsException e) {
// ignoro l'eccezione il pattern verra compilato successivamente se necessario
}
}
}
// se la cache non e' stata inizializzata o qualocsa e' andato storto lo compilo
if (this.pattern == null)
this.pattern = RegularExpressionEngine.createPatternEngine("^" + value + "$");
}
private static final Pattern NAME_PARAM_PATTERN = Pattern.compile("\\$\\{(\\d+)\\}");
@Override
public Map<String, String> computeHeaders(Collection<String> headers) {
Map<String, String> newHdrs = new HashMap<>();
for (String header : headers) {
try {
List<String> groups = RegularExpressionEngine.getAllStringMatchPattern(header, this.pattern);
Matcher m = NAME_PARAM_PATTERN.matcher(this.headerName);
String name = m.replaceAll(g -> {
String id = g.group(1);
int index = Integer.parseInt(id) - 1;
if (index < 0)
return header;
return groups.get(index);
});
String value = header;
newHdrs.put(name, value);
} catch (RegExpException | RegExpNotFoundException e) {
// regexp non trovata
}
}
return newHdrs;
}
}