/**
* Copyright (c) 2005-2011 by Appcelerator, Inc. All Rights Reserved.
* Licensed under the terms of the Eclipse Public License (EPL).
* Please see the license.txt included with this distribution for details.
* Any modifications to this file must keep this entire header intact.
*/
package org.python.pydev.logging.ping;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import org.python.pydev.core.docutils.StringUtils;
import org.python.pydev.core.log.Log;
import org.python.pydev.plugin.PydevPlugin;
import com.aptana.shared_core.io.FileUtils;
/**
* Used for usage statistics.
*
* This class is synchronized for concurrent access.
*/
public class SynchedLogPing implements ILogPing {
private File location;
private OutputStream bufferedOutputStream;
private final List<String> keyValueContents = new ArrayList<String>();
private ILogPingProvider provider;
public ILogPingSender sender;
private FileOutputStream stream;
private static Object lock = new Object();
public SynchedLogPing(String location) {
this(location, new LogInfoProvider(), new LogPingSender());
}
public SynchedLogPing(String location, ILogPingProvider provider, ILogPingSender sender) {
this.provider = provider;
this.sender = sender;
this.location = new File(location);
start();
}
private void start() {
synchronized (lock) {
if (this.location.exists()) {
//The file exists. Let's fill our list with its contents
String fileContents;
try {
fileContents = FileUtils.getFileContents(this.location);
} catch (Exception e) {
Log.log(e);
fileContents = "";
}
if (fileContents.length() > 1024 * 1024) {
//More than 1MB in the file. Let's throw the contents away (used for too long
//without being online or with active firewall).
try {
this.location.delete();
} catch (Exception e) {
Log.log(e);
}
}
List<String> fileLines = StringUtils.split(fileContents, '\n');
keyValueContents.addAll(fileLines);
}
try {
stream = new FileOutputStream(this.location, true);
bufferedOutputStream = new BufferedOutputStream(stream);
} catch (Exception e) {
try {
stream.close();
} catch (IOException e1) {
//ignore.
}
Log.log(e);
bufferedOutputStream = new OutputStream() {
public void write(int b) throws IOException {
//do nothing (just a stub keeping the interface).
}
};
}
}
}
/* (non-Javadoc)
* @see org.python.pydev.logging.ILogPing#addPingOpenEditor()
*/
public void addPingOpenEditor() {
synchronized (lock) {
String message = createPingOpenEditorEncodedMessage();
addEncodedMessage(message);
}
}
public void addPingStartPlugin() {
synchronized (lock) {
String message = createPingStartPluginEncodedMessage();
addEncodedMessage(message);
}
};
/*package*/String createPingOpenEditorEncodedMessage() {
return createEncodedMessage("editor.opened", ("PydevEditor_" + PydevPlugin.version));
}
/*package*/String createPingStartPluginEncodedMessage() {
return createEncodedMessage("plugin.started", ("Pydev_" + PydevPlugin.version));
}
/*package*/String createEncodedMessage(String key, String val) {
return StringUtils.urlEncodeKeyValuePair(key + "[]", provider.getCurrentTime() + ":" + val);
}
/*package*/void addEncodedMessage(String urlEncodeKeyValuePair) {
if (urlEncodeKeyValuePair != null) {
keyValueContents.add(urlEncodeKeyValuePair);
try {
bufferedOutputStream.write(urlEncodeKeyValuePair.getBytes());
bufferedOutputStream.write("\n".getBytes());
} catch (IOException e) {
Log.log(e);
}
}
}
/*package*/void clear() {
synchronized (lock) {
this.stop(); //clear in-memory
try {
this.location.delete(); //clear file
} catch (Exception e) {
Log.log(e);
}
this.start(); //recreate the initial structure
}
}
/*package*/String getContentsToSend() {
synchronized (lock) {
if (keyValueContents.size() > 0) {
return "id=" + provider.getApplicationId() + "&" + com.aptana.shared_core.string.StringUtils.join("&", keyValueContents);
}
}
return "";
}
/* (non-Javadoc)
* @see org.python.pydev.logging.ILogPing#send()
*/
public void send() {
synchronized (lock) {
String contentsToSend = getContentsToSend();
//System.out.println("Sending: "+contentsToSend);
if (this.sender.sendPing(contentsToSend)) {
this.clear();
}
}
}
/* (non-Javadoc)
* @see org.python.pydev.logging.ILogPing#stop()
*/
public void stop() {
synchronized (lock) {
this.keyValueContents.clear();
try {
this.bufferedOutputStream.flush();
} catch (IOException e) {
//ignore
}
try {
this.bufferedOutputStream.close();
} catch (IOException e) {
//ignore
}
try {
this.stream.close();
} catch (IOException e) {
//ignore
}
bufferedOutputStream = new OutputStream() {
public void write(int b) throws IOException {
//do nothing (just a stub keeping the interface).
}
};
}
}
}