Initial support for IDEA-108265. Currently only "Recent" projects are available.

This commit is contained in:
Denis Fokin
2013-08-08 16:23:43 +04:00
parent b47f1be290
commit 11afb9b5e7
8 changed files with 238 additions and 1 deletions
Binary file not shown.
Binary file not shown.
@@ -79,6 +79,12 @@ public class SocketLock {
}
}
private volatile int acquiredPort = -1;
public synchronized int getAcquiredPort () {
return acquiredPort;
}
public synchronized ActivateStatus lock(String path, boolean markPort, String... args) {
if (LOG.isDebugEnabled()) {
LOG.debug("enter: lock(path='" + path + "')");
@@ -194,6 +200,7 @@ public class SocketLock {
mySocket = new ServerSocket(i, 50, InetAddress.getByName("127.0.0.1"));
port = i;
acquiredPort = port;
break;
}
catch (IOException e) {
@@ -76,6 +76,10 @@ public class StartupUtil {
void start(boolean newConfigFolder);
}
public synchronized static int getAcquiredPort() {
return ourLock.getAcquiredPort();
}
static void prepareAndStart(String[] args, AppStarter appStarter) {
boolean newConfigFolder = false;
@@ -17,6 +17,7 @@ package com.intellij.openapi.wm.impl;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.ui.mac.MacDockDelegate;
import com.intellij.ui.win.WinDockDelegate;
/**
* @author Denis Fokin
@@ -28,6 +29,8 @@ public class SystemDock {
static {
if (SystemInfo.isMac) {
delegate = MacDockDelegate.getInstance();
} else if (SystemInfo.isWin7OrNewer) {
delegate = WinDockDelegate.getInstance();
}
}
@@ -36,7 +39,7 @@ public class SystemDock {
delegate.updateRecentProjectsMenu();
}
public static interface Delegate {
public interface Delegate {
void updateRecentProjectsMenu();
}
}
@@ -0,0 +1,91 @@
/*
* Copyright 2000-2013 JetBrains s.r.o.
*
* 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.ui.win;
import com.intellij.openapi.application.PathManager;
import java.io.File;
import java.lang.ref.WeakReference;
import java.util.concurrent.atomic.AtomicBoolean;
public class RecentTasks {
private static AtomicBoolean initialiazed =
new AtomicBoolean(false);
private final static WeakReference<Thread> openerThread =
new WeakReference<Thread>(Thread.currentThread());
static {
final String libraryName = (System.getProperty("sun.arch.data.model").contains("64"))?
"jumplistbridge64.dll":
"jumplistbridge.dll";
final String binPath = PathManager.getBinPath();
final String communityBinPath = PathManager.getHomePath() + File.separatorChar + "community" + File.separatorChar + "bin";
final String [] libraryPaths = {
binPath,
binPath + File.separatorChar + "win",
communityBinPath,
communityBinPath + File.separatorChar + "win",
};
for (String path : libraryPaths) {
final File candidate = new File(path + File.separatorChar + libraryName);
if (candidate.exists()) {
System.load(candidate.getAbsolutePath());
break;
}
}
}
private synchronized static void init() {
if (initialiazed.get()) return;
initialize("JetBrains.JetBrainsNativeAppID");
initialiazed.set(true);
}
/**
* Com initialization should be invoked once per process.
* All invocation should be made from the same thread.
* @param applicationId
*/
native private static void initialize (String applicationId);
native private static void addTaskNative (String location, String args, String description);
native private static void clearNative();
public synchronized static void clear() {
init();
checkThread();
clearNative();
}
public synchronized static void addTask(File location, String args, String description) {
init();
checkThread();
if (!location.exists()) throw new IllegalArgumentException("Task should be a valid path");
addTaskNative(location.getAbsolutePath(), args, description);
}
private static void checkThread() {
Thread t = openerThread.get();
if (t == null || !t.equals(Thread.currentThread()))
throw new RuntimeException("This class has to be used from the same thread");
}
}
@@ -0,0 +1,74 @@
/*
* Copyright 2000-2013 JetBrains s.r.o.
*
* 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.ui.win;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
/**
* @author Denis Fokin
*/
public class SocketControlHelper {
private static final String ACTIVATE_COMMAND = "activate ";
/*
* args[0] - socket of controlled IDE
* args[1] - project path
*/
public static void main(String[] args) {
final int portNumber = Integer.parseInt(args[0]);
final String pathToProject = new File(args[1]).getAbsolutePath();
final InetAddress lba = getLoopbackAddress();
try {
Socket socket = new Socket(lba, portNumber);
socket.setSoTimeout(300);
DataInputStream in = new DataInputStream(socket.getInputStream());
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
try {
out.writeUTF(ACTIVATE_COMMAND + new File(".").getAbsolutePath() + "\0" + pathToProject);
out.flush();
String response = in.readUTF();
if (response.equals("ok")) {
System.err.println("Activated.");
}
} finally {
in.close();
out.close();
socket.close();
}
} catch (IOException ignored) {}
System.err.println("Activation failed");
}
private static InetAddress getLoopbackAddress() {
InetAddress returnValue = null;
try {
returnValue = InetAddress.getByName("127.0.0.1");
} catch (UnknownHostException uhe) {
uhe.printStackTrace();
}
return returnValue;
}
}
@@ -0,0 +1,58 @@
/*
* Copyright 2000-2013 JetBrains s.r.o.
*
* 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.ui.win;
import com.intellij.ide.RecentProjectsManagerBase;
import com.intellij.ide.ReopenProjectAction;
import com.intellij.idea.StartupUtil;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.wm.impl.SystemDock;
import java.io.File;
/**
* @author Denis Fokin
*/
public class WinDockDelegate implements SystemDock.Delegate {
private static final Logger LOG = Logger.getInstance("#com.intellij.ui.win.WinDockDelegate");
private static final String javaExe = System.getProperty("java.home") + File.separatorChar + "bin" + File.separatorChar + "javaw.exe";
private static final String argsToExecute = new StringBuilder(" -classpath ").append(PathManager.getJarPathForClass(SocketControlHelper.class)).
append(" com.intellij.ui.win.SocketControlHelper ").append(StartupUtil.getAcquiredPort())
.append(" ").toString();
private static boolean initialized = false;
private static final SystemDock.Delegate instance = new WinDockDelegate();
private WinDockDelegate() {}
public void updateRecentProjectsMenu () {
final AnAction[] recentProjectActions = RecentProjectsManagerBase.getInstance().getRecentProjectsActions(false);
RecentTasks.clear();
for (final AnAction action : recentProjectActions) {
ReopenProjectAction rpa = ((ReopenProjectAction)action);
RecentTasks.addTask(new File(javaExe), argsToExecute + rpa.getProjectPath(), rpa.getProjectName());
}
}
synchronized public static SystemDock.Delegate getInstance() {
if (!initialized) {
initialized = true;
}
return instance;
}
}