<commit_before>/*
 * Tigase XMPP Client Library
 * Copyright (C) 2006-2012 "<NAME>" <<EMAIL>>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. Look for COPYING file in the top folder.
 * If not, see http://www.gnu.org/licenses/.
 */
package tigase.jaxmpp.j2se;

import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.Executor;
import java.util.logging.Level;

import tigase.jaxmpp.core.client.Connector;
import tigase.jaxmpp.core.client.Connector.ConnectorEvent;
import tigase.jaxmpp.core.client.JaxmppCore;
import tigase.jaxmpp.core.client.Processor;
import tigase.jaxmpp.core.client.SessionObject;
import tigase.jaxmpp.core.client.XmppSessionLogic.SessionListener;
import tigase.jaxmpp.core.client.exceptions.JaxmppException;
import tigase.jaxmpp.core.client.observer.Observable;
import tigase.jaxmpp.core.client.observer.ObservableFactory;
import tigase.jaxmpp.core.client.observer.ObservableFactory.FactorySpi;
import tigase.jaxmpp.core.client.xml.Element;
import tigase.jaxmpp.core.client.xml.XMLException;
import tigase.jaxmpp.core.client.xmpp.modules.ResourceBinderModule;
import tigase.jaxmpp.core.client.xmpp.modules.ResourceBinderModule.ResourceBindEvent;
import tigase.jaxmpp.core.client.xmpp.modules.capabilities.CapabilitiesModule;
import tigase.jaxmpp.core.client.xmpp.modules.disco.DiscoInfoModule;
import tigase.jaxmpp.core.client.xmpp.modules.presence.PresenceModule;
import tigase.jaxmpp.core.client.xmpp.utils.DateTimeFormat;
import tigase.jaxmpp.j2se.connectors.bosh.BoshConnector;
import tigase.jaxmpp.j2se.connectors.socket.SocketConnector;
import tigase.jaxmpp.j2se.observer.ThreadSafeObservable;

public class Jaxmpp extends JaxmppCore {

	private class LoginTimeoutTask extends TimerTask {

		@Override
		public void run() {
			synchronized (Jaxmpp.this) {
				Jaxmpp.this.notify();
			}
		}
	}

	public static final String CONNECTOR_TYPE = "connectorType";

	private static final Executor DEFAULT_EXECUTOR = new Executor() {

		@Override
		public void execute(Runnable command) {
			(new Thread(command)).start();
		}
	};

	public static final String EXCEPTION_KEY = "jaxmpp#ThrowedException";;

	public static final String LOGIN_TIMEOUT_KEY = "LOGIN_TIMEOUT_KEY";

	public static final String SYNCHRONIZED_MODE = "jaxmpp#synchronized";

	static {
		ObservableFactory.setFactorySpi(new FactorySpi() {

			@Override
			public Observable create() {
				return create(null);
			}

			@Override
			public Observable create(Observable parent) {
				return new ThreadSafeObservable(parent);
			}
		});
		DateTimeFormat.setProvider(new DateTimeFormatProviderImpl());
	}

	private Executor executor;

	private TimerTask loginTimeoutTask;

	private final Timer timer = new Timer(true);

	public Jaxmpp() {
		this(new J2SESessionObject());
		setExecutor(DEFAULT_EXECUTOR);
	}

	public Jaxmpp(SessionObject sessionObject) {
		super(sessionObject);
		setExecutor(DEFAULT_EXECUTOR);
		TimerTask checkTimeouts = new TimerTask() {

			@Override
			public void run() {
				try {
					checkTimeouts();
				} catch (JaxmppException e) {
					e.printStackTrace();
				}
			}
		};
		timer.schedule(checkTimeouts, 30 * 1000, 30 * 1000);

		this.processor = new Processor(this.modulesManager, this.sessionObject, this.writer);

		modulesInit();

		ResourceBinderModule r = this.modulesManager.getModule(ResourceBinderModule.class);
		r.addListener(ResourceBinderModule.ResourceBindSuccess, resourceBindListener);

	}

	protected void checkTimeouts() throws JaxmppException {
		sessionObject.checkHandlersTimeout();
	}

	@Override
	public void disconnect() throws JaxmppException {
		disconnect(false);
	}

	public void disconnect(boolean snc) throws JaxmppException {
		if (this.connector != null) {
			try {
				this.connector.stop();
			} catch (XMLException e) {
				throw new JaxmppException(e);
			}
			Boolean sync = (Boolean) this.sessionObject.getProperty(SYNCHRONIZED_MODE);
			if (sync != null && sync) {
				synchronized (Jaxmpp.this) {
					// Jaxmpp.this.wait();
				}
			}
		}
	}

