package no.asgari.civilization.server;
import com.codahale.metrics.MetricRegistry;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheBuilderSpec;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.mongodb.BasicDBObject;
import com.mongodb.DB;
import com.mongodb.MongoClient;
import io.dropwizard.Application;
import io.dropwizard.assets.AssetsBundle;
import io.dropwizard.auth.basic.BasicCredentials;
import io.dropwizard.java8.Java8Bundle;
import io.dropwizard.java8.auth.AuthFactory;
import io.dropwizard.java8.auth.CachingAuthenticator;
import io.dropwizard.java8.auth.basic.BasicAuthFactory;
import io.dropwizard.setup.Bootstrap;
import io.dropwizard.setup.Environment;
import lombok.extern.log4j.Log4j;
import no.asgari.civilization.server.action.PBFTestAction;
import no.asgari.civilization.server.application.CivAuthenticator;
import no.asgari.civilization.server.application.CivSingleton;
import no.asgari.civilization.server.application.MongoManaged;
import no.asgari.civilization.server.model.Chat;
import no.asgari.civilization.server.model.GameLog;
import no.asgari.civilization.server.model.PBF;
import no.asgari.civilization.server.model.Player;
import no.asgari.civilization.server.model.Playerhand;
import no.asgari.civilization.server.resource.AdminResource;
import no.asgari.civilization.server.resource.AuthResource;
import no.asgari.civilization.server.resource.DrawResource;
import no.asgari.civilization.server.resource.GameResource;
import no.asgari.civilization.server.resource.PlayerResource;
import org.apache.commons.codec.digest.DigestUtils;
import org.glassfish.hk2.utilities.Binder;
import org.mongojack.JacksonDBCollection;
import org.mongojack.WriteResult;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
@Log4j
@SuppressWarnings("unchecked")
public class CivilizationIntegrationTestApplication extends Application<CivilizationTestConfiguration> {
public DB db;
public JacksonDBCollection<PBF, String> pbfCollection;
public JacksonDBCollection<GameLog, String> gameLogCollection;
public JacksonDBCollection<Player, String> playerCollection;
public JacksonDBCollection<Chat, String> chatCollection;
public String pbfId;
public String playerId;
public String pbfId_2;
public String pbfId_3;
@Override
public void initialize(Bootstrap<CivilizationTestConfiguration> bootstrap) {
bootstrap.addBundle(new Java8Bundle());
bootstrap.addBundle(new AssetsBundle());
}
@Override
public void run(CivilizationTestConfiguration configuration, Environment environment) throws Exception {
MongoClient mongo = new MongoClient(configuration.mongohost, configuration.mongoport);
this.db = mongo.getDB(configuration.mongodb);
MongoManaged mongoManaged = new MongoManaged(mongo);
//Database
environment.lifecycle().manage(mongoManaged);
this.playerCollection = JacksonDBCollection.wrap(db.getCollection(Player.COL_NAME), Player.class, String.class);
this.pbfCollection = JacksonDBCollection.wrap(db.getCollection(PBF.COL_NAME), PBF.class, String.class);
this.gameLogCollection = JacksonDBCollection.wrap(db.getCollection(GameLog.COL_NAME), GameLog.class, String.class);
this.chatCollection = JacksonDBCollection.wrap(db.getCollection(Chat.COL_NAME), Chat.class, String.class);
playerCollection.drop();
pbfCollection.drop();
gameLogCollection.drop();
chatCollection.drop();
createIndexForPlayer(playerCollection);
createUsernameCache(playerCollection);
createIndexForPBF(pbfCollection);
// createItemCache();
//Resources
environment.jersey().register(new GameResource(db));
environment.jersey().register(new AuthResource(db));
environment.jersey().register(new PlayerResource(db));
environment.jersey().register(new DrawResource(db));
environment.jersey().register(new AdminResource(db));
//Authenticator
CachingAuthenticator<BasicCredentials, Player> cachingAuthenticator = new CachingAuthenticator<>(
new MetricRegistry(),
new CivAuthenticator(db),
CacheBuilderSpec.parse("expireAfterWrite=120m")
);
//Authentication binder
Binder authBinder = AuthFactory.binder(new BasicAuthFactory<>(cachingAuthenticator, "civilization", Player.class));
//Authentication
environment.jersey().register(authBinder);
//Test data
createPlayer("admin", null);
createNewPBFGame();
createAnotherPBF();
createEmptyPBF();
playerId = playerCollection.find().toArray().stream()
.filter(p -> p.getUsername().equals("cash1981"))
.findFirst().get().getId();
}
// private void createItemCache() {
// CivSingleton.instance().setItemsCache(
// CacheBuilder.newBuilder()
// .maximumSize(4) //1 for each game type
// .removalListener(lis -> log.debug("Removing " + lis.getKey() + " from the gameCache"))
// .build(new CacheLoader<GameType, ItemReader>() {
// public ItemReader load(GameType type) {
// ItemReader itemReader = new ItemReader();
// try {
// itemReader.readItemsFromExcel(type);
// } catch (IOException e) {
// log.error("Couldn't read from Excel file " + e.getMessage(), e);
// throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR);
// }
// return itemReader;
// }
// })
// );
// }
private void createUsernameCache(JacksonDBCollection<Player, String> playerCollection) {
LoadingCache<String, String> usernameCache = CacheBuilder.newBuilder()
.expireAfterWrite(2, TimeUnit.HOURS)
.maximumSize(100)
.removalListener(lis -> log.debug("Removing " + lis.toString() + " from the usernameCache"))
.build(new CacheLoader<String, String>() {
public String load(String playerId) {
return playerCollection.findOneById(playerId).getUsername();
}
});
CivSingleton.instance().setPlayerCache(usernameCache);
}
private void createIndexForPlayer(JacksonDBCollection<Player, String> playerCollection) {
playerCollection.createIndex(new BasicDBObject(Player.USERNAME, 1), new BasicDBObject("unique", true));
playerCollection.createIndex(new BasicDBObject(Player.EMAIL, 1), new BasicDBObject("unique", true));
}
private void createIndexForPBF(JacksonDBCollection<PBF, String> pbfCollection) {
pbfCollection.createIndex(new BasicDBObject(PBF.NAME, 1), new BasicDBObject("unique", true));
}
private void createNewPBFGame() throws IOException {
PBFTestAction pbfTestAction = new PBFTestAction();
PBF pbf = pbfTestAction.createNewGame("First civ game");
WriteResult<PBF, String> writeResult = pbfCollection.insert(pbf);
pbfId = writeResult.getSavedId();
PBF oneById = pbfCollection.findOneById(pbfId);
Playerhand cash1981 = createPlayerhand(createPlayer("cash1981", pbfId));
cash1981.setGameCreator(true);
cash1981.setYourTurn(true);
oneById.getPlayers().add(cash1981);
oneById.getPlayers().add(createPlayerhand(createPlayer("Karandras1", pbfId)));
oneById.getPlayers().add(createPlayerhand(createPlayer("Itchi", pbfId)));
oneById.getPlayers().add(createPlayerhand(createPlayer("Chul", pbfId)));
pbfCollection.updateById(pbfId, oneById);
}
private void createAnotherPBF() throws IOException {
PBFTestAction pbfTestAction = new PBFTestAction();
PBF pbf = pbfTestAction.createNewGame("Second civ game");
WriteResult<PBF, String> writeResult = pbfCollection.insert(pbf);
pbfId_2 = writeResult.getSavedId();
PBF oneById = pbfCollection.findOneById(pbfId_2);
Playerhand morthai = createPlayerhand(createPlayer("Morthai", pbfId_2));
morthai.setGameCreator(true);
morthai.setYourTurn(true);
oneById.getPlayers().add(morthai);
oneById.getPlayers().add(createPlayerhand(createPlayer("CJWF", pbfId_2)));
oneById.getPlayers().add(createPlayerhand(createPlayer("DaveLuca", pbfId_2)));
oneById.getPlayers().add(createPlayerhand(createPlayer("Foobar", pbfId_2)));
oneById.setActive(false);
pbfCollection.updateById(pbfId_2, oneById);
}
private void createEmptyPBF() throws IOException {
PBFTestAction pbfTestAction = new PBFTestAction();
PBF pbf = pbfTestAction.createNewGame("Third civ game");
WriteResult<PBF, String> writeResult = pbfCollection.insert(pbf);
pbfId_3 = writeResult.getSavedId();
}
private Playerhand createPlayerhand(Player player) {
Playerhand playerhand = new Playerhand();
playerhand.setUsername(player.getUsername());
playerhand.setPlayerId(player.getId());
playerhand.setColor("Red");
return playerhand;
}
private Player createPlayer(String username, String pbfId) throws JsonProcessingException {
//The Player object should be cached and retrieved from cache
Player player = new Player();
player.setUsername(username);
player.getGameIds().add(pbfId);
player.setEmail(username + "@mailinator.com");
player.setPassword(DigestUtils.sha1Hex("foo"));
WriteResult<Player, String> writeResult = playerCollection.insert(player);
System.out.println("Saved player " + writeResult.toString());
player.setId(writeResult.getSavedId());
return player;
}
}