PretendYoureXyzzy/src/main/java/net/socialgamer/cah/CahModule.java

585 lines
15 KiB
Java

/**
* Copyright (c) 2012-2018, Andy Janata
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted
* provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this list of conditions
* and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
* WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.socialgamer.cah;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.Properties;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;
import javax.servlet.ServletContext;
import com.google.inject.*;
import net.socialgamer.cah.data.GameOptions;
import org.apache.log4j.Logger;
import org.hibernate.Session;
import com.google.common.collect.ImmutableSet;
import com.google.inject.assistedinject.FactoryModuleBuilder;
import net.socialgamer.cah.data.GameManager;
import net.socialgamer.cah.data.GameManager.GameId;
import net.socialgamer.cah.data.GameManager.MaxGames;
import net.socialgamer.cah.data.User;
import net.socialgamer.cah.metrics.Metrics;
import net.socialgamer.cah.metrics.UniqueIds;
/**
* CAH Guice module.
*
* @author Andy Janata (ajanata@socialgamer.net)
*/
public class CahModule extends AbstractModule {
private static final Logger LOG = Logger.getLogger(CahModule.class);
private final Properties properties = new Properties();
private final ServletContext context;
public CahModule(final ServletContext context) {
this.context = context;
}
@Override
protected void configure() {
bind(Integer.class)
.annotatedWith(GameId.class)
.toProvider(GameManager.class);
/*
* A mutable Set of IP addresses (in String format) which are banned. This Set is
* thread-safe.
*/
bind(new TypeLiteral<Set<String>>() {
})
.annotatedWith(BanList.class)
.toInstance(Collections.synchronizedSet(new HashSet<String>()));
bind(Properties.class).toInstance(properties);
// this is only so injected constructors can log
StartupUtils.reconfigureLogging(context);
// FIXME huge hack.
StartupUtils.reloadProperties(context, properties);
final String metricsClassName = properties.getProperty("pyx.metrics.impl");
try {
@SuppressWarnings("unchecked")
final Class<? extends Metrics> metricsClass = (Class<? extends Metrics>) Class
.forName(metricsClassName);
bind(Metrics.class).to(metricsClass);
} catch (final ClassNotFoundException e) {
throw new RuntimeException(e);
}
bind(Date.class).annotatedWith(ServerStarted.class).toInstance(new Date());
bind(String.class).annotatedWith(UniqueId.class).toProvider(UniqueIds.class);
install(new FactoryModuleBuilder().build(User.Factory.class));
final ScheduledThreadPoolExecutor threadPool =
new ScheduledThreadPoolExecutor(2 * Runtime.getRuntime().availableProcessors(),
new ThreadFactory() {
final AtomicInteger threadCount = new AtomicInteger();
@Override
public Thread newThread(final Runnable r) {
final Thread t = new Thread(r);
t.setDaemon(true);
t.setName("timer-task-" + threadCount.incrementAndGet());
return t;
}
});
threadPool.setRemoveOnCancelPolicy(true);
bind(ScheduledThreadPoolExecutor.class).toInstance(threadPool);
}
@Provides
@UserPersistentId
String provideUserPersistentId() {
return UUID.randomUUID().toString();
}
/**
* @return The maximum number of games allowed on this server.
*/
@Provides
@MaxGames
Integer provideMaxGames() {
synchronized (properties) {
return Integer.valueOf(properties.getProperty("pyx.server.max_games", "20"));
}
}
/**
* @return The maximum number of users allowed to connect to this server.
*/
@Provides
@MaxUsers
Integer provideMaxUsers() {
synchronized (properties) {
return Integer.valueOf(properties.getProperty("pyx.server.max_users", "100"));
}
}
@Provides
@BroadcastConnectsAndDisconnects
Boolean provideBroadcastConnectsAndDisconnects() {
synchronized (properties) {
return Boolean.valueOf(properties.getProperty(
"pyx.server.broadcast_connects_and_disconnects", "true"));
}
}
@Provides
@GlobalChatEnabled
Boolean provideGlobalChatEnabled() {
synchronized (properties) {
return Boolean.valueOf(properties.getProperty(
"pyx.server.global_chat_enabled", "true"));
}
}
@Provides
@GameChatEnabled
Boolean provideGameChatEnabled() {
synchronized (properties) {
return Boolean.valueOf(properties.getProperty("pyx.server.game_chat_enabled", "true"));
}
}
@Provides
@ShowGamePermalink
Boolean provideShowGamePermalink() {
synchronized (properties) {
return Boolean.valueOf(properties.getProperty("pyx.metrics.game.enabled", "false"));
}
}
@Provides
@GamePermalinkUrlFormat
String provideGamePermalinkUrlFormat() {
synchronized (properties) {
return properties.getProperty("pyx.metrics.game.url_format", "about:blank#%s");
}
}
@Provides
@ShowRoundPermalink
Boolean provideShowRoundPermalink() {
synchronized (properties) {
return Boolean.valueOf(properties.getProperty("pyx.metrics.round.enabled", "false"));
}
}
@Provides
@RoundPermalinkUrlFormat
String provideRoundPermalinkUrlFormat() {
synchronized (properties) {
return properties.getProperty("pyx.metrics.round.url_format", "about:blank#%s");
}
}
@Provides
@ShowSessionPermalink
Boolean provideShowSessionPermalink() {
synchronized (properties) {
return Boolean.valueOf(properties.getProperty("pyx.metrics.session.enabled", "false"));
}
}
@Provides
@SessionPermalinkUrlFormat
String provideSessionPermalinkUrlFormat() {
synchronized (properties) {
return properties.getProperty("pyx.metrics.session.url_format", "about:blank#%s");
}
}
@Provides
@ShowUserPermalink
Boolean provideShowUserPermalink() {
synchronized (properties) {
return Boolean.valueOf(properties.getProperty("pyx.metrics.user.enabled", "false"));
}
}
@Provides
@UserPermalinkUrlFormat
String provideUserPermalinkUrlFormat() {
synchronized (properties) {
return properties.getProperty("pyx.metrics.user.url_format", "about:blank#%s");
}
}
@Provides
@InsecureIdAllowed
Boolean provideInsecureIdAllowed() {
synchronized (properties) {
return Boolean.valueOf(properties.getProperty(
"pyx.server.insecure_id_allowed", "true"));
}
}
@Provides
@IdCodeSalt
String provideIdCodeSalt() {
synchronized (properties) {
return properties.getProperty("pyx.server.id_code_salt", "");
}
}
@Provides
@CookieDomain
String getCookieDomain() {
synchronized (properties) {
return properties.getProperty("pyx.client.cookie_domain", ".localhost");
}
}
@Provides
@IncludeInactiveCardsets
Boolean getIncludeInactiveCardsets() {
synchronized (properties) {
return Boolean.valueOf(properties
.getProperty("pyx.server.include_inactive_cardsets", "false"));
}
}
/**
* @return A Hibernate session. Objects which receive a Hibernate session should close the
* session when they are done!
*/
@Provides
Session provideHibernateSession() {
final Session session = HibernateUtil.instance.sessionFactory.openSession();
if (!session.isConnected()) {
LOG.error("Session disconnected!");
}
return session;
}
@Provides
@Admins
Set<String> provideAdmins() {
synchronized (properties) {
return ImmutableSet
.copyOf(properties.getProperty("pyx.server.admin_addrs", "127.0.0.1,::1").split(","));
}
}
@Provides
@BannedNicks
Set<String> provideBannedNicks() {
synchronized (properties) {
return ImmutableSet.copyOf(properties.getProperty("pyx.banned_nicks", "").split(","));
}
}
@Provides
@AllowBlankCards
Boolean provideAllowBlankCards() {
synchronized (properties) {
return Boolean.valueOf(properties.getProperty("pyx.server.allow_blank_cards", "true"));
}
}
@BindingAnnotation
@Retention(RetentionPolicy.RUNTIME)
public @interface BanList {
}
@BindingAnnotation
@Retention(RetentionPolicy.RUNTIME)
public @interface MaxUsers {
}
@BindingAnnotation
@Retention(RetentionPolicy.RUNTIME)
public @interface ShowGamePermalink {
}
@BindingAnnotation
@Retention(RetentionPolicy.RUNTIME)
public @interface GamePermalinkUrlFormat {
}
@BindingAnnotation
@Retention(RetentionPolicy.RUNTIME)
public @interface ShowRoundPermalink {
}
@BindingAnnotation
@Retention(RetentionPolicy.RUNTIME)
public @interface RoundPermalinkUrlFormat {
}
@BindingAnnotation
@Retention(RetentionPolicy.RUNTIME)
public @interface ShowSessionPermalink {
}
@BindingAnnotation
@Retention(RetentionPolicy.RUNTIME)
public @interface SessionPermalinkUrlFormat {
}
@BindingAnnotation
@Retention(RetentionPolicy.RUNTIME)
public @interface ShowUserPermalink {
}
@BindingAnnotation
@Retention(RetentionPolicy.RUNTIME)
public @interface UserPermalinkUrlFormat {
}
@BindingAnnotation
@Retention(RetentionPolicy.RUNTIME)
public @interface BroadcastConnectsAndDisconnects {
}
@BindingAnnotation
@Retention(RetentionPolicy.RUNTIME)
public @interface GlobalChatEnabled {
}
@BindingAnnotation
@Retention(RetentionPolicy.RUNTIME)
public @interface GameChatEnabled {
}
@BindingAnnotation
@Retention(RetentionPolicy.RUNTIME)
public @interface InsecureIdAllowed {
}
@BindingAnnotation
@Retention(RetentionPolicy.RUNTIME)
public @interface IdCodeSalt {
}
@BindingAnnotation
@Retention(RetentionPolicy.RUNTIME)
public @interface CookieDomain {
}
@BindingAnnotation
@Retention(RetentionPolicy.RUNTIME)
public @interface IncludeInactiveCardsets {
}
@BindingAnnotation
@Retention(RetentionPolicy.RUNTIME)
public @interface ServerStarted {
}
@BindingAnnotation
@Retention(RetentionPolicy.RUNTIME)
public @interface UniqueId {
}
@BindingAnnotation
@Retention(RetentionPolicy.RUNTIME)
public @interface UserPersistentId {
}
@BindingAnnotation
@Retention(RetentionPolicy.RUNTIME)
public @interface Admins {
}
@BindingAnnotation
@Retention(RetentionPolicy.RUNTIME)
public @interface BannedNicks {
}
@BindingAnnotation
@Retention(RetentionPolicy.RUNTIME)
public @interface AllowBlankCards {
}
@BindingAnnotation
@Retention(RetentionPolicy.RUNTIME)
public @interface MinScoreLimit {
}
@Provides
@MinScoreLimit
Integer provideMinScoreLimit() {
synchronized (properties) {
return Integer.valueOf(properties.getProperty("pyx.game.min_score_limit", "4"));
}
}
@BindingAnnotation
@Retention(RetentionPolicy.RUNTIME)
public @interface DefaultScoreLimit {
}
@Provides
@DefaultScoreLimit
Integer provideDefaultScoreLimit() {
synchronized (properties) {
return Integer.valueOf(properties.getProperty("pyx.game.default_score_limit", "8"));
}
}
@BindingAnnotation
@Retention(RetentionPolicy.RUNTIME)
public @interface MaxScoreLimit {
}
@Provides
@MaxScoreLimit
Integer provideMaxScoreLimit() {
synchronized (properties) {
return Integer.valueOf(properties.getProperty("pyx.game.max_score_limit", "69"));
}
}
@BindingAnnotation
@Retention(RetentionPolicy.RUNTIME)
public @interface MinPlayerLimit {
}
@Provides
@MinPlayerLimit
Integer provideMinPlayerLimit() {
synchronized (properties) {
return Integer.valueOf(properties.getProperty("pyx.game.min_player_limit", "3"));
}
}
@BindingAnnotation
@Retention(RetentionPolicy.RUNTIME)
public @interface DefaultPlayerLimit {
}
@Provides
@DefaultPlayerLimit
Integer provideDefaultPlayerLimit() {
synchronized (properties) {
return Integer.valueOf(properties.getProperty("pyx.game.default_player_limit", "10"));
}
}
@BindingAnnotation
@Retention(RetentionPolicy.RUNTIME)
public @interface MaxPlayerLimit {
}
@Provides
@MaxPlayerLimit
Integer provideMaxPlayerLimit() {
synchronized (properties) {
return Integer.valueOf(properties.getProperty("pyx.game.max_player_limit", "20"));
}
}
@BindingAnnotation
@Retention(RetentionPolicy.RUNTIME)
public @interface MinSpectatorLimit {
}
@Provides
@MinSpectatorLimit
Integer provideMinSpectatorLimit() {
synchronized (properties) {
return Integer.valueOf(properties.getProperty("pyx.game.min_spectator_limit", "0"));
}
}
@BindingAnnotation
@Retention(RetentionPolicy.RUNTIME)
public @interface DefaultSpectatorLimit {
}
@Provides
@DefaultSpectatorLimit
Integer provideDefaultSpectatorLimit() {
synchronized (properties) {
return Integer.valueOf(properties.getProperty("pyx.game.default_spectator_limit", "10"));
}
}
@BindingAnnotation
@Retention(RetentionPolicy.RUNTIME)
public @interface MaxSpectatorLimit {
}
@Provides
@MaxSpectatorLimit
Integer provideMaxSpectatorLimit() {
synchronized (properties) {
return Integer.valueOf(properties.getProperty("pyx.game.max_spectator_limit", "20"));
}
}
@BindingAnnotation
@Retention(RetentionPolicy.RUNTIME)
public @interface MinBlankCardLimit {
}
@Provides
@MinBlankCardLimit
Integer provideMinBlankCardLimit() {
synchronized (properties) {
return Integer.valueOf(properties.getProperty("pyx.game.min_blank_card_limit", "0"));
}
}
@BindingAnnotation
@Retention(RetentionPolicy.RUNTIME)
public @interface DefaultBlankCardLimit {
}
@Provides
@DefaultBlankCardLimit
Integer provideDefaultBlankCardLimit() {
synchronized (properties) {
return Integer.valueOf(properties.getProperty("pyx.game.default_blank_card_limit", "0"));
}
}
@BindingAnnotation
@Retention(RetentionPolicy.RUNTIME)
public @interface MaxBlankCardLimit {
}
@Provides
@MaxBlankCardLimit
Integer provideMaxBlankCardLimit() {
synchronized (properties) {
return Integer.valueOf(properties.getProperty("pyx.game.max_blank_card_limit", "30"));
}
}
}