blob: cf19c90ecc656ebb9e8467bb5a0477f19f62619f [file] [log] [blame]
package org.jetbrains.android.database;
import com.android.ddmlib.AndroidDebugBridge;
import com.android.ddmlib.IDevice;
import com.intellij.CommonBundle;
import com.intellij.database.psi.DbDataSourceElement;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import org.jetbrains.android.sdk.AndroidSdkUtils;
import org.jetbrains.android.util.AndroidBundle;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.*;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import static com.intellij.database.view.DatabaseView.getSelectedElements;
/**
* @author Eugene.Kudelevsky
*/
public class AndroidUploadDatabaseAction extends AnAction {
private static final Logger LOG = Logger.getInstance("#org.jetbrains.android.database.AndroidUploadDatabaseAction");
@Override
public void update(AnActionEvent e) {
final Project project = e.getProject();
e.getPresentation().setVisible(project != null && !getSelectedAndroidDataSources(e).isEmpty());
}
@Override
public void actionPerformed(AnActionEvent e) {
final Project project = e.getProject();
assert project != null;
final List<AndroidDataSource> dataSources = getSelectedAndroidDataSources(e);
final AndroidDebugBridge debugBridge = AndroidSdkUtils.getDebugBridge(project);
if (debugBridge == null) {
Messages.showErrorDialog(project, AndroidBundle.message("cannot.connect.to.adb.error"), CommonBundle.getErrorTitle());
return;
}
ProgressManager.getInstance().run(new Task.Backgroundable(project, AndroidBundle.message("android.db.uploading.progress.title"), true) {
@Override
public void run(@NotNull ProgressIndicator indicator) {
for (final AndroidDataSource dataSource : dataSources) {
indicator.setText("Uploading " + dataSource.getName());
synchronized (AndroidDbUtil.DB_SYNC_LOCK) {
uploadDatabase(project, dataSource, indicator, debugBridge);
}
indicator.checkCanceled();
}
}
});
}
@NotNull
private static List<AndroidDataSource> getSelectedAndroidDataSources(AnActionEvent e) {
final Set<DbDataSourceElement> dataSourceElements = getSelectedElements(e.getDataContext(), DbDataSourceElement.class);
if (dataSourceElements.isEmpty()) {
return Collections.emptyList();
}
final List<AndroidDataSource> androidDataSources = new ArrayList<AndroidDataSource>();
for (DbDataSourceElement element : dataSourceElements) {
final Object delegate = element.getDelegate();
if (delegate instanceof AndroidDataSource) {
androidDataSources.add((AndroidDataSource)delegate);
}
}
return androidDataSources;
}
private static void uploadDatabase(@NotNull Project project,
@NotNull AndroidDataSource dataSource,
@NotNull ProgressIndicator indicator,
@NotNull AndroidDebugBridge debugBridge) {
final String localDbFilePath = dataSource.buildLocalDbFileOsPath();
final AndroidDbErrorReporterImpl errorReporter = new AndroidDbErrorReporterImpl(project, dataSource, true);
final AndroidDbConnectionInfo dbConnectionInfo = AndroidDbUtil.checkDataSource(dataSource, debugBridge, errorReporter);
if (dbConnectionInfo == null) {
return;
}
final IDevice device = dbConnectionInfo.getDevice();
final String packageName = dbConnectionInfo.getPackageName();
final String dbName = dbConnectionInfo.getDbName();
final String localFileMd5Hash = getLocalFileMd5Hash(new File(localDbFilePath));
final String deviceId = AndroidDbUtil.getDeviceId(device);
final boolean external = dbConnectionInfo.isExternal();
if (localFileMd5Hash == null || deviceId == null) {
return;
}
if (AndroidDbUtil.uploadDatabase(device, packageName, dbName, external, localDbFilePath, indicator, errorReporter)) {
final Long modificationTime = AndroidDbUtil.getModificationTime(device, packageName, dbName, external, errorReporter, indicator);
if (modificationTime != null) {
AndroidRemoteDataBaseManager.MyDatabaseInfo dbInfo = AndroidRemoteDataBaseManager.
getInstance().getDatabaseInfo(deviceId, packageName, dbName, external);
if (dbInfo == null) {
dbInfo = new AndroidRemoteDataBaseManager.MyDatabaseInfo();
}
dbInfo.modificationTime = modificationTime;
AndroidRemoteDataBaseManager.getInstance().setDatabaseInfo(deviceId, packageName, dbName, dbInfo, external);
}
}
}
@Nullable
private static String getLocalFileMd5Hash(@NotNull File file) {
try {
final byte[] buffer = new byte[1024];
final MessageDigest md5 = MessageDigest.getInstance("MD5");
final InputStream fis = new BufferedInputStream(new FileInputStream(file));
try {
int read;
while ((read = fis.read(buffer)) > 0) {
md5.update(buffer, 0, read);
}
}
finally {
fis.close();
}
final StringBuilder builder = new StringBuilder();
for (byte b : md5.digest()) {
builder.append(Integer.toString((b & 0xff) + 0x100, 16).substring(1));
}
return builder.toString();
}
catch (IOException e) {
LOG.error(e);
return null;
}
catch (NoSuchAlgorithmException e) {
LOG.error(e);
return null;
}
}
}