	/**
	 * {@inheritDoc}
	 */
	@SuppressWarnings("unchecked")
	@Override
	public ConnectionConfiguration getConnectionConfiguration() {
		return new ConnectionConfiguration(this.sessionObject);
	}

	public Executor getExecutor() {
		return executor;
	}

	@Override
	public void login() throws JaxmppException {
		login(true);
	}

	public void login(boolean sync) throws JaxmppException {
		this.sessionObject.clear();

		if (this.sessionLogic != null) {
			this.sessionLogic.unbind();
			this.sessionLogic = null;
		}
		if (this.connector != null) {
			this.connector.removeAllListeners();
			this.connector = null;
		}

		if (sessionObject.getProperty(CONNECTOR_TYPE) == null || "socket".equals(sessionObject.getProperty(CONNECTOR_TYPE))) {
			log.info("Using SocketConnector");
			this.connector = new SocketConnector(observable, this.sessionObject);
		} else if ("bosh".equals(sessionObject.getProperty(CONNECTOR_TYPE))) {
			log.info("Using BOSHConnector");
			this.connector = new BoshConnector(observable, this.sessionObject);
		} else
			throw new JaxmppException("Unknown connector type");

		this.connector.addListener(Connector.StanzaReceived, this.stanzaReceivedListener);
		connector.addListener(Connector.StreamTerminated, this.streamTerminateListener);
		connector.addListener(Connector.Error, this.streamErrorListener);

		this.sessionLogic = connector.createSessionLogic(modulesManager, this.writer);
		this.sessionLogic.setSessionListener(new SessionListener() {

			@Override
			public void onException(JaxmppException e) throws JaxmppException {
				Jaxmpp.this.onException(e);
			}
		});

		try {
			this.sessionLogic.beforeStart();
			this.connector.start();
			this.sessionObject.setProperty(SYNCHRONIZED_MODE, Boolean.valueOf(sync));
			if (sync) {
				loginTimeoutTask = new LoginTimeoutTask();<commit_msg>add protected method to create new Connector instance<commit_after>/*
 * Tigase XMPP Client Library
 * Copyright (C) 2006-2012 "<NAME>" <<EMAIL>>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. Look for COPYING file in the top folder.
 * If not, see http://www.gnu.org/licenses/.
 */
package tigase.jaxmpp.j2se;

import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.Executor;
import java.util.logging.Level;

import tigase.jaxmpp.core.client.Connector;
import tigase.jaxmpp.core.client.Connector.ConnectorEvent;
import tigase.jaxmpp.core.client.JaxmppCore;
import tigase.jaxmpp.core.client.Processor;
import tigase.jaxmpp.core.client.SessionObject;
import tigase.jaxmpp.core.client.XmppSessionLogic.SessionListener;
import tigase.jaxmpp.core.client.exceptions.JaxmppException;
import tigase.jaxmpp.core.client.observer.Observable;
import tigase.jaxmpp.core.client.observer.ObservableFactory;
import tigase.jaxmpp.core.client.observer.ObservableFactory.FactorySpi;
import tigase.jaxmpp.core.client.xml.Element;
import tigase.jaxmpp.core.client.xml.XMLException;
import tigase.jaxmpp.core.client.xmpp.modules.ResourceBinderModule;
import tigase.jaxmpp.core.client.xmpp.modules.ResourceBinderModule.ResourceBindEvent;
import tigase.jaxmpp.core.client.xmpp.modules.capabilities.CapabilitiesModule;
import tigase.jaxmpp.core.client.xmpp.modules.disco.DiscoInfoModule;
import tigase.jaxmpp.core.client.xmpp.modules.presence.PresenceModule;
import tigase.jaxmpp.core.client.xmpp.utils.DateTimeFormat;
import tigase.jaxmpp.j2se.connectors.bosh.BoshConnector;
import tigase.jaxmpp.j2se.connectors.socket.SocketConnector;
import tigase.jaxmpp.j2se.observer.ThreadSafeObservable;

public class Jaxmpp extends JaxmppCore {

	private class LoginTimeoutTask extends TimerTask {

		@Override
		public void run() {
			synchronized (Jaxmpp.this) {
				Jaxmpp.this.notify();
			}
		}
	}

	public static final String CONNECTOR_TYPE = "connectorType";

	private static final Executor DEFAULT_EXECUTOR = new Executor() {

		@Override
		public void execute(Runnable command) {
			(new Thread(command)).start();
		}
	};

	public static final String EXCEPTION_KEY = "jaxmpp#ThrowedException";;

	public static final String LOGIN_TIMEOUT_KEY = "LOGIN_TIMEOUT_KEY";

	public static final String SYNCHRONIZED_MODE = "jaxmpp#synchronized";

	static {
		ObservableFactory.setFactorySpi(new FactorySpi() {

			@Override
			public Observable create() {
				return create(null);
			}

			@Override
			public Observable create(Observable parent) {
				return new ThreadSafeObservable(parent);
			}
		});
		DateTimeFormat.setProvider(new DateTimeFormatProviderImpl());
	}

	private Executor executor;

	private TimerTask loginTimeoutTask;

	private final Timer timer = new Timer(true);

	public Jaxmpp() {
		this(new J2SESessionObject());
		setExecutor(DEFAULT_EXECUTOR);
	}

	public Jaxmpp(SessionObject sessionObject) {
		super(sessionObject);
		setExecutor(DEFAULT_EXECUTOR);
		TimerTask checkTimeouts = new TimerTask() {

			@Override
			public void run() {
				try {
					checkTimeouts();
				} catch (JaxmppException e) {
					e.printStackTrace();
				}
			}
		};
		timer.schedule(checkTimeouts, 30 * 1000, 30 * 1000);

		this.processor = new Processor(this.modulesManager, this.sessionObject, this.writer);

		modulesInit();

		ResourceBinderModule r = this.modulesManager.getModule(ResourceBinderModule.class);
		r.addListener(ResourceBinderModule.ResourceBindSuccess, resourceBindListener);

	}

	protected void checkTimeouts() throws JaxmppException {
		sessionObject.checkHandlersTimeout();
	}

	protected Connector createConnector() throws JaxmppException {
		if (sessionObject.getProperty(CONNECTOR_TYPE) == null || "socket".equals(sessionObject.getProperty(CONNECTOR_TYPE))) {
			log.info("Using SocketConnector");
			return new SocketConnector(observable, this.sessionObject);
		} else if ("bosh".equals(sessionObject.getProperty(CONNECTOR_TYPE))) {
			log.info("Using BOSHConnector");
			return new BoshConnector(observable, this.sessionObject);
		} else
			throw new JaxmppException("Unknown connector type");
	}

	@Override
	public void disconnect() throws JaxmppException {
		disconnect(false);
	}

	public void disconnect(boolean snc) throws JaxmppException {
		if (this.connector != null) {
			try {
				this.connector.stop();
			} catch (XMLException e) {
				throw new JaxmppException(e);
			}
			Boolean sync = (Boolean) this.sessionObject.getProperty(SYNCHRONIZED_MODE);
			if (sync != null && sync) {
				synchronized (Jaxmpp.this) {
					// Jaxmpp.this.wait();
				}
			}
		}
	}

	/**
	 * {@inheritDoc}
	 */
	@SuppressWarnings("unchecked")
	@Override
	public ConnectionConfiguration getConnectionConfiguration() {
		return new ConnectionConfiguration(this.sessionObject);
	}

	public Executor getExecutor() {
		return executor;
	}

	@Override
	public void login() throws JaxmppException {
		login(true);
	}

	public void login(boolean sync) throws JaxmppException {
		this.sessionObject.clear();

		if (this.sessionLogic != null) {
			this.sessionLogic.unbind();
			this.sessionLogic = null;
		}
		if (this.connector != null) {
			this.connector.removeAllListeners();
			this.connector = null;
		}

		this.connector = getConnector();

		this.connector.addListener(Connector.StanzaReceived, this.stanzaReceivedListener);
		connector.addListener(Connector.StreamTerminated, this.streamTerminateListener);
		connector.addListener(Connector.Error, this.streamErrorListener);

		this.sessionLogic = connector.createSessionLogic(modulesManager, this.writer);
		this.sessionLogic.setSessionListener(new SessionListener() {

			@Override
			public void onException(JaxmppException e) throws JaxmppException {
				Jaxmpp.this.onException(e);
			}
		});

		try {
			this.sessionLogic.beforeStart();
			this.connector.start();
			this.sessionObject.setProperty(SYNCHRONIZED_MODE, Boolean.valueOf(sync));
			if (sync) {
				loginTimeoutTask = new LoginTimeoutTask();
{'fraction_non_alphanumeric': 0.10213260953858085, 'fraction_numerical': 0.004032570763861962, 'mean_word_length': 4.8352941176470585, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 4}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7656743', 'n_tokens_mistral': 4438, 'n_tokens_neox': 4017, 'n_words': 865}