/**
* eobjects.org DataCleaner
* Copyright (C) 2010 eobjects.org
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* 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 Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.eobjects.datacleaner.user;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.message.BasicNameValuePair;
import org.eobjects.datacleaner.Main;
import org.eobjects.datacleaner.util.HttpXmlUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Class that handles remote logging of usage data
*
* @author Kasper Sørensen
*/
public final class UsageLogger {
private static final Logger logger = LoggerFactory.getLogger(UsageLogger.class);
// Special username used for anonymous entries. This is the only
// non-existing username that is allowed on server side.
private static final String NOT_LOGGED_IN_USERNAME = "[not-logged-in]";
private static final UsageLogger instance = new UsageLogger();
private final UserPreferences _userPreferences;
private ExecutorService _executorService;
public static UsageLogger getInstance() {
return instance;
}
// prevent instantiation
private UsageLogger() {
_userPreferences = UserPreferences.getInstance();
}
private ExecutorService getExecutorService() {
if (_executorService == null || _executorService.isShutdown()) {
_executorService = Executors.newSingleThreadExecutor();
}
return _executorService;
}
public void logApplicationStartup() {
final String action = "Startup";
final String username = getUsername();
logger.debug("Logging '{}'", action);
final Runnable runnable = new UsageLoggerRunnable(username, action);
getExecutorService().submit(runnable);
}
private String getUsername() {
if (_userPreferences.isLoggedIn()) {
return _userPreferences.getUsername();
} else {
return NOT_LOGGED_IN_USERNAME;
}
}
public void logApplicationShutdown() {
final String action = "Shutdown";
final String username = getUsername();
logger.debug("Logging '{}'", action);
final Runnable runnable = new UsageLoggerRunnable(username, action);
try {
getExecutorService().submit(runnable).get();
} catch (Exception e) {
logger.warn("Exception occurred sending shutdown message", e);
}
// order the executor service to shut down.
getExecutorService().shutdown();
}
public void log(final String action) {
if (!_userPreferences.isLoggedIn()) {
logger.debug("Not logging '{}', because user is not logged in", action);
return;
}
final String username = getUsername();
logger.debug("Logging '{}'", action);
final Runnable runnable = new UsageLoggerRunnable(username, action);
getExecutorService().submit(runnable);
}
/**
* Runnable implementation that does the actual remote notification. This is
* executed in a separate thread to avoid waiting for the user.
*
* @author Kasper Sørensen
*/
private static final class UsageLoggerRunnable implements Runnable {
private final String _username;
private final String _action;
public UsageLoggerRunnable(final String username, final String action) {
_username = username;
_action = action;
}
@Override
public void run() {
try {
final List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
final HttpPost req = new HttpPost("http://datacleaner.eobjects.org/ws/user_action");
nameValuePairs.add(new BasicNameValuePair("username", _username));
nameValuePairs.add(new BasicNameValuePair("action", _action));
nameValuePairs.add(new BasicNameValuePair("version", Main.VERSION));
req.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpResponse resp = HttpXmlUtils.getHttpClient().execute(req);
InputStream content = resp.getEntity().getContent();
String line = new BufferedReader(new InputStreamReader(content)).readLine();
assert "success".equals(line);
logger.debug("Usage logger response: {}", line);
} catch (Exception e) {
logger.warn("Could not dispatch usage log for action: {} ({})", _action, e.getMessage());
logger.debug("Error occurred while dispatching usage log", e);
}
}
}
}