diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..d0942bf0 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +DSP_SIM_MODEL.json diff --git a/data-services/pom.xml b/data-services/pom.xml new file mode 100644 index 00000000..9120857e --- /dev/null +++ b/data-services/pom.xml @@ -0,0 +1,142 @@ + + + 4.0.0 + com.atg.openssp + open-ssp-data-services + 0.1 + open-ssp-data-services + http://maven.apache.org + war + + UTF-8 + y + + + + mock-catalina-home + + + !env.catalina.home + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.5.1 + + 1.8 + 1.8 + + + + org.apache.maven.plugins + maven-surefire-plugin + + + + catalina.home + ${my.dev.catalina.home} + + + + + + + + + + + ssp-data-provider + + + org.apache.tomcat.maven + tomcat7-maven-plugin + 2.2 + + /${project.build.finalName} + utf-8 + + -Xms512m -Xmx1024m + + 9090 + + + + + org.codehaus.mojo + properties-maven-plugin + 1.0.0 + + + + ${project.build.outputDirectory}/app.properties + + + + + generate-resources + + write-project-properties + + + + + + + org.apache.maven.plugins + maven-war-plugin + 2.6 + + + + + + + junit + junit + 3.8.1 + test + + + javax.servlet + javax.servlet-api + 3.1.0 + provided + + + com.google.code.gson + gson + 2.6.2 + + + org.apache.logging.log4j + log4j-core + 2.6.2 + + + org.apache.logging.log4j + log4j-slf4j-impl + 2.8 + + + + com.atg.openssp + open-ssp-common + 0.3 + + + com.atg.openssp + core + 0.3 + + + com.atg.openssp + open-ssp-openrtb + 0.3 + + + + diff --git a/data-services/src/main/java/com/atg/openssp/dataprovider/provider/dto/TokenWrapper.java b/data-services/src/main/java/com/atg/openssp/dataprovider/provider/dto/TokenWrapper.java new file mode 100644 index 00000000..06c3d2f0 --- /dev/null +++ b/data-services/src/main/java/com/atg/openssp/dataprovider/provider/dto/TokenWrapper.java @@ -0,0 +1,17 @@ +package com.atg.openssp.dataprovider.provider.dto; + +/** + * @author André Schmer + */ +public class TokenWrapper { + private String token; + + public String getToken() { + return token; + } + + @SuppressWarnings("unused") + public void setToken(final String token) { + this.token = token; + } +} diff --git a/data-services/src/main/java/com/atg/openssp/dataprovider/provider/handler/AppDataHandler.java b/data-services/src/main/java/com/atg/openssp/dataprovider/provider/handler/AppDataHandler.java new file mode 100644 index 00000000..dd6a9873 --- /dev/null +++ b/data-services/src/main/java/com/atg/openssp/dataprovider/provider/handler/AppDataHandler.java @@ -0,0 +1,70 @@ +package com.atg.openssp.dataprovider.provider.handler; + +import com.atg.openssp.core.cache.broker.dto.AppDto; +import com.atg.openssp.core.system.LocalContext; +import com.google.gson.Gson; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import util.properties.ProjectProperty; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.xml.bind.PropertyException; +import java.io.IOException; +import java.io.OutputStream; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.Map; + +/** + * @author Brian Sorensen + */ +public class AppDataHandler extends DataHandler { + private static final Logger log = LoggerFactory.getLogger(AppDataHandler.class); + public static final String CONTEXT = "/lookup/app"; + + public AppDataHandler(HttpServletRequest request, HttpServletResponse response) { + if (LocalContext.isAppDataServiceEnabled()) { + try { + String location; + try { + location = ProjectProperty.getPropertiesResourceLocation()+"/"; + } catch (PropertyException e) { + log.warn("property file not found."); + location=""; + } + Gson gson = new Gson(); + String content = new String(Files.readAllBytes(Paths.get(location+"app_db.json")), StandardCharsets.UTF_8); + + AppDto data = gson.fromJson(content, AppDto.class); + + Map parms = queryToMap(request.getQueryString()); + String t = parms.get("t"); + + if (LoginHandler.TOKEN.equals(t)) { + String result = new Gson().toJson(data); + + response.setStatus(200); + response.setContentType("application/json; charset=UTF8"); + OutputStream os = response.getOutputStream(); + os.write(result.getBytes()); + os.close(); + } else { + response.setStatus(401); + } + } catch (IOException e) { + response.setStatus(500); + log.error(e.getMessage(), e); + } + } else { + response.setStatus(404); + } + } + + @Override + public void cleanUp() { + + } + +} diff --git a/data-services/src/main/java/com/atg/openssp/dataprovider/provider/handler/CurrencyDataHandler.java b/data-services/src/main/java/com/atg/openssp/dataprovider/provider/handler/CurrencyDataHandler.java new file mode 100644 index 00000000..33f5bbd2 --- /dev/null +++ b/data-services/src/main/java/com/atg/openssp/dataprovider/provider/handler/CurrencyDataHandler.java @@ -0,0 +1,69 @@ +package com.atg.openssp.dataprovider.provider.handler; + +import com.atg.openssp.core.cache.broker.dto.CurrencyDto; +import com.atg.openssp.core.system.LocalContext; +import com.google.gson.Gson; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import util.properties.ProjectProperty; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.xml.bind.PropertyException; +import java.io.IOException; +import java.io.OutputStream; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.Map; + +/** + * @author Brian Sorensen + */ +public class CurrencyDataHandler extends DataHandler { + private static final Logger log = LoggerFactory.getLogger(CurrencyDataHandler.class); + public static final String CONTEXT = "/lookup/eurref"; + + public CurrencyDataHandler(HttpServletRequest request, HttpServletResponse response) { + if (LocalContext.isCurrencyDataServiceEnabled()) { + try { + String location; + try { + location = ProjectProperty.getPropertiesResourceLocation()+"/"; + } catch (PropertyException e) { + log.warn("property file not found."); + location=""; + } + Gson gson = new Gson(); + String content = new String(Files.readAllBytes(Paths.get(location+"currency_db.json")), StandardCharsets.UTF_8); + CurrencyDto data = gson.fromJson(content, CurrencyDto.class); + + Map parms = queryToMap(request.getQueryString()); + String t = parms.get("t"); + + if (LoginHandler.TOKEN.equals(t)) { + String result = new Gson().toJson(data); + + response.setStatus(200); + response.setContentType("application/json; charset=UTF8"); + OutputStream os = response.getOutputStream(); + os.write(result.getBytes()); + os.close(); + } else { + response.setStatus(401); + } + } catch (IOException e) { + response.setStatus(500); + log.error(e.getMessage(), e); + } + } else { + response.setStatus(404); + } + } + + @Override + public void cleanUp() { + + } + +} diff --git a/data-services/src/main/java/com/atg/openssp/dataprovider/provider/handler/DataHandler.java b/data-services/src/main/java/com/atg/openssp/dataprovider/provider/handler/DataHandler.java new file mode 100644 index 00000000..9aba9e78 --- /dev/null +++ b/data-services/src/main/java/com/atg/openssp/dataprovider/provider/handler/DataHandler.java @@ -0,0 +1,94 @@ +package com.atg.openssp.dataprovider.provider.handler; + +import javax.servlet.http.HttpServletRequest; +import java.io.*; +import java.net.URLDecoder; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @author André Schmer + */ +public abstract class DataHandler { + public abstract void cleanUp(); + + protected static Map queryToMap(String query){ + Map result = new HashMap(); + if (query != null) { + for (String param : query.split("&")) { + String pair[] = param.split("="); + if (pair.length>1) { + result.put(pair[0], pair[1]); + }else{ + result.put(pair[0], ""); + } + } + } + return result; + } + + protected static String queryFromBodyString(InputStream is){ + BufferedReader br = new BufferedReader(new InputStreamReader(is)); + String query; + try { + query = br.readLine(); + } catch (IOException e) { + e.printStackTrace(); + query=""; + } + return query; + } + + protected static Map attributesToMap(HttpServletRequest request){ + Map result = (Map) request.getAttribute("attributes"); + if (result == null) { + result = new HashMap(); + } + return result; + } + + protected void populateFromBody(Map parameters, String query) { + if (query != null) { + String pairs[] = query.split("[&]"); + + for (String pair : pairs) { + String param[] = pair.split("[=]"); + + String key = null; + String value = null; + if (param.length > 0) { + try { + key = URLDecoder.decode(param[0], "UTF-8"); + } catch (UnsupportedEncodingException e) { + key = param[0]; + } + } + + if (param.length > 1) { + try { + value = URLDecoder.decode(param[1], "UTF-8"); + } catch (UnsupportedEncodingException e) { + value = param[1]; + } + } + + if (parameters.containsKey(key)) { + Object obj = parameters.get(key); + if(obj instanceof List) { + List values = (List)obj; + values.add(value); + } else if(obj instanceof String) { + List values = new ArrayList(); + values.add((String)obj); + values.add(value); + } + } else { + parameters.put(key, value); + } + } + } + } + +} diff --git a/data-services/src/main/java/com/atg/openssp/dataprovider/provider/handler/LoginHandler.java b/data-services/src/main/java/com/atg/openssp/dataprovider/provider/handler/LoginHandler.java new file mode 100644 index 00000000..4455ebd2 --- /dev/null +++ b/data-services/src/main/java/com/atg/openssp/dataprovider/provider/handler/LoginHandler.java @@ -0,0 +1,67 @@ +package com.atg.openssp.dataprovider.provider.handler; + +import com.atg.openssp.core.system.LocalContext; +import com.atg.openssp.dataprovider.provider.dto.TokenWrapper; +import com.google.gson.Gson; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.OutputStream; +import java.util.Map; + +/** + * @author André Schmer + */ +public class LoginHandler extends DataHandler { + private static final Logger log = LoggerFactory.getLogger(LoginHandler.class); + public static final String TOKEN = "liverworst-5"; + public static final String CONTEXT = "/login/token"; + + public LoginHandler(HttpServletRequest request, HttpServletResponse response) { + if (LocalContext.isLoginServiceEnabled()) { + try { + Map parms; + if ("POST".equalsIgnoreCase(request.getMethod())) { + String body = queryFromBodyString(request.getInputStream()); + parms = attributesToMap(request); + populateFromBody(parms, body); + } else { + parms = queryToMap(request.getQueryString()); + } + String user = parms.get("u"); + String pw = parms.get("p"); + if (!isAuthorized(user, pw)) { + response.setStatus(401); + } else { + TokenWrapper token = new TokenWrapper(); + token.setToken(TOKEN); + String result = new Gson().toJson(token); + response.setContentType("application/json; charset=UTF8"); + response.setStatus(200); + response.setContentLength(result.length()); + OutputStream os = response.getOutputStream(); + os.write(result.getBytes()); + os.close(); + } + } catch (IOException e) { + response.setStatus(500); + log.error(e.getMessage(), e); + } + } else { + response.setStatus(404); + } + } + + @Override + public void cleanUp() { + + } + + private boolean isAuthorized(String user, String pw) { + return user != null && "izod".equals(user) && pw != null && "frogs".equals(pw); + } + +} diff --git a/data-services/src/main/java/com/atg/openssp/dataprovider/provider/handler/PricelayerDataHandler.java b/data-services/src/main/java/com/atg/openssp/dataprovider/provider/handler/PricelayerDataHandler.java new file mode 100644 index 00000000..85c0264e --- /dev/null +++ b/data-services/src/main/java/com/atg/openssp/dataprovider/provider/handler/PricelayerDataHandler.java @@ -0,0 +1,69 @@ +package com.atg.openssp.dataprovider.provider.handler; + +import com.atg.openssp.core.cache.broker.dto.PricelayerDto; +import com.atg.openssp.core.system.LocalContext; +import com.google.gson.Gson; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import util.properties.ProjectProperty; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.xml.bind.PropertyException; +import java.io.IOException; +import java.io.OutputStream; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.Map; + +/** + * @author André Schmer + */ +public class PricelayerDataHandler extends DataHandler { + private static final Logger log = LoggerFactory.getLogger(PricelayerDataHandler.class); + public static final String CONTEXT = "/lookup/pricelayer"; + + public PricelayerDataHandler(HttpServletRequest request, HttpServletResponse response) { + if (LocalContext.isPricelayerDataServiceEnabled()) { + try { + String location; + try { + location = ProjectProperty.getPropertiesResourceLocation()+"/"; + } catch (PropertyException e) { + log.warn("property file not found."); + location=""; + } + Gson gson = new Gson(); + String content = new String(Files.readAllBytes(Paths.get(location+"price_layer.json")), StandardCharsets.UTF_8); + PricelayerDto data = gson.fromJson(content, PricelayerDto.class); + + Map parms = queryToMap(request.getQueryString()); + String t = parms.get("t"); + + if (LoginHandler.TOKEN.equals(t)) { + String result = new Gson().toJson(data); + + response.setStatus(200); + response.setContentType("application/json; charset=UTF8"); + OutputStream os = response.getOutputStream(); + os.write(result.getBytes()); + os.close(); + } else { + response.setStatus(401); + } + } catch (IOException e) { + response.setStatus(500); + log.error(e.getMessage(), e); + } + } else { + response.setStatus(404); + } + } + + @Override + public void cleanUp() { + + } + +} diff --git a/data-services/src/main/java/com/atg/openssp/dataprovider/provider/handler/SiteDataHandler.java b/data-services/src/main/java/com/atg/openssp/dataprovider/provider/handler/SiteDataHandler.java new file mode 100644 index 00000000..b4212770 --- /dev/null +++ b/data-services/src/main/java/com/atg/openssp/dataprovider/provider/handler/SiteDataHandler.java @@ -0,0 +1,69 @@ +package com.atg.openssp.dataprovider.provider.handler; + +import com.atg.openssp.core.cache.broker.dto.SiteDto; +import com.atg.openssp.core.system.LocalContext; +import com.google.gson.Gson; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import util.properties.ProjectProperty; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.xml.bind.PropertyException; +import java.io.IOException; +import java.io.OutputStream; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.Map; + +/** + * @author André Schmer + */ +public class SiteDataHandler extends DataHandler { + private static final Logger log = LoggerFactory.getLogger(SiteDataHandler.class); + public static final String CONTEXT = "/lookup/site"; + + public SiteDataHandler(HttpServletRequest request, HttpServletResponse response) { + if (LocalContext.isSiteDataServiceEnabled()) { + try { + String location; + try { + location = ProjectProperty.getPropertiesResourceLocation()+"/"; + } catch (PropertyException e) { + log.warn("property file not found."); + location=""; + } + Gson gson = new Gson(); + String content = new String(Files.readAllBytes(Paths.get(location+"site_db.json")), StandardCharsets.UTF_8); + SiteDto data = gson.fromJson(content, SiteDto.class); + + Map parms = queryToMap(request.getQueryString()); + String t = parms.get("t"); + + if (LoginHandler.TOKEN.equals(t)) { + String result = new Gson().toJson(data); + + response.setStatus(200); + response.setContentType("application/json; charset=UTF8"); + OutputStream os = response.getOutputStream(); + os.write(result.getBytes()); + os.close(); + } else { + response.setStatus(401); + } + } catch (IOException e) { + response.setStatus(500); + log.error(e.getMessage(), e); + } + } else { + response.setStatus(404); + } + } + + @Override + public void cleanUp() { + + } + +} diff --git a/data-services/src/main/java/com/atg/openssp/dataprovider/provider/handler/SupplierDataHandler.java b/data-services/src/main/java/com/atg/openssp/dataprovider/provider/handler/SupplierDataHandler.java new file mode 100644 index 00000000..83bce000 --- /dev/null +++ b/data-services/src/main/java/com/atg/openssp/dataprovider/provider/handler/SupplierDataHandler.java @@ -0,0 +1,69 @@ +package com.atg.openssp.dataprovider.provider.handler; + +import com.atg.openssp.core.cache.broker.dto.SupplierDto; +import com.atg.openssp.core.system.LocalContext; +import com.google.gson.Gson; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import util.properties.ProjectProperty; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.xml.bind.PropertyException; +import java.io.IOException; +import java.io.OutputStream; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.Map; + +/** + * @author André Schmer + */ +public class SupplierDataHandler extends DataHandler { + private static final Logger log = LoggerFactory.getLogger(SupplierDataHandler.class); + public static final String CONTEXT = "/lookup/supplier"; + + public SupplierDataHandler(HttpServletRequest request, HttpServletResponse response) { + if (LocalContext.isSupplierDataServiceEnabled()) { + try { + String location; + try { + location = ProjectProperty.getPropertiesResourceLocation()+"/"; + } catch (PropertyException e) { + log.warn("property file not found."); + location=""; + } + Gson gson = new Gson(); + String content = new String(Files.readAllBytes(Paths.get(location+"supplier_db.json")), StandardCharsets.UTF_8); + SupplierDto data = gson.fromJson(content, SupplierDto.class); + + Map parms = queryToMap(request.getQueryString()); + String t = parms.get("t"); + + if (LoginHandler.TOKEN.equals(t)) { + String result = new Gson().toJson(data); + + response.setStatus(200); + response.setContentType("application/json; charset=UTF8"); + OutputStream os = response.getOutputStream(); + os.write(result.getBytes()); + os.close(); + } else { + response.setStatus(401); + } + } catch (IOException e) { + response.setStatus(500); + log.error(e.getMessage(), e); + } + } else { + response.setStatus(404); + } + } + + @Override + public void cleanUp() { + + } + +} diff --git a/data-services/src/main/java/com/atg/openssp/dataprovider/service/AppDataService.java b/data-services/src/main/java/com/atg/openssp/dataprovider/service/AppDataService.java new file mode 100644 index 00000000..ba499834 --- /dev/null +++ b/data-services/src/main/java/com/atg/openssp/dataprovider/service/AppDataService.java @@ -0,0 +1,48 @@ +package com.atg.openssp.dataprovider.service; + +import com.atg.openssp.common.exception.RequestException; +import com.atg.openssp.core.system.LocalContext; +import com.atg.openssp.dataprovider.provider.handler.AppDataHandler; +import com.atg.openssp.dataprovider.provider.handler.DataHandler; + +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; + +/** + * Servlet implementation class AppDataService + * + * @author Brian Sorensen + */ +@WebServlet(value = AppDataHandler.CONTEXT, asyncSupported = false, name = "AppData-Service") +public class AppDataService extends CoreDataServlet { + + private static final long serialVersionUID = 1L; + + @Override + protected DataHandler getHandler(final HttpServletRequest request, final HttpServletResponse response) throws RequestException { + String handlerClassName = LocalContext.getAppDataHandlerClass(); + if (handlerClassName == null) { + return new AppDataHandler(request, response); + } else { + try { + Class handlerClass = Class.forName(handlerClassName); + Constructor cc = handlerClass.getConstructor(new Class[]{HttpServletRequest.class, HttpServletResponse.class}); + return (DataHandler) cc.newInstance(new Object[]{request, response}); + } catch (ClassNotFoundException e) { + throw new RequestException(e.getMessage()); + } catch (NoSuchMethodException e) { + throw new RequestException(e.getMessage()); + } catch (IllegalAccessException e) { + throw new RequestException(e.getMessage()); + } catch (InstantiationException e) { + throw new RequestException(e.getMessage()); + } catch (InvocationTargetException e) { + throw new RequestException(e.getMessage()); + } + } + } + +} diff --git a/data-services/src/main/java/com/atg/openssp/dataprovider/service/CoreDataServlet.java b/data-services/src/main/java/com/atg/openssp/dataprovider/service/CoreDataServlet.java new file mode 100644 index 00000000..3df38e1a --- /dev/null +++ b/data-services/src/main/java/com/atg/openssp/dataprovider/service/CoreDataServlet.java @@ -0,0 +1,61 @@ +package com.atg.openssp.dataprovider.service; + +import com.atg.openssp.common.buffer.SSPLatencyBuffer; +import com.atg.openssp.common.exception.RequestException; +import com.google.common.base.Stopwatch; +import com.atg.openssp.dataprovider.provider.handler.DataHandler; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.concurrent.TimeUnit; + +/** + * Servlet abstract class CoreDataServlet + * + * @author André Schmer + */ +public abstract class CoreDataServlet extends HttpServlet { + private static final Logger log = LoggerFactory.getLogger(CoreDataServlet.class); + + @Override + public void init() throws ServletException { + } + + @Override + protected void doGet(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException { + + final Stopwatch stopwatch = Stopwatch.createStarted(); + T handler = null; + boolean hasResult = false; + try { + handler = getHandler(request, response); + } catch (final RequestException e) { + log.error(e.getMessage()); + e.printStackTrace(); + } finally { + stopwatch.stop(); + if (hasResult) { + SSPLatencyBuffer.getBuffer().bufferValue(stopwatch.elapsed(TimeUnit.MILLISECONDS)); + } + if (handler != null) { + handler.cleanUp(); + } + handler = null; + } + + } + + @Override + protected void doPost(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException { + doGet(request, response); + } + + + protected abstract T getHandler(HttpServletRequest request, HttpServletResponse response) throws RequestException; + +} diff --git a/data-services/src/main/java/com/atg/openssp/dataprovider/service/CurrencyDataService.java b/data-services/src/main/java/com/atg/openssp/dataprovider/service/CurrencyDataService.java new file mode 100644 index 00000000..1246d380 --- /dev/null +++ b/data-services/src/main/java/com/atg/openssp/dataprovider/service/CurrencyDataService.java @@ -0,0 +1,49 @@ +package com.atg.openssp.dataprovider.service; + +import com.atg.openssp.common.exception.RequestException; +import com.atg.openssp.core.system.LocalContext; +import com.atg.openssp.dataprovider.provider.handler.AppDataHandler; +import com.atg.openssp.dataprovider.provider.handler.CurrencyDataHandler; +import com.atg.openssp.dataprovider.provider.handler.DataHandler; + +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; + +/** + * Servlet implementation class CurrencyDataService + * + * @author Brian Sorensen + */ +@WebServlet(value = CurrencyDataHandler.CONTEXT, asyncSupported = false, name = "CurrencyData-Service") +public class CurrencyDataService extends CoreDataServlet { + + private static final long serialVersionUID = 1L; + + @Override + protected DataHandler getHandler(final HttpServletRequest request, final HttpServletResponse response) throws RequestException { + String handlerClassName = LocalContext.getCurrencyDataHandlerClass(); + if (handlerClassName == null) { + return new CurrencyDataHandler(request, response); + } else { + try { + Class handlerClass = Class.forName(handlerClassName); + Constructor cc = handlerClass.getConstructor(new Class[]{HttpServletRequest.class, HttpServletResponse.class}); + return (DataHandler) cc.newInstance(new Object[]{request, response}); + } catch (ClassNotFoundException e) { + throw new RequestException(e.getMessage()); + } catch (NoSuchMethodException e) { + throw new RequestException(e.getMessage()); + } catch (IllegalAccessException e) { + throw new RequestException(e.getMessage()); + } catch (InstantiationException e) { + throw new RequestException(e.getMessage()); + } catch (InvocationTargetException e) { + throw new RequestException(e.getMessage()); + } + } + } + +} diff --git a/data-services/src/main/java/com/atg/openssp/dataprovider/service/LoginService.java b/data-services/src/main/java/com/atg/openssp/dataprovider/service/LoginService.java new file mode 100644 index 00000000..12c953fb --- /dev/null +++ b/data-services/src/main/java/com/atg/openssp/dataprovider/service/LoginService.java @@ -0,0 +1,48 @@ +package com.atg.openssp.dataprovider.service; + +import com.atg.openssp.common.exception.RequestException; +import com.atg.openssp.core.system.LocalContext; +import com.atg.openssp.dataprovider.provider.handler.LoginHandler; +import com.atg.openssp.dataprovider.provider.handler.DataHandler; + +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; + +/** + * Servlet implementation class LoginService + * + * @author Brian Sorensen + */ +@WebServlet(value = LoginHandler.CONTEXT, asyncSupported = false, name = "Login-Service") +public class LoginService extends CoreDataServlet { + + private static final long serialVersionUID = 1L; + + @Override + protected DataHandler getHandler(final HttpServletRequest request, final HttpServletResponse response) throws RequestException { + String handlerClassName = LocalContext.getLoginHandlerClass(); + if (handlerClassName == null) { + return new LoginHandler(request, response); + } else { + try { + Class handlerClass = Class.forName(handlerClassName); + Constructor cc = handlerClass.getConstructor(new Class[]{HttpServletRequest.class, HttpServletResponse.class}); + return (DataHandler) cc.newInstance(new Object[]{request, response}); + } catch (ClassNotFoundException e) { + throw new RequestException(e.getMessage()); + } catch (NoSuchMethodException e) { + throw new RequestException(e.getMessage()); + } catch (IllegalAccessException e) { + throw new RequestException(e.getMessage()); + } catch (InstantiationException e) { + throw new RequestException(e.getMessage()); + } catch (InvocationTargetException e) { + throw new RequestException(e.getMessage()); + } + } + } + +} diff --git a/data-services/src/main/java/com/atg/openssp/dataprovider/service/PricelayerDataService.java b/data-services/src/main/java/com/atg/openssp/dataprovider/service/PricelayerDataService.java new file mode 100644 index 00000000..75277cb2 --- /dev/null +++ b/data-services/src/main/java/com/atg/openssp/dataprovider/service/PricelayerDataService.java @@ -0,0 +1,49 @@ +package com.atg.openssp.dataprovider.service; + +import com.atg.openssp.common.exception.RequestException; +import com.atg.openssp.core.system.LocalContext; +import com.atg.openssp.dataprovider.provider.handler.AppDataHandler; +import com.atg.openssp.dataprovider.provider.handler.DataHandler; +import com.atg.openssp.dataprovider.provider.handler.PricelayerDataHandler; + +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; + +/** + * Servlet implementation class PricelayerService + * + * @author Brian Sorensen + */ +@WebServlet(value = PricelayerDataHandler.CONTEXT, asyncSupported = false, name = "PricelayerData-Service") +public class PricelayerDataService extends CoreDataServlet { + + private static final long serialVersionUID = 1L; + + @Override + protected DataHandler getHandler(final HttpServletRequest request, final HttpServletResponse response) throws RequestException { + String handlerClassName = LocalContext.getPricelayerDataHandlerClass(); + if (handlerClassName == null) { + return new PricelayerDataHandler(request, response); + } else { + try { + Class handlerClass = Class.forName(handlerClassName); + Constructor cc = handlerClass.getConstructor(new Class[]{HttpServletRequest.class, HttpServletResponse.class}); + return (DataHandler) cc.newInstance(new Object[]{request, response}); + } catch (ClassNotFoundException e) { + throw new RequestException(e.getMessage()); + } catch (NoSuchMethodException e) { + throw new RequestException(e.getMessage()); + } catch (IllegalAccessException e) { + throw new RequestException(e.getMessage()); + } catch (InstantiationException e) { + throw new RequestException(e.getMessage()); + } catch (InvocationTargetException e) { + throw new RequestException(e.getMessage()); + } + } + } + +} diff --git a/data-services/src/main/java/com/atg/openssp/dataprovider/service/SiteDataService.java b/data-services/src/main/java/com/atg/openssp/dataprovider/service/SiteDataService.java new file mode 100644 index 00000000..a2a7f8d9 --- /dev/null +++ b/data-services/src/main/java/com/atg/openssp/dataprovider/service/SiteDataService.java @@ -0,0 +1,49 @@ +package com.atg.openssp.dataprovider.service; + +import com.atg.openssp.common.exception.RequestException; +import com.atg.openssp.core.system.LocalContext; +import com.atg.openssp.dataprovider.provider.handler.AppDataHandler; +import com.atg.openssp.dataprovider.provider.handler.DataHandler; +import com.atg.openssp.dataprovider.provider.handler.SiteDataHandler; + +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; + +/** + * Servlet implementation class SiteVideoService + * + * @author Brian Sorensen + */ +@WebServlet(value = SiteDataHandler.CONTEXT, asyncSupported = false, name = "SiteData-Service") +public class SiteDataService extends CoreDataServlet { + + private static final long serialVersionUID = 1L; + + @Override + protected DataHandler getHandler(final HttpServletRequest request, final HttpServletResponse response) throws RequestException { + String handlerClassName = LocalContext.getSiteDataHandlerClass(); + if (handlerClassName == null) { + return new SiteDataHandler(request, response); + } else { + try { + Class handlerClass = Class.forName(handlerClassName); + Constructor cc = handlerClass.getConstructor(new Class[]{HttpServletRequest.class, HttpServletResponse.class}); + return (DataHandler) cc.newInstance(new Object[]{request, response}); + } catch (ClassNotFoundException e) { + throw new RequestException(e.getMessage()); + } catch (NoSuchMethodException e) { + throw new RequestException(e.getMessage()); + } catch (IllegalAccessException e) { + throw new RequestException(e.getMessage()); + } catch (InstantiationException e) { + throw new RequestException(e.getMessage()); + } catch (InvocationTargetException e) { + throw new RequestException(e.getMessage()); + } + } + } + +} diff --git a/data-services/src/main/java/com/atg/openssp/dataprovider/service/SupplierDataService.java b/data-services/src/main/java/com/atg/openssp/dataprovider/service/SupplierDataService.java new file mode 100644 index 00000000..cdde7ed4 --- /dev/null +++ b/data-services/src/main/java/com/atg/openssp/dataprovider/service/SupplierDataService.java @@ -0,0 +1,49 @@ +package com.atg.openssp.dataprovider.service; + +import com.atg.openssp.common.exception.RequestException; +import com.atg.openssp.core.system.LocalContext; +import com.atg.openssp.dataprovider.provider.handler.AppDataHandler; +import com.atg.openssp.dataprovider.provider.handler.SupplierDataHandler; +import com.atg.openssp.dataprovider.provider.handler.DataHandler; + +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; + +/** + * Servlet implementation class SupplierDataService + * + * @author Brian Sorensen + */ +@WebServlet(value = SupplierDataHandler.CONTEXT, asyncSupported = false, name = "SupplierData-Service") +public class SupplierDataService extends CoreDataServlet { + + private static final long serialVersionUID = 1L; + + @Override + protected DataHandler getHandler(final HttpServletRequest request, final HttpServletResponse response) throws RequestException { + String handlerClassName = LocalContext.getSupplierDataHandlerClass(); + if (handlerClassName == null) { + return new SupplierDataHandler(request, response); + } else { + try { + Class handlerClass = Class.forName(handlerClassName); + Constructor cc = handlerClass.getConstructor(new Class[]{HttpServletRequest.class, HttpServletResponse.class}); + return (DataHandler) cc.newInstance(new Object[]{request, response}); + } catch (ClassNotFoundException e) { + throw new RequestException(e.getMessage()); + } catch (NoSuchMethodException e) { + throw new RequestException(e.getMessage()); + } catch (IllegalAccessException e) { + throw new RequestException(e.getMessage()); + } catch (InstantiationException e) { + throw new RequestException(e.getMessage()); + } catch (InvocationTargetException e) { + throw new RequestException(e.getMessage()); + } + } + } + +} diff --git a/data-services/src/main/java/com/atg/openssp/dataprovider/system/InitLogging.java b/data-services/src/main/java/com/atg/openssp/dataprovider/system/InitLogging.java new file mode 100644 index 00000000..912389a6 --- /dev/null +++ b/data-services/src/main/java/com/atg/openssp/dataprovider/system/InitLogging.java @@ -0,0 +1,20 @@ +package com.atg.openssp.dataprovider.system; + +import util.CatalinaUtil; + +/** + * @author André Schmer + * + */ +class InitLogging { + + static void setSystemProperties() { + System.setProperty("tomcatid", CatalinaUtil.instanceName()); + if (false == "localhost".equals(CatalinaUtil.instanceName())) { + System.setProperty("log4j.configurationFile", CatalinaUtil.catalinaHome() + "/properties/log4j2.xml"); + } + System.setProperty("Log4jContextSelector", "org.apache.logging.log4j.core.async.AsyncLoggerContextSelector"); + System.setProperty("pid", CatalinaUtil.pid()); + } + +} diff --git a/data-services/src/main/java/com/atg/openssp/dataprovider/system/ServicesInit.java b/data-services/src/main/java/com/atg/openssp/dataprovider/system/ServicesInit.java new file mode 100644 index 00000000..0c277fb8 --- /dev/null +++ b/data-services/src/main/java/com/atg/openssp/dataprovider/system/ServicesInit.java @@ -0,0 +1,55 @@ +package com.atg.openssp.dataprovider.system; + +import com.atg.openssp.core.system.job.WatchdogService; +import com.atg.openssp.core.system.loader.ConfigLoader; +import com.atg.openssp.core.system.loader.GlobalContextLoader; +import com.atg.openssp.core.system.loader.LocalContextLoader; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.servlet.GenericServlet; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import java.io.IOException; +import java.util.concurrent.CountDownLatch; + +/** + * Servlet implementation class AppDataService + * + * @author Brian Sorensen + */ +public class ServicesInit extends GenericServlet { + + private final Logger log = LoggerFactory.getLogger(ServicesInit.class); + + @Override + public void init() throws ServletException { + InitLogging.setSystemProperties(); + log.info("**** Initing core application ****"); + //LocalContext.setVersion(new MavenProperties().getVersion()); + //log.info("**** SSP Version: " + LocalContext.getVersion() + " ****"); + + final CountDownLatch cdl = new CountDownLatch(3); + // loading static config + new ConfigLoader(cdl).readValues(); + // initing watchdogs for global.runtime.xml and local.runtime.xml + WatchdogService.instance.initLoaderWatchdog(new LocalContextLoader(cdl), true).initLoaderWatchdog(new GlobalContextLoader(cdl), true).startWatchdogs(); + try { + cdl.await(); + } catch (final InterruptedException e) { + log.error(e.getMessage()); + } + super.init(); + } + + @Override + public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException { + } + + @Override + public void destroy() { + super.destroy(); + } + +} diff --git a/data-services/src/main/resources/app_db.json b/data-services/src/main/resources/app_db.json new file mode 100644 index 00000000..772cf6f7 --- /dev/null +++ b/data-services/src/main/resources/app_db.json @@ -0,0 +1,7 @@ +{ + "apps": [ + { + "id": "1" + } + ] +} \ No newline at end of file diff --git a/data-services/src/main/resources/config.xml b/data-services/src/main/resources/config.xml new file mode 100644 index 00000000..02226fed --- /dev/null +++ b/data-services/src/main/resources/config.xml @@ -0,0 +1,10 @@ + + + + + + + + + false + diff --git a/data-services/src/main/resources/currency_db.json b/data-services/src/main/resources/currency_db.json new file mode 100644 index 00000000..6ff313b3 --- /dev/null +++ b/data-services/src/main/resources/currency_db.json @@ -0,0 +1,8 @@ +{ + "currency": "USD", + "data": [{ + "currency": "EUR", + "rate": 0.80 + } + ] +} \ No newline at end of file diff --git a/data-services/src/main/resources/global.runtime.xml b/data-services/src/main/resources/global.runtime.xml new file mode 100644 index 00000000..a64b60fb --- /dev/null +++ b/data-services/src/main/resources/global.runtime.xml @@ -0,0 +1,16 @@ + + + + + + + + + + 0.3 + + + + 500 + + diff --git a/data-services/src/main/resources/local.runtime.xml b/data-services/src/main/resources/local.runtime.xml new file mode 100644 index 00000000..82df3703 --- /dev/null +++ b/data-services/src/main/resources/local.runtime.xml @@ -0,0 +1,46 @@ + + + + + true + + + true + + + true + + + true + + + true + + + true + + + com.atg.openssp.dataprovider.provider.handler.AppDataHandler + + + com.atg.openssp.dataprovider.provider.handler.CurrencyDataHandler + + + com.atg.openssp.dataprovider.provider.handler.LoginHandler + + + com.atg.openssp.dataprovider.provider.handler.PricelayerDataHandler + + + com.atg.openssp.dataprovider.provider.handler.SiteDataHandler + + + com.atg.openssp.dataprovider.provider.handler.SupplierDataHandler + + + true + + + false + + diff --git a/data-services/src/main/resources/log4j2.xml b/data-services/src/main/resources/log4j2.xml new file mode 100644 index 00000000..6e78dd7b --- /dev/null +++ b/data-services/src/main/resources/log4j2.xml @@ -0,0 +1,200 @@ + + + + + + + + + + + + + + + + + + [%d] %m%n + + + + + + + + + + + + + + [%d]%m%n + + + + + + + + + + + + [%d]%m%n + + + + + + + + + + + + + [%d]%m%n + + + + + + + + + + + + + [%d]%m%n + + + + + + + + + + + + + [%d]#%m%n + + + + + + + + + + + [%d] %C{1.} %m%n + + + + + + + + + + [%d]#%m%n + + + + + + + + + + + + + %m%n + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/data-services/src/main/resources/price_layer.json b/data-services/src/main/resources/price_layer.json new file mode 100644 index 00000000..f6b0ba01 --- /dev/null +++ b/data-services/src/main/resources/price_layer.json @@ -0,0 +1,8 @@ +{ + "pricelayer": [{ + "siteid": "1", + "bidfloor": 1.2, + "currency": "USD" + } + ] +} \ No newline at end of file diff --git a/data-services/src/main/resources/site_db.json b/data-services/src/main/resources/site_db.json new file mode 100644 index 00000000..36b49377 --- /dev/null +++ b/data-services/src/main/resources/site_db.json @@ -0,0 +1,33 @@ +{ + "sites": [{ + "id": "1", + "name": "site_1", + "domain": "site_1.com", + "cat": ["1"], + "page": "www.site_1.com", + "publisher": { + "id": "pubisher_1", + "name": "publisher_1_name", + "cat": [], + "domain": "www.publisher_1.com", + "ext": null + }, + "ext": null + }, + { + "id": "testsite.com", + "name": "testsite.com", + "domain": "testsite.com", + "cat": ["1"], + "page": "http://alexs-mbp:8000/integrationExamples/gpt/freestar_hello_world.html", + "publisher": { + "id": "testpublisher_1", + "name": "testpublisher 1", + "cat": [], + "domain": "www.testpublisher_1.com", + "ext": null + }, + "ext": null + } + ] +} \ No newline at end of file diff --git a/data-services/src/main/resources/supplier_db.json b/data-services/src/main/resources/supplier_db.json new file mode 100644 index 00000000..5356f6ef --- /dev/null +++ b/data-services/src/main/resources/supplier_db.json @@ -0,0 +1,14 @@ +{ + "supplier": [{ + "shortName": "dsp_1", + "endPoint": "http://localhost:8082/dsp-sim/DemandService", + "connectionKeepAlive": true, + "openRtbVersion": 2.2, + "contentType": "application/json", + "supplierId": "1", + "currency": "USD", + "underTest": 1, + "active": 1 + } + ] +} diff --git a/data-services/src/main/webapp/WEB-INF/web.xml b/data-services/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 00000000..81967bff --- /dev/null +++ b/data-services/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,9 @@ + + + ATG SSP + + ServicesInit + com.atg.openssp.dataprovider.system.ServicesInit + 1 + + \ No newline at end of file diff --git a/data-sim-client/pom.xml b/data-sim-client/pom.xml new file mode 100644 index 00000000..92ae2668 --- /dev/null +++ b/data-sim-client/pom.xml @@ -0,0 +1,91 @@ + + + 4.0.0 + com.atg.openssp + open-ssp-dsp-sim-client + 0.1 + open-ssp-dsp-sim-client + http://maven.apache.org + + UTF-8 + + + + + junit + junit + 3.8.1 + test + + + com.google.code.gson + gson + 2.6.2 + + + org.apache.logging.log4j + log4j-core + 2.6.2 + + + org.apache.logging.log4j + log4j-slf4j-impl + 2.8 + + + com.atg.openssp + open-ssp-common + 0.3 + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.5.1 + + 1.8 + 1.8 + + + + org.apache.maven.plugins + maven-dependency-plugin + + + copy-dependencies + prepare-package + + copy-dependencies + + + ${project.build.directory}/lib + false + false + true + + + + + + org.apache.maven.plugins + maven-jar-plugin + 3.0.2 + + + + true + + lib/ + com.atg.openssp.dspSim.DspSimClient + + + + + + + diff --git a/data-sim-client/run_sim.sh b/data-sim-client/run_sim.sh new file mode 100755 index 00000000..af3cb3eb --- /dev/null +++ b/data-sim-client/run_sim.sh @@ -0,0 +1,3 @@ + +java -jar target/open-ssp-dsp-sim-client-0.1-SNAPSHOT.jar + diff --git a/data-sim-client/src/main/java/com/atg/openssp/dspSim/DspSimClient.java b/data-sim-client/src/main/java/com/atg/openssp/dspSim/DspSimClient.java new file mode 100644 index 00000000..1dabe954 --- /dev/null +++ b/data-sim-client/src/main/java/com/atg/openssp/dspSim/DspSimClient.java @@ -0,0 +1,63 @@ +package com.atg.openssp.dspSim; + +import com.atg.openssp.dspSim.model.ModelException; +import com.atg.openssp.dspSim.model.ad.AdModel; +import com.atg.openssp.dspSim.model.dsp.DspModel; +import com.atg.openssp.dspSim.view.dsp.DspView; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; + +/** + * @author Brian Sorensen + */ +public class DspSimClient { + private static final Logger log = LoggerFactory.getLogger(DspSimClient.class); + private final Properties props = new Properties(); + private final DspView dspView; + private DspModel dspModel; + private AdModel adModel; + + public DspSimClient() throws ModelException { + load(props); + dspModel = new DspModel(props); + dspView = new DspView(dspModel); + adModel = new AdModel(props); + } + + private void load(Properties p) { + try { + File file = new File("DspSimClient.properties"); + InputStream is; + if (file.exists()) { + is = new FileInputStream(file); + } else { + is = getClass().getClassLoader().getSystemResourceAsStream("DspSimClient.properties"); + } + p.load(is); + is.close(); + } catch (IOException e) { + log.warn("Could not load properties file.", e); + } + } + + public void start() { + dspView.start(); + dspModel.start(); + } + + public static void main(String[] args) { + try { + DspSimClient sim = new DspSimClient(); + sim.start(); + } catch (ModelException e) { + log.error(e.getMessage(), e); + } + } + +} \ No newline at end of file diff --git a/data-sim-client/src/main/java/com/atg/openssp/dspSim/ServerHandler.java b/data-sim-client/src/main/java/com/atg/openssp/dspSim/ServerHandler.java new file mode 100644 index 00000000..be25bafc --- /dev/null +++ b/data-sim-client/src/main/java/com/atg/openssp/dspSim/ServerHandler.java @@ -0,0 +1,114 @@ +package com.atg.openssp.dspSim; + +import com.atg.openssp.dspSim.model.ModelException; +import com.atg.openssp.dspSim.model.client.ServerCommand; +import com.atg.openssp.dspSim.model.client.ServerCommandType; +import com.atg.openssp.dspSim.model.client.ServerResponse; +import com.atg.openssp.dspSim.model.client.ServerResponseStatus; +import com.atg.openssp.dspSim.model.dsp.DspModel; +import com.atg.openssp.dspSim.model.dsp.SimBidder; +import com.google.gson.Gson; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.util.EntityUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; + +/** + * @author Brian Sorensen + */ +public class ServerHandler implements Runnable { + private static final Logger log = LoggerFactory.getLogger(ServerHandler.class); + private static final String SERVER_HOST = "server-host"; + private static final String SERVER_PORT = "server-port"; + private final Thread t = new Thread(this); + private final DspModel model; + private boolean running; + + public ServerHandler(DspModel model) { + this.model = model; + t.setName("ServerHandler"); + t.setDaemon(true); + } + + public void start() { + if (!running) { + t.start(); + } + } + + @Override + public void run() { + running = true; + while(running) { + try { + sendListCommand(); + } catch (ModelException e) { + log.warn(e.getMessage(), e); + } + try { + Thread.sleep(90000); + } catch (InterruptedException e) { + running = false; + } + Thread.yield(); + } + } + + private void sendListCommand() throws ModelException { + sendCommand(ServerCommandType.LIST, "", 0); + } + + public void sendAddCommand(SimBidder sb) throws ModelException { + sendCommand(ServerCommandType.ADD, sb.getId(), sb.getPrice()); + } + + public void sendRemoveCommand(SimBidder sb) throws ModelException { + sendCommand(ServerCommandType.REMOVE, sb.getId(), sb.getPrice()); + } + + public void sendUpdateCommand(SimBidder sb, float newPrice) throws ModelException { + sendCommand(ServerCommandType.UPDATE, sb.getId(), newPrice); + } + + private void sendCommand(ServerCommandType type, String bidderId, float price) throws ModelException { + try { + CloseableHttpClient client = HttpClients.createDefault(); + HttpPost httpPost = new HttpPost("http://"+model.lookupProperty(SERVER_HOST, "localhost")+":"+model.lookupProperty(SERVER_PORT, "8082")+"/dsp-sim/admin"); + ServerCommand command = new ServerCommand(); + command.setType(type); + command.setId(bidderId); + command.setPrice(price); + StringEntity entity = new StringEntity(new Gson().toJson(command)); + httpPost.setEntity(entity); + httpPost.setHeader("Accept", "application/json"); + httpPost.setHeader("Content-type", "application/json"); + CloseableHttpResponse response = client.execute(httpPost); + if (response.getStatusLine().getStatusCode() == 200) { + String json = EntityUtils.toString(response.getEntity(), "UTF-8"); + ServerResponse sr = new Gson().fromJson(json, ServerResponse.class); + if (sr.getStatus() == ServerResponseStatus.SUCCESS) { + model.handleList(sr.getBidders()); + } else { + String m = type+" command failed with error: " + sr.getReason(); + model.setMessageAsFault(m); + throw new ModelException(m); + } + } else { + String m = type+" call failed with http error: " + response.getStatusLine().getStatusCode(); + model.setMessageAsFault(m); + throw new ModelException(m); + } + client.close(); + } catch (IOException e) { + model.setMessageAsFault("Could not access server: "+e.getMessage()); + throw new ModelException(e.getMessage()); + } + } + +} diff --git a/data-sim-client/src/main/java/com/atg/openssp/dspSim/model/BaseModel.java b/data-sim-client/src/main/java/com/atg/openssp/dspSim/model/BaseModel.java new file mode 100644 index 00000000..f8f07ba6 --- /dev/null +++ b/data-sim-client/src/main/java/com/atg/openssp/dspSim/model/BaseModel.java @@ -0,0 +1,33 @@ +package com.atg.openssp.dspSim.model; + +import java.util.ArrayList; + +public abstract class BaseModel { + private final ArrayList messageListeners = new ArrayList(); + + public void setMessage(String m) { + notifyMessageListeners(MessageStatus.NOMINAL, m); + } + + public void setMessageAsWarning(String m) { + notifyMessageListeners(MessageStatus.WARNING, m); + } + + public void setMessageAsFault(String m) { + notifyMessageListeners(MessageStatus.FAULT, m); + } + + private void notifyMessageListeners(MessageStatus s, String m) { + for (MessageNotificationListener lis : messageListeners) { + lis.sendMessage(s, m); + } + } + + public void addMessageNotificationListener(MessageNotificationListener lis) { + messageListeners.add(lis); + } + + public void removeMessageNotificationListener(MessageNotificationListener lis) { + messageListeners.remove(lis); + } +} diff --git a/data-sim-client/src/main/java/com/atg/openssp/dspSim/model/MessageNotificationListener.java b/data-sim-client/src/main/java/com/atg/openssp/dspSim/model/MessageNotificationListener.java new file mode 100644 index 00000000..efbf63af --- /dev/null +++ b/data-sim-client/src/main/java/com/atg/openssp/dspSim/model/MessageNotificationListener.java @@ -0,0 +1,6 @@ +package com.atg.openssp.dspSim.model; + +public interface MessageNotificationListener { + void sendMessage(MessageStatus s, String m); + +} diff --git a/data-sim-client/src/main/java/com/atg/openssp/dspSim/model/MessageStatus.java b/data-sim-client/src/main/java/com/atg/openssp/dspSim/model/MessageStatus.java new file mode 100644 index 00000000..e832f0a7 --- /dev/null +++ b/data-sim-client/src/main/java/com/atg/openssp/dspSim/model/MessageStatus.java @@ -0,0 +1,18 @@ +package com.atg.openssp.dspSim.model; + +import java.awt.*; + +public enum MessageStatus { + NOMINAL(Color.WHITE), FAULT(Color.RED), WARNING(Color.YELLOW); + + private final Color c; + + MessageStatus(Color c) { + this.c = c; + } + + public Color getColor() + { + return c; + } +} diff --git a/data-sim-client/src/main/java/com/atg/openssp/dspSim/model/ModelException.java b/data-sim-client/src/main/java/com/atg/openssp/dspSim/model/ModelException.java new file mode 100644 index 00000000..97544938 --- /dev/null +++ b/data-sim-client/src/main/java/com/atg/openssp/dspSim/model/ModelException.java @@ -0,0 +1,10 @@ +package com.atg.openssp.dspSim.model; + +/** + * @author Brian Sorensen + */ +public class ModelException extends Exception { + public ModelException(String msg) { + super(msg); + } +} diff --git a/data-sim-client/src/main/java/com/atg/openssp/dspSim/model/ad/AdModel.java b/data-sim-client/src/main/java/com/atg/openssp/dspSim/model/ad/AdModel.java new file mode 100644 index 00000000..706dde5c --- /dev/null +++ b/data-sim-client/src/main/java/com/atg/openssp/dspSim/model/ad/AdModel.java @@ -0,0 +1,18 @@ +package com.atg.openssp.dspSim.model.ad; + +import com.atg.openssp.dspSim.model.BaseModel; + +import java.util.Properties; /** + * @author Brian Sorensen + */ +public class AdModel extends BaseModel { + private final Properties props; + + public AdModel(Properties props) { + this.props = props; + } + + public String lookupProperty(String key) { + return props.getProperty(key); + } +} diff --git a/data-sim-client/src/main/java/com/atg/openssp/dspSim/model/client/ServerCommand.java b/data-sim-client/src/main/java/com/atg/openssp/dspSim/model/client/ServerCommand.java new file mode 100644 index 00000000..e7f7c7cd --- /dev/null +++ b/data-sim-client/src/main/java/com/atg/openssp/dspSim/model/client/ServerCommand.java @@ -0,0 +1,35 @@ +package com.atg.openssp.dspSim.model.client; + +/** + * @author Brian Sorensen + */ +public class ServerCommand { + private ServerCommandType type; + private String id; + private float price; + + public void setType(ServerCommandType type) { + this.type = type; + } + + public ServerCommandType getType() { + return type; + } + + public void setId(String id) { + this.id = id; + } + + public String getId() { + return id; + } + + public void setPrice(float price) { + this.price = price; + } + + public float getPrice() { + return price; + } + +} diff --git a/data-sim-client/src/main/java/com/atg/openssp/dspSim/model/client/ServerCommandType.java b/data-sim-client/src/main/java/com/atg/openssp/dspSim/model/client/ServerCommandType.java new file mode 100644 index 00000000..c1581af6 --- /dev/null +++ b/data-sim-client/src/main/java/com/atg/openssp/dspSim/model/client/ServerCommandType.java @@ -0,0 +1,8 @@ +package com.atg.openssp.dspSim.model.client; + +/** + * @author Brian Sorensen + */ +public enum ServerCommandType { + LIST, UPDATE, REMOVE, ADD +} diff --git a/data-sim-client/src/main/java/com/atg/openssp/dspSim/model/client/ServerResponse.java b/data-sim-client/src/main/java/com/atg/openssp/dspSim/model/client/ServerResponse.java new file mode 100644 index 00000000..6b3dd0f9 --- /dev/null +++ b/data-sim-client/src/main/java/com/atg/openssp/dspSim/model/client/ServerResponse.java @@ -0,0 +1,39 @@ +package com.atg.openssp.dspSim.model.client; + +import com.atg.openssp.dspSim.model.dsp.SimBidder; + +import java.util.List; + +/** + * @author Brian Sorensen + */ +public class ServerResponse { + private ServerResponseStatus status; + private String reason=""; + private List bidders; + + public void setStatus(ServerResponseStatus status) { + this.status = status; + } + + public ServerResponseStatus getStatus() { + return status; + } + + public void setReason(String reason) { + this.reason = reason; + } + + public String getReason() { + return reason; + } + + public void setBidders(List bidders) { + this.bidders = bidders; + } + + public List getBidders() { + return bidders; + } + +} diff --git a/data-sim-client/src/main/java/com/atg/openssp/dspSim/model/client/ServerResponseStatus.java b/data-sim-client/src/main/java/com/atg/openssp/dspSim/model/client/ServerResponseStatus.java new file mode 100644 index 00000000..7fc904ad --- /dev/null +++ b/data-sim-client/src/main/java/com/atg/openssp/dspSim/model/client/ServerResponseStatus.java @@ -0,0 +1,8 @@ +package com.atg.openssp.dspSim.model.client; + +/** + * @author Brian Sorensen + */ +public enum ServerResponseStatus { + FAILURE, SUCCESS +} diff --git a/data-sim-client/src/main/java/com/atg/openssp/dspSim/model/dsp/DspModel.java b/data-sim-client/src/main/java/com/atg/openssp/dspSim/model/dsp/DspModel.java new file mode 100644 index 00000000..05035fe0 --- /dev/null +++ b/data-sim-client/src/main/java/com/atg/openssp/dspSim/model/dsp/DspModel.java @@ -0,0 +1,86 @@ +package com.atg.openssp.dspSim.model.dsp; + +import com.atg.openssp.dspSim.ServerHandler; +import com.atg.openssp.dspSim.model.BaseModel; +import com.atg.openssp.dspSim.model.ModelException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.swing.*; +import java.util.*; + +/** + * @author Brian Sorensen + */ +public class DspModel extends BaseModel { + private static final Logger log = LoggerFactory.getLogger(DspModel.class); + private final Properties props; + private DefaultListModel mBidders = new DefaultListModel(); + private final ServerHandler serverHandler; + + public DspModel(Properties props) throws ModelException { + this.props = props; + serverHandler = new ServerHandler(this); + } + + public String lookupProperty(String key) { + return props.getProperty(key); + } + + public String lookupProperty(String key, String defaultValue) { + String v = lookupProperty(key); + if (v == null) { + return defaultValue; + } else { + return v; + } + } + + private HashMap getBidders() { + HashMap map = new HashMap(); + for (int i=0; i getBidderModel() { + return mBidders; + } + + public void start() { + serverHandler.start(); + } + + public void handleList(List bidders) { + HashMap map = getBidders(); + for (SimBidder bidder : bidders) { + SimBidder check = map.get(bidder.getId()); + if (check == null) { + mBidders.addElement(bidder); + } else { + map.remove(bidder.getId()); + check.setPrice(bidder.getPrice()); + } + } + // if any are left, remove them as extras + for (Map.Entry tBidder : map.entrySet()) { + mBidders.removeElement(tBidder.getValue()); + } + } + + public void sendAddCommand(float price) throws ModelException { + SimBidder sb = new SimBidder(UUID.randomUUID().toString()); + sb.setPrice(price); + serverHandler.sendAddCommand(sb); + } + + public void sendUpdateCommand(SimBidder sb, float newPrice) throws ModelException { + serverHandler.sendUpdateCommand(sb, newPrice); + } + + public void sendRemoveCommand(SimBidder sb) throws ModelException { + serverHandler.sendRemoveCommand(sb); + } + +} diff --git a/data-sim-client/src/main/java/com/atg/openssp/dspSim/model/dsp/SimBidder.java b/data-sim-client/src/main/java/com/atg/openssp/dspSim/model/dsp/SimBidder.java new file mode 100644 index 00000000..3a5a6e11 --- /dev/null +++ b/data-sim-client/src/main/java/com/atg/openssp/dspSim/model/dsp/SimBidder.java @@ -0,0 +1,30 @@ +package com.atg.openssp.dspSim.model.dsp; + +/** + * @author Brian Sorensen + */ +public class SimBidder { + private final String id; + private float price; + + public SimBidder(String id) { + this.id = id; + } + + public String getId() { + return id; + } + + public void setPrice(float price) { + this.price = price; + } + + public float getPrice() { + return price; + } + + @Override + public String toString() { + return id + " - ("+price+")"; + } +} diff --git a/data-sim-client/src/main/java/com/atg/openssp/dspSim/view/dsp/DspView.java b/data-sim-client/src/main/java/com/atg/openssp/dspSim/view/dsp/DspView.java new file mode 100644 index 00000000..3b634095 --- /dev/null +++ b/data-sim-client/src/main/java/com/atg/openssp/dspSim/view/dsp/DspView.java @@ -0,0 +1,29 @@ +package com.atg.openssp.dspSim.view.dsp; + +import com.atg.openssp.dspSim.model.dsp.DspModel; + +import javax.swing.*; +import java.awt.*; + +/** + * @author Brian Sorensen + */ +public class DspView { + private final DspModel model; + private final JFrame frame; + + public DspView(DspModel model) { + this.model = model; + frame = new JFrame("DSP Sim"); + JTabbedPane tabs = new JTabbedPane(); + tabs.addTab("Bidders", new SimBidderPanel(model)); + frame.setContentPane(tabs); + Dimension d = Toolkit.getDefaultToolkit().getScreenSize(); + frame.setSize(d.width, d.height-40); + frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); + } + + public void start() { + frame.setVisible(true); + } +} diff --git a/data-sim-client/src/main/java/com/atg/openssp/dspSim/view/dsp/SimBidderPanel.java b/data-sim-client/src/main/java/com/atg/openssp/dspSim/view/dsp/SimBidderPanel.java new file mode 100644 index 00000000..204fe5cd --- /dev/null +++ b/data-sim-client/src/main/java/com/atg/openssp/dspSim/view/dsp/SimBidderPanel.java @@ -0,0 +1,182 @@ +package com.atg.openssp.dspSim.view.dsp; + +import com.atg.openssp.dspSim.model.MessageNotificationListener; +import com.atg.openssp.dspSim.model.MessageStatus; +import com.atg.openssp.dspSim.model.ModelException; +import com.atg.openssp.dspSim.model.dsp.DspModel; +import com.atg.openssp.dspSim.model.dsp.SimBidder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.swing.*; +import javax.swing.border.TitledBorder; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.text.DecimalFormat; +import java.text.ParseException; + +/** + * @author Brian Sorensen + */ +public class SimBidderPanel extends JPanel implements ListSelectionListener, ActionListener, MessageNotificationListener { + private static final Logger log = LoggerFactory.getLogger(SimBidderPanel.class); + private final DspModel model; + private final JList lBidders; + private final JLabel lbId = new JLabel(""); + private final JTextField tfPrice = new JTextField(8); + private final JTextField tfAddPrice = new JTextField(8); + private final JButton bUpdate = new JButton("update"); + private final JButton bRemove = new JButton("remove"); + private final JButton bAdd = new JButton("add"); + private final JTextField tfMemo = new JTextField(20); + + public SimBidderPanel(DspModel model) { + this.model = model; + lBidders = new JList<>(model.getBidderModel()); + + setLayout(new BorderLayout()); + + JPanel pTop = new JPanel(); + add(pTop, BorderLayout.NORTH); + JPanel pBottom = new JPanel(); + pBottom.setLayout(new BoxLayout(pBottom, BoxLayout.Y_AXIS)); + add(pBottom, BorderLayout.SOUTH); + JPanel pMiddle = new JPanel(); + add(pMiddle, BorderLayout.CENTER); + JPanel pRight = new JPanel(); + pRight.setLayout(new BoxLayout(pRight, BoxLayout.Y_AXIS)); + add(pRight, BorderLayout.EAST); + + lBidders.setVisibleRowCount(10); + addItem(pTop, "Bidders: ", lBidders); + lBidders.addListSelectionListener(this); + bUpdate.setEnabled(false); + bUpdate.addActionListener(this); + addItem(pTop, "", bUpdate); + bRemove.setEnabled(false); + bRemove.addActionListener(this); + addItem(pTop, "", bRemove); + + pMiddle.setBorder(new TitledBorder("Active Bidder")); + addItem(pMiddle, "ID:", lbId); + addItem(pMiddle, "Price:", tfPrice); + + pRight.setBorder(new TitledBorder("Add Bidder")); + addItem(pRight, "Price:", tfAddPrice); + bAdd.addActionListener(this); + addItem(pRight, "", bAdd); + + tfMemo.setEditable(false); + pBottom.add(tfMemo); + model.addMessageNotificationListener(this); + model.setMessage(""); + } + + private void addItem(JPanel pMain, String txt, JComponent c) { + JPanel p0 = new JPanel(); + pMain.add(p0); + p0.setLayout(new FlowLayout()); + JPanel p1 = new JPanel(); + p0.add(p1); + p1.setLayout(new BoxLayout(p1, BoxLayout.X_AXIS)); + p1.add(new JLabel(txt)); + p1.add(c); + } + + @Override + public void valueChanged(ListSelectionEvent e) { + if (!e.getValueIsAdjusting()) { + SimBidder sb = lBidders.getSelectedValue(); + if (sb != null) { + lbId.setText(sb.getId()); + resetActiveDisplay(sb); + bUpdate.setEnabled(true); + bRemove.setEnabled(true); + } else { + if (lBidders.getModel().getSize() == 0) { + resetActiveDisplay(sb); + bUpdate.setEnabled(false); + bRemove.setEnabled(false); + } else { + resetActiveDisplay(sb); + lBidders.setSelectedIndex(0); + bUpdate.setEnabled(true); + bRemove.setEnabled(true); + } + + } + } + model.setMessage(""); + } + + private void resetActiveDisplay(SimBidder sb) { + if (sb == null) { + tfPrice.setText(""); + tfMemo.setText(""); + } else { + DecimalFormat formatter = new DecimalFormat("###,###,###.00"); + tfPrice.setText(formatter.format(sb.getPrice())); + tfMemo.setText("Bidder selected."); + } + } + + @Override + public void actionPerformed(ActionEvent ev) { + if (ev.getSource() == bUpdate) { + SimBidder sb = lBidders.getSelectedValue(); + if (sb != null) { + DecimalFormat formatter = new DecimalFormat("###,###,###.00"); + try { + float newPrice = formatter.parse(tfPrice.getText()).floatValue(); + if (sb.getPrice() != newPrice) { + model.sendUpdateCommand(sb, newPrice); + model.setMessage("Bidder saved."); + } + } catch (ModelException e) { + model.setMessageAsFault(e.getMessage()); + } catch (Exception e) { + log.error(e.getMessage(), e); + e.printStackTrace(); + model.setMessageAsFault("Could not save Bidder due to invalid price."); + } + } else { + model.setMessageAsWarning("No Bidder selected."); + } + repaint(); + } else if (ev.getSource() == bAdd) { + DecimalFormat formatter = new DecimalFormat("###,###,###.00"); + try { + model.sendAddCommand(formatter.parse(tfAddPrice.getText()).floatValue()); + model.setMessage("Bidder added."); + tfAddPrice.setText(""); + } catch (ModelException e) { + model.setMessageAsFault(e.getMessage()); + } catch (ParseException e) { + model.setMessageAsFault("Could not add Bidder due to invalid price."); + } + repaint(); + } else if (ev.getSource() == bRemove) { + SimBidder sb = lBidders.getSelectedValue(); + if (sb != null) { + try { + model.sendRemoveCommand(sb); + } catch (ModelException e) { + model.setMessageAsFault(e.getMessage()); + } + } else { + model.setMessageAsWarning("No Bidder selected."); + } + repaint(); + } + } + + @Override + public void sendMessage(MessageStatus s, String m) { + tfMemo.setText(m); + tfMemo.setBackground(s.getColor()); + } + +} diff --git a/data-sim-client/src/main/resources/DspSimClient.properties b/data-sim-client/src/main/resources/DspSimClient.properties new file mode 100644 index 00000000..3cc56e1f --- /dev/null +++ b/data-sim-client/src/main/resources/DspSimClient.properties @@ -0,0 +1,3 @@ + +server-host=localhost +server-port=8082 diff --git a/dsp-sim/pom.xml b/dsp-sim/pom.xml new file mode 100644 index 00000000..99f994e4 --- /dev/null +++ b/dsp-sim/pom.xml @@ -0,0 +1,81 @@ + + + 4.0.0 + com.atg.openssp + open-ssp-dsp-sim + 0.1 + open-ssp-dsp-sim + http://maven.apache.org + + UTF-8 + + + + + junit + junit + 3.8.1 + test + + + com.google.code.gson + gson + 2.6.2 + + + com.atg.openssp + open-ssp-common + 0.3 + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.5.1 + + 1.8 + 1.8 + + + + org.apache.maven.plugins + maven-dependency-plugin + + + copy-dependencies + prepare-package + + copy-dependencies + + + ${project.build.directory}/lib + false + false + true + + + + + + org.apache.maven.plugins + maven-jar-plugin + 3.0.2 + + + + true + + lib/ + com.atg.openssp.dspSim.DspSim + + + + + + + diff --git a/dsp-sim/run_sim.sh b/dsp-sim/run_sim.sh new file mode 100755 index 00000000..3ad13821 --- /dev/null +++ b/dsp-sim/run_sim.sh @@ -0,0 +1,3 @@ + +java -jar target/open-ssp-dsp-sim-0.1-SNAPSHOT.jar + diff --git a/dsp-sim/src/main/java/com/atg/openssp/dspSim/AdServerHandler.java b/dsp-sim/src/main/java/com/atg/openssp/dspSim/AdServerHandler.java new file mode 100644 index 00000000..d63f41bb --- /dev/null +++ b/dsp-sim/src/main/java/com/atg/openssp/dspSim/AdServerHandler.java @@ -0,0 +1,52 @@ +package com.atg.openssp.dspSim; + +import com.atg.openssp.dspSim.model.ad.AdModel; +import com.google.gson.Gson; +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import com.atg.openssp.dspSim.channel.adserving.AdservingCampaignProvider; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.*; + +/** + * @author Brian Sorensen + */ +public class AdServerHandler implements HttpHandler { + private static final Logger log = LoggerFactory.getLogger(AdServerHandler.class); + private final AdModel model; + + public AdServerHandler(AdModel model) { + this.model = model; + } + + @Override + public void handle(HttpExchange httpExchange) throws IOException { + + StringBuilder input = new StringBuilder(); + try { + BufferedReader is = new BufferedReader(new InputStreamReader(httpExchange.getRequestBody())); + String line; + while((line = is.readLine()) != null) { + input.append(line+"\n"); + } + } catch (Exception ex) { + log.error(ex.getMessage(), ex); + } + log.info("AD-->"+new Gson().toJson(input)); + + AdservingCampaignProvider p = new AdservingCampaignProvider(); + p.setIsValid(true); + p.setPrice(40f); + p.setPriceEur(30f); + + String result = new Gson().toJson(p); + log.info("<--"+result); + httpExchange.sendResponseHeaders(200, result.length()); + OutputStream os = httpExchange.getResponseBody(); + os.write(result.getBytes()); + os.close(); + + } +} diff --git a/dsp-sim/src/main/java/com/atg/openssp/dspSim/ClientHandler.java b/dsp-sim/src/main/java/com/atg/openssp/dspSim/ClientHandler.java new file mode 100644 index 00000000..ddb0acc6 --- /dev/null +++ b/dsp-sim/src/main/java/com/atg/openssp/dspSim/ClientHandler.java @@ -0,0 +1,104 @@ +package com.atg.openssp.dspSim; + +import com.atg.openssp.dspSim.model.ModelException; +import com.atg.openssp.dspSim.model.client.ClientCommand; +import com.atg.openssp.dspSim.model.client.ClientCommandType; +import com.atg.openssp.dspSim.model.client.ClientResponse; +import com.atg.openssp.dspSim.model.client.ClientResponseStatus; +import com.atg.openssp.dspSim.model.dsp.DspModel; +import com.atg.openssp.dspSim.model.dsp.SimBidder; +import com.google.gson.Gson; +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.*; +import java.util.UUID; + +/** + * @author Brian Sorensen + */ +public class ClientHandler implements HttpHandler { + private static final Logger log = LoggerFactory.getLogger(ClientHandler.class); + private final DspModel model; + + public ClientHandler(DspModel model) { + this.model = model; + } + + @Override + public void handle(HttpExchange httpExchange) throws IOException { + ClientCommand cc = new Gson().fromJson(new InputStreamReader(httpExchange.getRequestBody()), ClientCommand.class); + log.info("CC-->"+new Gson().toJson(cc)); + ClientResponse cr = new ClientResponse(); + if (cc == null) { + cr.setStatus(ClientResponseStatus.FAILURE); + cr.setReason("Command not found"); + cr.setBidders(model.getBidders()); + } else if (cc.getType() == ClientCommandType.LIST) { + cr.setStatus(ClientResponseStatus.SUCCESS); + cr.setBidders(model.getBidders()); + } else if (cc.getType() == ClientCommandType.ADD) { + SimBidder sb = model.lookupBidder(cc.getId()); + if (sb == null) { + sb = new SimBidder(cc.getId()); + sb.setPrice(cc.getPrice()); + model.add(sb); + try { + model.saveModel(); + cr.setStatus(ClientResponseStatus.SUCCESS); + } catch (ModelException e) { + log.error(e.getMessage(), e); + cr.setStatus(ClientResponseStatus.FAILURE); + cr.setReason("add save failed: "+e.getMessage()); + } + } else { + cr.setStatus(ClientResponseStatus.FAILURE); + cr.setReason("SimBidder already exists"); + } + cr.setBidders(model.getBidders()); + } else if (cc.getType() == ClientCommandType.REMOVE) { + SimBidder sb = model.lookupBidder(cc.getId()); + if (sb == null) { + cr.setStatus(ClientResponseStatus.FAILURE); + cr.setReason("SimBidder does not exists"); + } else { + model.remove(sb); + try { + model.saveModel(); + cr.setStatus(ClientResponseStatus.SUCCESS); + } catch (ModelException e) { + log.error(e.getMessage(), e); + cr.setStatus(ClientResponseStatus.FAILURE); + cr.setReason("remove save failed: "+e.getMessage()); + } + } + cr.setBidders(model.getBidders()); + } else if (cc.getType() == ClientCommandType.UPDATE) { + SimBidder sb = model.lookupBidder(cc.getId()); + if (sb == null) { + cr.setStatus(ClientResponseStatus.FAILURE); + cr.setReason("SimBidder not found"); + } else { + sb.setPrice(cc.getPrice()); + cr.setStatus(ClientResponseStatus.SUCCESS); + try { + model.saveModel(); + } catch (ModelException e) { + log.error(e.getMessage(), e); + cr.setStatus(ClientResponseStatus.FAILURE); + cr.setReason("update save failed: "+e.getMessage()); + } + } + cr.setBidders(model.getBidders()); + } + String result = new Gson().toJson(cr); + log.info("CR<--"+result); + httpExchange.sendResponseHeaders(200, result.length()); + OutputStream os = httpExchange.getResponseBody(); + os.write(result.getBytes()); + os.close(); + + } +} diff --git a/dsp-sim/src/main/java/com/atg/openssp/dspSim/DspHandler.java b/dsp-sim/src/main/java/com/atg/openssp/dspSim/DspHandler.java new file mode 100644 index 00000000..f965b541 --- /dev/null +++ b/dsp-sim/src/main/java/com/atg/openssp/dspSim/DspHandler.java @@ -0,0 +1,63 @@ +package com.atg.openssp.dspSim; + +import com.atg.openssp.dspSim.model.dsp.DspModel; +import com.google.gson.Gson; +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import openrtb.bidrequest.model.BidRequest; +import openrtb.bidresponse.model.BidResponse; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStream; + +/** + * @author Brian Sorensen + */ +public class DspHandler implements HttpHandler { + private static final Logger log = LoggerFactory.getLogger(DspHandler.class); + private final DspModel model; + + public DspHandler(DspModel model) { + this.model = model; + } + + @Override + public void handle(HttpExchange httpExchange) throws IOException { + // method: post + // writeFinished: false + // uri: /dsp-sim/DemandService + // reqContentLen: 724 + + // _REQ_HEADERS_ + // Accept-encoding: gzip,deflate + // Connection: Keep-Alive + // Host: localhost:8082 + // User-agent: Apache-HttpClient/4.5.2 (Java/1.8.0_161) + // Content-type: application/json; charset=UTF-8 + // Contenttype: application/json + // X-openrtb-version: 2.2 + // Content-length: 724 + + BidRequest brq = new Gson().fromJson(new InputStreamReader(httpExchange.getRequestBody()), BidRequest.class); + log.info("-->"+new Gson().toJson(brq)); + + BidResponse brsp = model.createBidResponse(brq); + + if (brsp.getSeatbid().size() > 0 || true) { + String result = new Gson().toJson(brsp); + log.info("<--"+result); + httpExchange.sendResponseHeaders(200, result.length()); + OutputStream os = httpExchange.getResponseBody(); + os.write(result.getBytes()); + os.close(); + } else { + httpExchange.sendResponseHeaders(201, 0); + } + + + } + +} diff --git a/dsp-sim/src/main/java/com/atg/openssp/dspSim/DspSim.java b/dsp-sim/src/main/java/com/atg/openssp/dspSim/DspSim.java new file mode 100644 index 00000000..e53906d5 --- /dev/null +++ b/dsp-sim/src/main/java/com/atg/openssp/dspSim/DspSim.java @@ -0,0 +1,55 @@ +package com.atg.openssp.dspSim; + +import com.atg.openssp.dspSim.model.ModelException; +import com.atg.openssp.dspSim.model.ad.AdModel; +import com.atg.openssp.dspSim.model.dsp.DspModel; +import com.sun.net.httpserver.HttpServer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.net.InetSocketAddress; + +/** + * @author Brian Sorensen + */ +public class DspSim { + private static final Logger log = LoggerFactory.getLogger(DspSim.class); + private DspModel dspModel; + private AdModel adModel; + + public DspSim() throws ModelException { + dspModel = new DspModel(); + adModel = new AdModel(); + } + + public void start() { + try { + HttpServer server = HttpServer.create(new InetSocketAddress(8082), 0); + server.createContext("/dsp-sim/admin", new ClientHandler(dspModel)); + server.createContext("/dsp-sim/DemandService", new DspHandler(dspModel)); + server.createContext("/dsp-sim/myAds", new AdServerHandler(adModel)); + server.setExecutor(null); // creates a default executor + server.start(); + } catch (IOException e) { + log.error(e.getMessage(), e); + } + + } + + public static void main(String[] args) { + try { + DspSim sim = new DspSim(); + sim.start(); + while(true) { + try { + Thread.sleep(100000); + } catch (InterruptedException e) { + } + } + } catch (ModelException e) { + log.error(e.getMessage(), e); + } + } + +} \ No newline at end of file diff --git a/dsp-sim/src/main/java/com/atg/openssp/dspSim/channel/adserving/AdservingCampaignProvider.java b/dsp-sim/src/main/java/com/atg/openssp/dspSim/channel/adserving/AdservingCampaignProvider.java new file mode 100644 index 00000000..6a97e05c --- /dev/null +++ b/dsp-sim/src/main/java/com/atg/openssp/dspSim/channel/adserving/AdservingCampaignProvider.java @@ -0,0 +1,87 @@ +package com.atg.openssp.dspSim.channel.adserving; + +import com.atg.openssp.common.core.entry.SessionAgent; +import com.atg.openssp.common.provider.AdProviderReader; +import com.atg.openssp.common.provider.AdProviderWriter; + +/** + * + * @author André Schmer + * + */ +public class AdservingCampaignProvider implements AdProviderReader, AdProviderWriter { + + private boolean isValid = Boolean.TRUE; + + private static final String currency = "EUR"; + + private float cpm; + + private int adid;// sent by adserver + + private String vasturl; + + @Override + public float getPrice() { + return cpm; + } + + @Override + public void setPrice(final float bidPrice) { + cpm = bidPrice; + } + + @Override + public void setIsValid(final boolean valid) { + isValid = valid; + } + + @Override + public boolean isValid() { + return isValid; + } + + @Override + public float getPriceEur() { + return cpm * 1; + } + + @Override + public String getCurrrency() { + return currency; + } + + @Override + public void perform(final SessionAgent agent) { + // nothing to implement yet + } + + @Override + public String buildResponse() { + return vasturl; + } + + @Override + public String getVendorId() { + if (adid > 0) { + return "Adserving_" + adid; + } + return null; + } + + @Override + public void setPriceEur(final float priceEur) { + cpm = priceEur; + } + + @Override + public String getAdid() { + return String.valueOf(adid); + } + + @Override + public String toString() { + return "AdservingCampaignProvider [isValid=" + isValid + ", currency=" + currency + ", cpm=" + cpm + ", adid=" + adid + ", vasturl=" + vasturl + "]"; + } + +} diff --git a/dsp-sim/src/main/java/com/atg/openssp/dspSim/model/ModelException.java b/dsp-sim/src/main/java/com/atg/openssp/dspSim/model/ModelException.java new file mode 100644 index 00000000..97544938 --- /dev/null +++ b/dsp-sim/src/main/java/com/atg/openssp/dspSim/model/ModelException.java @@ -0,0 +1,10 @@ +package com.atg.openssp.dspSim.model; + +/** + * @author Brian Sorensen + */ +public class ModelException extends Exception { + public ModelException(String msg) { + super(msg); + } +} diff --git a/dsp-sim/src/main/java/com/atg/openssp/dspSim/model/ad/AdModel.java b/dsp-sim/src/main/java/com/atg/openssp/dspSim/model/ad/AdModel.java new file mode 100644 index 00000000..5235dc50 --- /dev/null +++ b/dsp-sim/src/main/java/com/atg/openssp/dspSim/model/ad/AdModel.java @@ -0,0 +1,7 @@ +package com.atg.openssp.dspSim.model.ad; + +/** + * @author Brian Sorensen + */ +public class AdModel { +} diff --git a/dsp-sim/src/main/java/com/atg/openssp/dspSim/model/client/ClientCommand.java b/dsp-sim/src/main/java/com/atg/openssp/dspSim/model/client/ClientCommand.java new file mode 100644 index 00000000..354696ad --- /dev/null +++ b/dsp-sim/src/main/java/com/atg/openssp/dspSim/model/client/ClientCommand.java @@ -0,0 +1,35 @@ +package com.atg.openssp.dspSim.model.client; + +/** + * @author Brian Sorensen + */ +public class ClientCommand { + private ClientCommandType type; + private String id; + private float price; + + public void setType(ClientCommandType type) { + this.type = type; + } + + public ClientCommandType getType() { + return type; + } + + public void setId(String id) { + this.id = id; + } + + public String getId() { + return id; + } + + public void setPrice(float price) { + this.price = price; + } + + public float getPrice() { + return price; + } + +} diff --git a/dsp-sim/src/main/java/com/atg/openssp/dspSim/model/client/ClientCommandType.java b/dsp-sim/src/main/java/com/atg/openssp/dspSim/model/client/ClientCommandType.java new file mode 100644 index 00000000..43e78f8a --- /dev/null +++ b/dsp-sim/src/main/java/com/atg/openssp/dspSim/model/client/ClientCommandType.java @@ -0,0 +1,8 @@ +package com.atg.openssp.dspSim.model.client; + +/** + * @author Brian Sorensen + */ +public enum ClientCommandType { + LIST, UPDATE, REMOVE, ADD +} diff --git a/dsp-sim/src/main/java/com/atg/openssp/dspSim/model/client/ClientResponse.java b/dsp-sim/src/main/java/com/atg/openssp/dspSim/model/client/ClientResponse.java new file mode 100644 index 00000000..b268658a --- /dev/null +++ b/dsp-sim/src/main/java/com/atg/openssp/dspSim/model/client/ClientResponse.java @@ -0,0 +1,39 @@ +package com.atg.openssp.dspSim.model.client; + +import com.atg.openssp.dspSim.model.dsp.SimBidder; + +import java.util.List; + +/** + * @author Brian Sorensen + */ +public class ClientResponse { + private ClientResponseStatus status; + private String reason=""; + private List bidders; + + public void setStatus(ClientResponseStatus status) { + this.status = status; + } + + public ClientResponseStatus getStatus() { + return status; + } + + public void setReason(String reason) { + this.reason = reason; + } + + public String getReason() { + return reason; + } + + public void setBidders(List bidders) { + this.bidders = bidders; + } + + public List getBidders() { + return bidders; + } + +} diff --git a/dsp-sim/src/main/java/com/atg/openssp/dspSim/model/client/ClientResponseStatus.java b/dsp-sim/src/main/java/com/atg/openssp/dspSim/model/client/ClientResponseStatus.java new file mode 100644 index 00000000..f9085b7e --- /dev/null +++ b/dsp-sim/src/main/java/com/atg/openssp/dspSim/model/client/ClientResponseStatus.java @@ -0,0 +1,8 @@ +package com.atg.openssp.dspSim.model.client; + +/** + * @author Brian Sorensen + */ +public enum ClientResponseStatus { + FAILURE, SUCCESS +} diff --git a/dsp-sim/src/main/java/com/atg/openssp/dspSim/model/dsp/DspModel.java b/dsp-sim/src/main/java/com/atg/openssp/dspSim/model/dsp/DspModel.java new file mode 100644 index 00000000..33fc61c5 --- /dev/null +++ b/dsp-sim/src/main/java/com/atg/openssp/dspSim/model/dsp/DspModel.java @@ -0,0 +1,127 @@ +package com.atg.openssp.dspSim.model.dsp; + +import com.atg.openssp.dspSim.model.ModelException; +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import openrtb.bidrequest.model.BidRequest; +import openrtb.bidrequest.model.Impression; +import openrtb.bidresponse.model.Bid; +import openrtb.bidresponse.model.BidResponse; +import openrtb.bidresponse.model.SeatBid; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.*; +import java.util.*; + +/** + * @author Brian Sorensen + */ +public class DspModel { + private static final Logger log = LoggerFactory.getLogger(DspModel.class); + private static final String FILE_NAME = "DSP_SIM_MODEL.json"; + private final ArrayList simBidderListeners = new ArrayList(); + private final ArrayList bList = new ArrayList(); + private final HashMap bMap = new LinkedHashMap(); + + public DspModel() throws ModelException { + loadModel(); + } + + private void loadModel() throws ModelException { + try { + File f = new File(FILE_NAME); + if (f.exists()) { + FileReader fr = new FileReader(f); + List buffer = new Gson().fromJson(fr, new TypeToken>(){}.getType()); + fr.close(); + bList.addAll(buffer); + for (SimBidder sb : bList) { + bMap.put(sb.getId(), sb); + } + } + } catch (Exception e) { + log.warn(e.getMessage(), e); + throw new ModelException("Could not load model from store."); + } + } + + public void saveModel() throws ModelException { + try { + PrintWriter fw = new PrintWriter(new FileWriter(FILE_NAME)); + String json = new Gson().toJson(bList); + fw.println(json); + fw.close(); + } catch (IOException e) { + log.warn(e.getMessage(), e); + throw new ModelException("Could not save model from store."); + } + } + + public synchronized void add(SimBidder sb) { + bList.add(sb); + bMap.put(sb.getId(), sb); + notifySimBidderAdded(sb); + } + + private void notifySimBidderAdded(SimBidder sb) { + for (SimBidderListener lis : simBidderListeners) { + lis.added(sb); + } + } + + public synchronized void remove(SimBidder sb) { + bList.remove(sb); + bMap.remove(sb.getId()); + notifySimBidderRemoved(sb); + } + + private void notifySimBidderRemoved(SimBidder sb) { + for (SimBidderListener lis : simBidderListeners) { + lis.removed(sb); + } + } + + public BidResponse createBidResponse(BidRequest request) { + BidResponse response = new BidResponse(); + response.setId(UUID.randomUUID().toString()); + response.setBidid(request.getId()); + + for (Impression i : request.getImp()) { + for (SimBidder sb : bList) { + response.addSeatBid(fabricateSeatBid(sb, i)); + } + } + return response; + } + + private SeatBid fabricateSeatBid(SimBidder simBidder, Impression i) { + SeatBid sb = new SeatBid(); + Bid b = new Bid(); + b.setId(simBidder.getId()); + b.setImpid(i.getId()); + b.setPrice(simBidder.getPrice()); + sb.getBid().add(b); + return sb; + } + + public synchronized void addSimBidderListener(SimBidderListener lis) { + simBidderListeners.add(lis); + for (SimBidder sb : bList) { + lis.added(sb); + } + } + + public void removeSimBidderListener(SimBidderListener lis) { + simBidderListeners.remove(lis); + } + + public List getBidders() { + return bList; + } + + public SimBidder lookupBidder(String id) { + return bMap.get(id); + } + +} diff --git a/dsp-sim/src/main/java/com/atg/openssp/dspSim/model/dsp/SimBidder.java b/dsp-sim/src/main/java/com/atg/openssp/dspSim/model/dsp/SimBidder.java new file mode 100644 index 00000000..3a5a6e11 --- /dev/null +++ b/dsp-sim/src/main/java/com/atg/openssp/dspSim/model/dsp/SimBidder.java @@ -0,0 +1,30 @@ +package com.atg.openssp.dspSim.model.dsp; + +/** + * @author Brian Sorensen + */ +public class SimBidder { + private final String id; + private float price; + + public SimBidder(String id) { + this.id = id; + } + + public String getId() { + return id; + } + + public void setPrice(float price) { + this.price = price; + } + + public float getPrice() { + return price; + } + + @Override + public String toString() { + return id + " - ("+price+")"; + } +} diff --git a/dsp-sim/src/main/java/com/atg/openssp/dspSim/model/dsp/SimBidderListener.java b/dsp-sim/src/main/java/com/atg/openssp/dspSim/model/dsp/SimBidderListener.java new file mode 100644 index 00000000..d174b0b0 --- /dev/null +++ b/dsp-sim/src/main/java/com/atg/openssp/dspSim/model/dsp/SimBidderListener.java @@ -0,0 +1,10 @@ +package com.atg.openssp.dspSim.model.dsp; + +/** + * @author Brian Sorensen + */ +public interface SimBidderListener { + void added(SimBidder sb); + + void removed(SimBidder sb); +} diff --git a/open-ssp-parent/channel-adserver/pom.xml b/open-ssp-parent/channel-adserver/pom.xml index 16402dfb..2928f39c 100644 --- a/open-ssp-parent/channel-adserver/pom.xml +++ b/open-ssp-parent/channel-adserver/pom.xml @@ -4,7 +4,7 @@ com.atg.openssp open-ssp-parent - 0.2 + 0.3 channel-adserver diff --git a/open-ssp-parent/core/pom.xml b/open-ssp-parent/core/pom.xml index 0aa0eb4b..fb7405b5 100644 --- a/open-ssp-parent/core/pom.xml +++ b/open-ssp-parent/core/pom.xml @@ -8,7 +8,7 @@ com.atg.openssp open-ssp-parent - 0.2 + 0.3 core core @@ -31,8 +31,8 @@ org.apache.maven.plugins maven-surefire-plugin - UTF-8 + UTF-8 catalina.home ${my.dev.catalina.home} @@ -40,6 +40,27 @@ + + org.apache.maven.plugins + maven-install-plugin + + + install + + install-file + + + jar + ${project.artifactId} + ${project.groupId} + ${project.version} + + ${project.build.directory}/open-ssp.jar + + + + + @@ -72,6 +93,7 @@ ${project.build.outputDirectory}/app.properties + @@ -88,6 +110,22 @@ maven-war-plugin 2.6 + + org.apache.maven.plugins + maven-jar-plugin + 3.0.2 + + + make-a-jar + compile + + jar + + + + + + @@ -182,6 +220,13 @@ test + + + com.lmax + disruptor + 3.3.0 + + diff --git a/open-ssp-parent/core/src/main/java/com/atg/openssp/core/cache/broker/dto/AppDto.java b/open-ssp-parent/core/src/main/java/com/atg/openssp/core/cache/broker/dto/AppDto.java new file mode 100644 index 00000000..612a0cce --- /dev/null +++ b/open-ssp-parent/core/src/main/java/com/atg/openssp/core/cache/broker/dto/AppDto.java @@ -0,0 +1,34 @@ +package com.atg.openssp.core.cache.broker.dto; + +import openrtb.bidrequest.model.App; + +import java.io.Serializable; +import java.util.List; + +/** + * + * @author André Schmer + * + */ +public class AppDto implements Serializable { + + private static final long serialVersionUID = 6743606462533687452L; + + private List apps; + + public AppDto() {} + + public List getApps() { + return apps; + } + + public void setSupplier(final List apps) { + this.apps = apps; + } + + @Override + public String toString() { + return String.format("AppDto [apps=%s]", apps); + } + +} diff --git a/open-ssp-parent/core/src/main/java/com/atg/openssp/core/cache/broker/remote/AbstractRemoteDataProvider.java b/open-ssp-parent/core/src/main/java/com/atg/openssp/core/cache/broker/remote/AbstractRemoteDataProvider.java index 79bfb482..4fe3eca0 100644 --- a/open-ssp-parent/core/src/main/java/com/atg/openssp/core/cache/broker/remote/AbstractRemoteDataProvider.java +++ b/open-ssp-parent/core/src/main/java/com/atg/openssp/core/cache/broker/remote/AbstractRemoteDataProvider.java @@ -10,11 +10,15 @@ import com.atg.openssp.common.configuration.ContextCache; import com.atg.openssp.common.configuration.ContextProperties; import com.atg.openssp.common.exception.EmptyHostException; - +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import restful.client.RemoteDataProviderConnector; import restful.context.PathBuilder; import restful.exception.RestException; +import java.net.URI; +import java.net.URISyntaxException; + /** * @author André Schmer * @@ -33,11 +37,11 @@ protected PathBuilder getDefaulPathBuilder() throws EmptyHostException { final PathBuilder pathBuilder = new PathBuilder(); try { - final URI remoteEndpintURI = new URI(ContextCache.instance.get(ContextProperties.DATA_PROVIDER_URL)); + final URI remoteEndpintURI = new URI(ContextCache.instance.get(ContextProperties.DATA_PROVIDER_HOST)); if (remoteEndpintURI.getHost() == null) { throw new EmptyHostException("No Host is defined, see data-provider-url in global.runtime.xml"); } - pathBuilder.setServer(remoteEndpintURI.getHost()); + pathBuilder.setHost(remoteEndpintURI.getHost()); if (remoteEndpintURI.getScheme() == null) { pathBuilder.setScheme("http"); } else { diff --git a/open-ssp-parent/core/src/main/java/com/atg/openssp/core/system/LocalContext.java b/open-ssp-parent/core/src/main/java/com/atg/openssp/core/system/LocalContext.java index 85b8e53a..0e098632 100644 --- a/open-ssp-parent/core/src/main/java/com/atg/openssp/core/system/LocalContext.java +++ b/open-ssp-parent/core/src/main/java/com/atg/openssp/core/system/LocalContext.java @@ -5,6 +5,9 @@ import com.atg.openssp.common.configuration.Context; import com.atg.openssp.common.configuration.ContextCache; import com.atg.openssp.common.configuration.ContextProperties; +import com.atg.openssp.core.system.properties.MavenProperties; + +import java.time.LocalDateTime; /** * @author André Schmer @@ -28,10 +31,38 @@ public class LocalContext extends Context { private static boolean isMetricsEnabled; - private static String sspVersion; + private static String sspVersion = new MavenProperties().getVersion(); + private static boolean isSspChannelEnabled; + //####################################### + private static boolean isAppDataServiceEnabled = false; + + private static boolean isCurrencyDataServiceEnabled = false; + + private static boolean isLoginServiceEnabled = false; + + private static boolean isPricelayerDataServiceEnabled = false; + + private static boolean isSiteDataServiceEnabled = false; + + private static boolean isSupplierDataServiceEnabled = false; + + private static String appDataHandlerClass; + + private static String currencyDataHandlerClass; + + private static String loginHandlerClass; + + private static String pricelayerDataHandlerClass; + + private static String siteDataHandlerClass; + + private static String supplierDataHandlerClass; + //####################################### + + static { initData(); } @@ -43,6 +74,20 @@ public static void refreshContext() { isSspChannelEnabled = Boolean.parseBoolean(ContextCache.instance.get(ContextProperties.SSPCHANNEL)); isVerboseEnabled = Boolean.parseBoolean(ContextCache.instance.get(ContextProperties.VERBOSE)); isMetricsEnabled = Boolean.parseBoolean(ContextCache.instance.get(ContextProperties.METRICS)); + + isAppDataServiceEnabled = Boolean.parseBoolean(ContextCache.instance.get(ContextProperties.APP_DATA_SERVICE_ENABLED)); + isCurrencyDataServiceEnabled = Boolean.parseBoolean(ContextCache.instance.get(ContextProperties.CURRENCY_DATA_SERVICE_ENABLED)); + isLoginServiceEnabled = Boolean.parseBoolean(ContextCache.instance.get(ContextProperties.LOGIN_SERVICE_ENABLED)); + isPricelayerDataServiceEnabled = Boolean.parseBoolean(ContextCache.instance.get(ContextProperties.PRICELAYER_DATA_SERVICE_ENABLED)); + isSiteDataServiceEnabled = Boolean.parseBoolean(ContextCache.instance.get(ContextProperties.SITE_DATA_SERVICE_ENABLED)); + isSupplierDataServiceEnabled = Boolean.parseBoolean(ContextCache.instance.get(ContextProperties.SUPPLIER_DATA_SERVICE_ENABLED)); + + appDataHandlerClass = ContextCache.instance.get(ContextProperties.APP_DATA_HANDLER_CLASS); + currencyDataHandlerClass = ContextCache.instance.get(ContextProperties.CURRENCY_DATA_HANDLER_CLASS); + loginHandlerClass = ContextCache.instance.get(ContextProperties.LOGIN_HANDLER_CLASS); + pricelayerDataHandlerClass = ContextCache.instance.get(ContextProperties.PRICELAYER_DATA_HANDLER_CLASS); + siteDataHandlerClass = ContextCache.instance.get(ContextProperties.SITE_DATA_HANDLER_CLASS); + supplierDataHandlerClass = ContextCache.instance.get(ContextProperties.SUPPLIER_DATA_HANDLER_CLASS); } private static void initData() { @@ -108,4 +153,54 @@ static void setVersion(final String version) { static String getVersion() { return sspVersion; } + + + public static boolean isAppDataServiceEnabled() { + return isAppDataServiceEnabled; + } + + public static boolean isCurrencyDataServiceEnabled() { + return isCurrencyDataServiceEnabled; + } + + public static boolean isLoginServiceEnabled() { + return isLoginServiceEnabled; + } + + public static boolean isPricelayerDataServiceEnabled() { + return isPricelayerDataServiceEnabled; + } + + public static boolean isSiteDataServiceEnabled() { + return isSiteDataServiceEnabled; + } + + public static boolean isSupplierDataServiceEnabled() { + return isSupplierDataServiceEnabled; + } + + public static String getAppDataHandlerClass() { + return appDataHandlerClass; + } + + public static String getCurrencyDataHandlerClass() { + return currencyDataHandlerClass; + } + + public static String getLoginHandlerClass() { + return loginHandlerClass; + } + + public static String getPricelayerDataHandlerClass() { + return pricelayerDataHandlerClass; + } + + public static String getSiteDataHandlerClass() { + return siteDataHandlerClass; + } + + public static String getSupplierDataHandlerClass() { + return supplierDataHandlerClass; + } + } diff --git a/open-ssp-parent/core/src/main/resources/global.runtime.xml b/open-ssp-parent/core/src/main/resources/global.runtime.xml index 72ea762f..7adc856b 100644 --- a/open-ssp-parent/core/src/main/resources/global.runtime.xml +++ b/open-ssp-parent/core/src/main/resources/global.runtime.xml @@ -14,11 +14,32 @@ 500 - + http + + localhost + + 9090 - + frogs - + izod + + + http + + localhost + + 8082 + + /dsp-sim/myAds + + io.freestar.ssp.entry.FreestarEntryValidatorForVideoHandler + + io.freestar.ssp.entry.FreestarEntryValidatorForBannerHandler + + io.freestar.ssp.channel.adserving.FreestarAdserverBrokerHandler + + io.freestar.ssp.exchange.FreestarBidRequestBuilderHandler diff --git a/open-ssp-parent/open-ssp-common/pom.xml b/open-ssp-parent/open-ssp-common/pom.xml index 7c4b42b9..85f1aab7 100644 --- a/open-ssp-parent/open-ssp-common/pom.xml +++ b/open-ssp-parent/open-ssp-common/pom.xml @@ -6,7 +6,7 @@ com.atg.openssp open-ssp-parent - 0.2 + 0.3 open-ssp-common open-ssp-common diff --git a/open-ssp-parent/open-ssp-common/src/main/java/com/atg/openssp/common/cache/broker/AbstractDataBroker.java b/open-ssp-parent/open-ssp-common/src/main/java/com/atg/openssp/common/cache/broker/AbstractDataBroker.java index 2d3377ea..2782477c 100644 --- a/open-ssp-parent/open-ssp-common/src/main/java/com/atg/openssp/common/cache/broker/AbstractDataBroker.java +++ b/open-ssp-parent/open-ssp-common/src/main/java/com/atg/openssp/common/cache/broker/AbstractDataBroker.java @@ -24,7 +24,9 @@ protected PathBuilder getDefaulPathBuilder() { final PathBuilder pathBuilder = new PathBuilder(); pathBuilder.setMaster_pw(ContextCache.instance.get(ContextProperties.MASTER_PW)); pathBuilder.setMaster_user(ContextCache.instance.get(ContextProperties.MASTER_USER)); - pathBuilder.setServer(ContextCache.instance.get(ContextProperties.DATA_PROVIDER_URL)); + pathBuilder.setScheme(ContextCache.instance.get(ContextProperties.DATA_PROVIDER_SCHEME)); + pathBuilder.setHost(ContextCache.instance.get(ContextProperties.DATA_PROVIDER_HOST)); + pathBuilder.setPort(ContextCache.instance.get(ContextProperties.DATA_PROVIDER_PORT)); return pathBuilder; } diff --git a/open-ssp-parent/open-ssp-common/src/main/java/com/atg/openssp/common/configuration/ContextProperties.java b/open-ssp-parent/open-ssp-common/src/main/java/com/atg/openssp/common/configuration/ContextProperties.java index d09876aa..32f71cb4 100644 --- a/open-ssp-parent/open-ssp-common/src/main/java/com/atg/openssp/common/configuration/ContextProperties.java +++ b/open-ssp-parent/open-ssp-common/src/main/java/com/atg/openssp/common/configuration/ContextProperties.java @@ -40,10 +40,22 @@ public enum ContextProperties { TRIGGER_EXPESSION("cache-trigger-expression"), /** - * data-privder-url + * data-privder-scheme */ @RuntimeMeta(type = Scope.GLOBAL) - DATA_PROVIDER_URL("data-provider-url"), + DATA_PROVIDER_SCHEME("data-provider-scheme"), + + /** + * data-privder-host + */ + @RuntimeMeta(type = Scope.GLOBAL) + DATA_PROVIDER_HOST("data-provider-host"), + + /** + * data-privder-port + */ + @RuntimeMeta(type = Scope.GLOBAL) + DATA_PROVIDER_PORT("data-provider-port"), /** * master_pw @@ -57,6 +69,30 @@ public enum ContextProperties { @RuntimeMeta(type = Scope.GLOBAL, printable = false) MASTER_USER("master_user"), + /** + * data-privder-scheme + */ + @RuntimeMeta(type = Scope.GLOBAL) + ADSERVER_PROVIDER_SCHEME("adserver-provider-scheme"), + + /** + * data-privder-host + */ + @RuntimeMeta(type = Scope.GLOBAL) + ADSERVER_PROVIDER_HOST("adserver-provider-host"), + + /** + * data-privder-port + */ + @RuntimeMeta(type = Scope.GLOBAL) + ADSERVER_PROVIDER_PORT("adserver-provider-port"), + + /** + * data-privder-path + */ + @RuntimeMeta(type = Scope.GLOBAL) + ADSERVER_PROVIDER_PATH("adserver-provider-path"), + /** * adserving */ @@ -79,7 +115,78 @@ public enum ContextProperties { * ssp */ @RuntimeMeta(type = Scope.LOCAL) - SSPCHANNEL("ssp"); + SSPCHANNEL("ssp"), + + @RuntimeMeta(type = Scope.GLOBAL) + VALIDATOR_HANDLER_FOR_VIDEO_CLASS("validator-handler-for-video-class"), + + @RuntimeMeta(type = Scope.GLOBAL) + VALIDATOR_HANDLER_FOR_BANNER_CLASS("validator-handler-for-banner-class"), + + @RuntimeMeta(type = Scope.GLOBAL) + ADSERVER_BROKER_HANDLER_CLASS("adserver-broker-handler-class"), + + @RuntimeMeta(type = Scope.GLOBAL) + BUILD_REQUEST_BUILDER_HANDLER_CLASS("bid-request-builder-handler-class"), + + + //########################################################### + /** + * app data service + */ + @RuntimeMeta(type = Scope.LOCAL) + APP_DATA_SERVICE_ENABLED("app-data-service-enabled"), + + @RuntimeMeta(type = Scope.LOCAL) + APP_DATA_HANDLER_CLASS("app-data-handler-class"), + + /** + * currency data service + */ + @RuntimeMeta(type = Scope.LOCAL) + CURRENCY_DATA_SERVICE_ENABLED("currency-data-service-enabled"), + + @RuntimeMeta(type = Scope.LOCAL) + CURRENCY_DATA_HANDLER_CLASS("currency-data-handler-class"), + + /** + * login service + */ + @RuntimeMeta(type = Scope.LOCAL) + LOGIN_SERVICE_ENABLED("login-service-enabled"), + + @RuntimeMeta(type = Scope.LOCAL) + LOGIN_HANDLER_CLASS("login-handler-class"), + + /** + * pricelayer data service + */ + @RuntimeMeta(type = Scope.LOCAL) + PRICELAYER_DATA_SERVICE_ENABLED("pricelayer-data-service-enabled"), + + @RuntimeMeta(type = Scope.LOCAL) + PRICELAYER_DATA_HANDLER_CLASS("pricelayer-data-handler-class"), + + /** + * site data service + */ + @RuntimeMeta(type = Scope.LOCAL) + SITE_DATA_SERVICE_ENABLED("site-data-service-enabled"), + + @RuntimeMeta(type = Scope.LOCAL) + SITE_DATA_HANDLER_CLASS("site-data-handler-class"), + + /** + * app data service + */ + @RuntimeMeta(type = Scope.LOCAL) + SUPPLIER_DATA_SERVICE_ENABLED("supplier-data-service-enabled"), + + @RuntimeMeta(type = Scope.LOCAL) + SUPPLIER_DATA_HANDLER_CLASS("supplier-data-handler-class"); + + + //########################################################### private String value; diff --git a/open-ssp-parent/open-ssp-common/src/main/java/com/atg/openssp/common/configuration/GlobalContext.java b/open-ssp-parent/open-ssp-common/src/main/java/com/atg/openssp/common/configuration/GlobalContext.java index 7ae70466..655c3c4c 100644 --- a/open-ssp-parent/open-ssp-common/src/main/java/com/atg/openssp/common/configuration/GlobalContext.java +++ b/open-ssp-parent/open-ssp-common/src/main/java/com/atg/openssp/common/configuration/GlobalContext.java @@ -8,6 +8,10 @@ public class GlobalContext extends Context { private static long executionTimeout; private static float drawModeration; + private static String entryValidatorHandlerForBannerClass; + private static String entryValidatorHandlerForVideoClass; + private static String adserverBrokerHandlerClass; + private static String bidRequestBuilderHandlerClass; public static void refreshContext() { // default value is 500 milliseconds @@ -17,6 +21,11 @@ public static void refreshContext() { // default value is 0.3 drawModeration = Float.parseFloat(ContextCache.instance.get(ContextProperties.DRAW_MODERATION) != null ? ContextCache.instance.get( ContextProperties.DRAW_MODERATION) : "0.3"); + + entryValidatorHandlerForBannerClass = ContextCache.instance.get(ContextProperties.VALIDATOR_HANDLER_FOR_BANNER_CLASS); + entryValidatorHandlerForVideoClass = ContextCache.instance.get(ContextProperties.VALIDATOR_HANDLER_FOR_VIDEO_CLASS); + adserverBrokerHandlerClass = ContextCache.instance.get(ContextProperties.ADSERVER_BROKER_HANDLER_CLASS); + bidRequestBuilderHandlerClass = ContextCache.instance.get(ContextProperties.BUILD_REQUEST_BUILDER_HANDLER_CLASS); } /** @@ -41,4 +50,19 @@ public static float getDrawModeration() { return drawModeration; } + public static String getEntryValidatorHandlerForVideoClass() { + return entryValidatorHandlerForVideoClass; + } + + public static String getEntryValidatorHandlerForBannerClass() { + return entryValidatorHandlerForBannerClass; + } + + public static String getAdserverBrokerHandlerClass() { + return adserverBrokerHandlerClass; + } + + public static String getBidRequestBuilderHandlerClass() { + return bidRequestBuilderHandlerClass; + } } diff --git a/open-ssp-parent/open-ssp-openrtb-validator/pom.xml b/open-ssp-parent/open-ssp-openrtb-validator/pom.xml index bf5a944c..029954fb 100644 --- a/open-ssp-parent/open-ssp-openrtb-validator/pom.xml +++ b/open-ssp-parent/open-ssp-openrtb-validator/pom.xml @@ -3,7 +3,7 @@ com.atg.openssp open-ssp-parent - 0.2 + 0.3 open-ssp-openrtb-validator diff --git a/open-ssp-parent/open-ssp-openrtb/pom.xml b/open-ssp-parent/open-ssp-openrtb/pom.xml index 231ef0de..f1a76b44 100644 --- a/open-ssp-parent/open-ssp-openrtb/pom.xml +++ b/open-ssp-parent/open-ssp-openrtb/pom.xml @@ -3,7 +3,7 @@ com.atg.openssp open-ssp-parent - 0.2 + 0.3 open-ssp-openrtb diff --git a/open-ssp-parent/open-ssp-openrtb/src/main/java/openrtb/bidrequest/model/App.java b/open-ssp-parent/open-ssp-openrtb/src/main/java/openrtb/bidrequest/model/App.java new file mode 100644 index 00000000..bfa0df36 --- /dev/null +++ b/open-ssp-parent/open-ssp-openrtb/src/main/java/openrtb/bidrequest/model/App.java @@ -0,0 +1,161 @@ +package openrtb.bidrequest.model; + +/** + * @author André Schmer + * + */ +public final class App implements Cloneable { + + private String id; + + /* + private String name; + private String domain; + + // see product taxonomy -> "http://www.google.com/basepages/producttype/taxonomy.en-US.txt" + private List cat; + + private String page; + + private Publisher publisher; + private Object ext; + */ + + public App() { + //cat = new ArrayList<>(); + } + + public String getId() { + return id; + } + + public void setId(final String id) { + this.id = id; + } + + /* + public String getName() { + return name; + } + + public void setName(final String name) { + this.name = name; + } + + public String getDomain() { + return domain; + } + + public List getCat() { + return cat; + } + + public void setCat(final List cat) { + this.cat = cat; + } + + public void addCat(final String cat) { + this.cat.add(cat); + } + + public String getPage() { + return page; + } + + public void setPage(final String page) { + this.page = page; + } + + public Object getExt() { + return ext; + } + + public void setExt(final Object ext) { + this.ext = ext; + } + + public void setDomain(final String domain) { + this.domain = domain; + } + + public Publisher getPublisher() { + return publisher; + } + + public void setPublisher(final Publisher publisher) { + this.publisher = publisher; + } + + @Override + public App clone() { + try { + final App clone = (App) super.clone(); + return clone; + } catch (final CloneNotSupportedException e) { + e.printStackTrace(); + } + return null; + } + + public static class Builder { + + private final App site; + + public Builder() { + site = new App(); + } + + public Builder setId(final String id) { + site.setId(id); + return this; + } + + public Builder setName(final String name) { + site.setName(name); + return this; + } + + public Builder addCat(final String cat) { + site.addCat(cat); + return this; + } + + public Builder setPage(final String page) { + site.setPage(page); + return this; + } + + public Builder setExtension(final Object ext) { + site.setExt(ext); + return this; + } + + public Builder setDomain(final String domain) { + site.setDomain(domain); + return this; + } + + public Builder setPublisher(final Publisher publisher) { + site.setPublisher(publisher); + return this; + } + + public Builder addCats(final List cats) { + cats.forEach(c -> site.addCat(String.valueOf(c))); + return this; + } + + public App build() { + return site; + } + + } + */ + + @Override + public String toString() { +// return String.format("Site [id=%s, name=%s, domain=%s, cat=%s, page=%s, ext=%s]", id);//, name, domain, cat, page, ext); + return String.format("Site [id=%s]", id);//, name, domain, cat, page, ext); + } + +} diff --git a/open-ssp-parent/open-ssp-restful-client/pom.xml b/open-ssp-parent/open-ssp-restful-client/pom.xml index cd498582..92742b65 100644 --- a/open-ssp-parent/open-ssp-restful-client/pom.xml +++ b/open-ssp-parent/open-ssp-restful-client/pom.xml @@ -4,7 +4,7 @@ com.atg.openssp open-ssp-parent - 0.2 + 0.3 open-ssp-restful-client diff --git a/open-ssp-parent/open-ssp-restful-client/src/main/java/restful/context/PathBuilder.java b/open-ssp-parent/open-ssp-restful-client/src/main/java/restful/context/PathBuilder.java index c345c427..c3af5ec6 100644 --- a/open-ssp-parent/open-ssp-restful-client/src/main/java/restful/context/PathBuilder.java +++ b/open-ssp-parent/open-ssp-restful-client/src/main/java/restful/context/PathBuilder.java @@ -27,7 +27,8 @@ public class PathBuilder { private final StringBuilder path; private String mediaType; - private String server; + private String host; + private String port; private String master_user; private String master_pw; private String scheme; @@ -89,8 +90,17 @@ public String getMediaType() { * * @param host */ - public void setServer(final String host) { - server = host; + public void setHost(final String host) { + this.host = host; + } + + /** + * Sets the value for the Host of this path. + * + * @param port + */ + public void setPort(final String port) { + this.port = port; } public void setScheme(final String scheme) { @@ -101,8 +111,16 @@ public String getScheme() { return scheme; } + public String getHost() { + return host; + } + public String getServer() { - return StringUtils.isEmpty(server) ? "" : server; + return (StringUtils.isEmpty(host) ? "" : host) + (StringUtils.isEmpty(port) ? "" : ":"+port); + } + + public String getPort() { + return port; } public String getMaster_user() { diff --git a/open-ssp-parent/open-ssp-utilities/pom.xml b/open-ssp-parent/open-ssp-utilities/pom.xml index 22f864c9..89387ee4 100644 --- a/open-ssp-parent/open-ssp-utilities/pom.xml +++ b/open-ssp-parent/open-ssp-utilities/pom.xml @@ -4,7 +4,7 @@ com.atg.openssp open-ssp-parent - 0.2 + 0.3 open-ssp-utilities diff --git a/open-ssp-parent/pom.xml b/open-ssp-parent/pom.xml index 1740b94b..77c492be 100644 --- a/open-ssp-parent/pom.xml +++ b/open-ssp-parent/pom.xml @@ -3,7 +3,7 @@ 4.0.0 com.atg.openssp open-ssp-parent - 0.2 + 0.3 pom