/*
* Copyright (c) Bosch Software Innovations GmbH 2016.
* Part of the SW360 Portal Project.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.sw360.cvesearch.datasource;
import org.eclipse.sw360.cvesearch.datasource.json.CveSearchJsonParser;
import com.google.common.base.Strings;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import org.eclipse.sw360.datahandler.common.CommonUtils;
import org.apache.log4j.Logger;
import java.io.BufferedReader;
import java.lang.reflect.Type;
import java.io.*;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
public class CveSearchApiImpl implements CveSearchApi {
Logger log = Logger.getLogger(CveSearchApiImpl.class);
private String host;
private String CVE_SEARCH_SEARCH = "search";
private String CVE_SEARCH_CVEFOR = "cvefor";
private String CVE_SEARCH_BROWSE = "browse";
private String CVE_SEARCH_CVE = "cve";
public String CVE_SEARCH_WILDCARD = ".*";
private Type LIST_TARGET_TYPE = new TypeToken<List<CveSearchData>>(){}.getType();
private Type SINGLE_TARGET_TYPE = new TypeToken<CveSearchData>(){}.getType();
private Type META_TARGET_TYPE = new TypeToken<Map<String,Object>>(){}.getType();
public CveSearchApiImpl(String host) {
this.host = host;
}
private Object getParsedContentFor(String query, Function<BufferedReader,Object> parser) throws IOException {
log.debug("Execute query: " + query);
InputStream is = new URL(query).openStream();
if (is != null) {
try (BufferedReader content = new BufferedReader(new InputStreamReader(is, Charset.forName("UTF-8")))) {
return parser.apply(content);
}
}
return null;
}
private String composeQuery(String call, String ... path) throws UnsupportedEncodingException {
String query = host + "/api/" + call;
for (String p : path){
query += "/" + URLEncoder.encode(p,"UTF-8");
}
return query;
}
private List<CveSearchData> getParsedCveSearchDatas(String query) throws IOException {
return (List<CveSearchData>) getParsedContentFor(query, new CveSearchJsonParser(LIST_TARGET_TYPE));
}
private CveSearchData getParsedCveSearchData(String query) throws IOException {
return (CveSearchData) getParsedContentFor(query, new CveSearchJsonParser(SINGLE_TARGET_TYPE));
}
private List<String> getParsedCveSearchMetadata(String query, String key) throws IOException {
Map<String,Object> rawMap = (Map<String,Object>) getParsedContentFor(query, json -> new Gson().fromJson(json, META_TARGET_TYPE));
if(rawMap.containsKey(key)){
return (List<String>) rawMap.get(key);
}
return new ArrayList<>();
}
@Override
public List<CveSearchData> search(String vendor, String product) throws IOException {
Function<String,String> unifyer = s -> {
if(Strings.isNullOrEmpty(s)) {
return CVE_SEARCH_WILDCARD;
}
return CommonUtils.nullToEmptyString(s).replace(" ", "_").toLowerCase();
};
String query = composeQuery(CVE_SEARCH_SEARCH,
unifyer.apply(vendor),
unifyer.apply(product));
return getParsedCveSearchDatas(query);
}
@Override
public List<CveSearchData> cvefor(String cpe) throws IOException {
String query = composeQuery(CVE_SEARCH_CVEFOR, cpe.toLowerCase());
return getParsedCveSearchDatas(query);
}
@Override
public CveSearchData cve(String cve) throws IOException {
String query = composeQuery(CVE_SEARCH_CVE, cve.toUpperCase());
return getParsedCveSearchData(query);
}
@Override
public List<String> allVendorNames() throws IOException {
String query = composeQuery(CVE_SEARCH_BROWSE);
return getParsedCveSearchMetadata(query, "vendor");
}
@Override
public List<String> allProductsOfVendor(String vendorName) throws IOException {
String query = composeQuery(CVE_SEARCH_BROWSE,vendorName);
return getParsedCveSearchMetadata(query, "product");
}
}