CatalogService.java [src/csip] Revision: Date:
/*
* $Id: 2.7+12 CatalogService.java ba6f84354433 2022-09-29 od $
*
* This file is part of the Cloud Services Integration Platform (CSIP),
* a Model-as-a-Service framework, API and application suite.
*
* 2012-2022, Olaf David and others, OMSLab, Colorado State University.
*
* OMSLab licenses this file to you under the MIT license.
* See the LICENSE file in the project root for more information.
*/
package csip;
import csip.annotations.State;
import csip.utils.JSONUtils;
import csip.utils.Services;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.*;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.UriInfo;
import org.codehaus.jettison.json.JSONArray;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;
/**
* Catalog service
*
* @author wlloyd,od
*/
@Path("")
public class CatalogService {
static final Logger LOG = Config.LOG;
@GET
@Produces(MediaType.TEXT_PLAIN)
public String getTextCatalog(@Context UriInfo uriInfo, @Context HttpServletRequest httpReq) {
return getJSONCatalog(uriInfo, httpReq);
}
@GET
@Produces(MediaType.APPLICATION_JSON)
public String getJSONCatalog(@Context UriInfo uriInfo, @Context HttpServletRequest httpReq) {
LOG.log(Level.INFO, "HTTP/GET {0}", httpReq.getRequestURL().toString());
Registry r = Config.getRegistry();
JSONArray services = new JSONArray();
try {
String host = Utils.getPublicRequestURL(httpReq);
if (!host.endsWith("/"))
host += "/";
// Config parameter for requesting configuration info if:
// '...?config=true'
boolean requestConfig = isConfigInfoRequested(uriInfo);
// check access if needed.
boolean accessOK = false;
if (requestConfig) {
try {
Utils.checkRemoteAccessACL(httpReq);
accessOK = true;
} catch (RuntimeException Ex) {
// false
}
}
for (Class<? extends ModelDataService> cl : r.getServices()) {
State sta = cl.getAnnotation(State.class);
if (sta != null && sta.value().equals(State.HIDDEN))
continue;
String path = host + Utils.getServicePath(cl);
JSONObject service_info = Utils.getServiceInfo(cl, path);
if (requestConfig)
addConfigInfo(service_info, cl, accessOK);
services.put(service_info);
}
return services.toString(2).replace("\\/", "/");
} catch (JSONException ex) {
services.put(JSONUtils.error(ex.getMessage()));
LOG.log(Level.SEVERE, null, ex);
}
return services.toString().replace("\\/", "/");
}
private void addConfigInfo(JSONObject o, Class<? extends ModelDataService> cl, boolean accessOK) throws JSONException {
Map<String, Object> vi = callGetConfigInfo(cl);
if (vi != null) {
if (accessOK) {
for (Map.Entry<String, Object> e : vi.entrySet()) {
o.put(e.getKey(), sanitize(e.getValue()));
}
} else {
o.put("config", "Not authorized.");
}
}
}
@SuppressWarnings("unchecked")
private Map<String, Object> callGetConfigInfo(Class<? extends ModelDataService> cl) {
try {
Method m = findGetConfigInfoMethod(cl);
if (m == null)
return null;
m.setAccessible(true);
return (Map<String, Object>) m.invoke(cl.getDeclaredConstructor().newInstance());
} catch (Exception ex) {
LOG.log(Level.SEVERE, null, ex);
return null;
}
}
private Method findGetConfigInfoMethod(Class<?> cl) {
try {
if (cl == ModelDataService.class)
return null;
return cl.getDeclaredMethod("getConfigInfo");
} catch (NoSuchMethodException E) {
return findGetConfigInfoMethod((Class<?>) cl.getSuperclass());
} catch (Exception E) {
return null;
}
}
private static boolean isConfigInfoRequested(UriInfo uriInfo) {
MultivaluedMap<String, String> qp = uriInfo.getQueryParameters();
if (qp == null)
return false;
String val = qp.getFirst("config");
return val != null && val.toLowerCase().equals("true");
}
/*
* remove credentials from JDBC connect string if present. such as
* "jdbc:sqlserver://129.82.20.129:1433;databaseName=conservation_resources;user=sdmro;password=emHBcNq3"
* or "jdbc:postgresql://localhost/test?user=fred&password=secret&ssl=true"
*
*/
private static Object sanitize(Object s) {
if (s == null)
return "null";
// only process strings here
if (!(s instanceof String))
return s;
String s1 = (String) s;
if (s1.contains("jdbc:sqlserver:")) {
// remove all credentials
s1 = s1.replaceAll(";user=[^;]*", "");
s1 = s1.replaceAll(";password=[^;]*", "");
} else if (s1.contains("jdbc:postgresql:")) {
// remove all URL Path parameter
s1 = s1 + "?"; // add this in case there is no authentication info
s1 = s1.substring(0, s1.indexOf('?'));
}
return s1;
}
}