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
+
+
+
+ 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
+
+
+
+ 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
+
+
+
+ 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