sync updater with changes from android studio updater.

This commit is contained in:
Vladimir.Orlov
2014-10-20 15:58:12 +04:00
parent d57583ccf3
commit c80f3e562e
4 changed files with 258 additions and 0 deletions
@@ -0,0 +1,59 @@
package com.intellij.updater;
import java.io.DataInputStream;
import java.io.File;
import java.io.IOException;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;
public abstract class BaseDeleteAction extends PatchAction {
public BaseDeleteAction(String path, long checksum) {
super(path, checksum);
}
public BaseDeleteAction(DataInputStream in) throws IOException {
super(in);
}
@Override
public void doBuildPatchFile(File olderFile, File newerFile, ZipOutputStream patchOutput) throws IOException {
// do nothing
}
@Override
protected ValidationResult doValidate(File toFile) throws IOException {
ValidationResult result = doValidateAccess(toFile, ValidationResult.Action.DELETE);
if (result != null) return result;
if (toFile.exists() && isModified(toFile)) {
return new ValidationResult(ValidationResult.Kind.CONFLICT,
myPath,
ValidationResult.Action.DELETE,
"Modified",
ValidationResult.Option.DELETE,
ValidationResult.Option.KEEP);
}
return null;
}
@Override
protected boolean shouldApplyOn(File toFile) {
return toFile.exists();
}
@Override
protected void doApply(ZipFile patchFile, File toFile) throws IOException {
Utils.delete(toFile);
}
protected void doBackup(File toFile, File backupFile) throws IOException {
Utils.copy(toFile, backupFile);
}
protected void doRevert(File toFile, File backupFile) throws IOException {
if (!toFile.exists() || toFile.isDirectory() || isModified(toFile)) {
Utils.delete(toFile); // make sure there is no directory remained on this path (may remain from previous 'create' actions
Utils.copy(backupFile, toFile);
}
}
}
@@ -0,0 +1,20 @@
package com.intellij.updater;
import java.io.DataInputStream;
import java.io.File;
import java.io.IOException;
public class DeleteZipAction extends BaseDeleteAction {
public DeleteZipAction(String path, long checksum) {
super(path, checksum);
}
public DeleteZipAction(DataInputStream in) throws IOException {
super(in);
}
@Override
protected boolean isModified(File toFile) throws IOException {
return myChecksum != Digester.digestFile(toFile);
}
}
@@ -0,0 +1,113 @@
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.updater;
import com.sun.jna.Pointer;
import com.sun.jna.StringArray;
import com.sun.jna.WString;
import com.sun.jna.platform.win32.Kernel32;
import com.sun.jna.platform.win32.WinBase;
import com.sun.jna.platform.win32.WinNT;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.ptr.LongByReference;
import java.io.File;
import java.util.LinkedList;
import java.util.List;
/**
* A utility class to find processes that hold a lock to a file. This relies on a Windows API called
* RestartManager {@see http://msdn.microsoft.com/en-us/library/windows/desktop/cc948910(v=vs.85).aspx}
*
* This class uses the RestartManager and the Kernel32 APIs, and it tries to initialize them the first
* time it is run. If the RestartManager DLL is not found, it being because we are running on XP or
* because we are not running on Windows, then the class is flagged as failed and no further attempts
* will be made to load the DLL.
*/
public class NativeFileManager {
private static final int MAX_PROCESSES = 10;
private static boolean ourFailed = false;
public static class Process {
public final int pid;
public final String name;
public Process(int pid, String name) {
this.pid = pid;
this.name = name;
}
public boolean terminate() {
Kernel32.HANDLE process = Kernel32.INSTANCE.OpenProcess(WinNT.PROCESS_TERMINATE | WinNT.SYNCHRONIZE, false, pid);
if (process.getPointer() == null) {
Runner.logger.warn("Unable to find process " + name + "(" + pid + ")");
return false;
} else {
Kernel32.INSTANCE.TerminateProcess(process, 1);
int wait = Kernel32.INSTANCE.WaitForSingleObject(process, 1000);
if (wait != WinBase.WAIT_OBJECT_0) {
Runner.logger.warn("Timed out while waiting for process " + name + "(" + pid + ") to end");
return false;
}
Kernel32.INSTANCE.CloseHandle(process);
return true;
}
}
}
public static List<Process> getProcessesUsing(File file) {
List<Process> processes = new LinkedList<Process>();
// If the DLL was not present (XP or other OS), do not try to find it again.
if (ourFailed) {
return processes;
}
try {
IntByReference session = new IntByReference();
char[] sessionKey = new char[Win32RestartManager.CCH_RM_SESSION_KEY + 1];
int error = Win32RestartManager.INSTANCE.RmStartSession(session, 0, sessionKey);
if (error != 0) {
Runner.logger.warn("Unable to start restart manager session");
return processes;
}
StringArray resources = new StringArray(new WString[]{new WString(file.toString())});
error = Win32RestartManager.INSTANCE.RmRegisterResources(session.getValue(), 1, resources, 0, Pointer.NULL, 0, null);
if (error != 0) {
Runner.logger.warn("Unable to register restart manager resource " + file.getAbsolutePath());
return processes;
}
IntByReference procInfoNeeded = new IntByReference();
Win32RestartManager.RmProcessInfo info = new Win32RestartManager.RmProcessInfo();
Win32RestartManager.RmProcessInfo[] infos = (Win32RestartManager.RmProcessInfo[])info.toArray(MAX_PROCESSES);
IntByReference procInfo = new IntByReference(infos.length);
error = Win32RestartManager.INSTANCE.RmGetList(session.getValue(), procInfoNeeded, procInfo, info, new LongByReference());
if (error != 0) {
Runner.logger.warn("Unable to get the list of processes using " + file.getAbsolutePath());
return processes;
}
for (int i = 0; i < procInfo.getValue(); i++) {
processes.add(new Process(infos[i].Process.dwProcessId, new String(infos[i].strAppName).trim()));
}
Win32RestartManager.INSTANCE.RmEndSession(session.getValue());
} catch (Throwable t) {
// Best effort approach, if no DLL is found ignore.
ourFailed = true;
}
return processes;
}
}
@@ -0,0 +1,66 @@
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.updater;
import com.sun.jna.*;
import com.sun.jna.platform.win32.WinBase;
import com.sun.jna.platform.win32.WinDef;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.ptr.LongByReference;
public interface Win32RestartManager extends Library {
Win32RestartManager INSTANCE = (Win32RestartManager) Native.loadLibrary("Rstrtmgr", Win32RestartManager.class);
int CCH_RM_SESSION_KEY = 32;
int CCH_RM_MAX_APP_NAME = 255;
int CCH_RM_MAX_SVC_NAME = 63;
class RmUniqueProcess extends Structure {
public int dwProcessId;
public WinBase.FILETIME ProcessStartTime;
}
class RmProcessInfo extends Structure {
public RmUniqueProcess Process;
public char[] strAppName = new char[CCH_RM_MAX_APP_NAME + 1];
public char[] strServiceShortName = new char[CCH_RM_MAX_SVC_NAME + 1];
public int ApplicationType;
public WinDef.LONG AppStatus;
public int TSSessionId;
public boolean bRestartable;
}
int RmGetList(int dwSessionHandle,
IntByReference pnProcInfoNeeded,
IntByReference pnProcInfo,
RmProcessInfo rgAffectedApps,
LongByReference lpdwRebootReasons);
int RmStartSession(IntByReference pSessionHandle,
int dwSessionFlags,
char[] strSessionKey);
int RmRegisterResources(int dwSessionHandle,
int nFiles,
StringArray rgsFilenames,
int nApplications,
Pointer rgApplications,
int nServices,
StringArray rgsServiceNames);
int RmEndSession(int dwSessionHandle);
}