mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
jps server module; initial
This commit is contained in:
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="library" name="Netty" level="project" />
|
||||
<orderEntry type="library" name="protobuf" level="project" />
|
||||
<orderEntry type="library" name="JPS-incremental" level="project" />
|
||||
<orderEntry type="module" module-name="annotations" />
|
||||
</component>
|
||||
</module>
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
protoc -I=. --java_out=../src *.proto
|
||||
@@ -0,0 +1,99 @@
|
||||
package org.jetbrains.jpsservice;
|
||||
|
||||
option java_package = "org.jetbrains.jpsservice";
|
||||
option optimize_for = LITE_RUNTIME;
|
||||
|
||||
message Message {
|
||||
|
||||
message UUID {
|
||||
required sint64 most_sig_bits = 1;
|
||||
required sint64 least_sig_bits = 2;
|
||||
}
|
||||
|
||||
enum Type {
|
||||
REQUEST = 1;
|
||||
RESPONSE = 2;
|
||||
FAILURE = 3;
|
||||
}
|
||||
|
||||
message Failure {
|
||||
optional int32 error_code = 1;
|
||||
optional string description = 2;
|
||||
optional string stacktrace = 3;
|
||||
}
|
||||
|
||||
message Request {
|
||||
enum Type {
|
||||
COMPILE_REQUEST = 1;
|
||||
SHUTDOWN_COMMAND = 2;
|
||||
}
|
||||
|
||||
message CompilationRequest {
|
||||
enum Type {
|
||||
REBUILD = 1;
|
||||
MAKE = 2;
|
||||
CLEAN = 3;
|
||||
CANCEL = 4;
|
||||
}
|
||||
required Type command_type = 1;
|
||||
optional string project_id = 2;
|
||||
repeated string module_name = 4;
|
||||
}
|
||||
|
||||
message ShutdownCommand {
|
||||
enum ShutdownPolicy {
|
||||
CANCEL_RUNNING_BUILDS = 1;
|
||||
WAIT_RUNNING_BUILDS = 2;
|
||||
}
|
||||
required ShutdownPolicy shutdownPolicy = 1;
|
||||
}
|
||||
|
||||
required Type request_type = 1;
|
||||
optional CompilationRequest compile_request = 2;
|
||||
optional ShutdownCommand shutdown_command = 3;
|
||||
}
|
||||
|
||||
message Response {
|
||||
enum Type {
|
||||
COMMAND_RESPONSE = 1;
|
||||
COMPILE_MESSAGE = 2;
|
||||
}
|
||||
|
||||
message CommandResponse {
|
||||
enum Type {
|
||||
COMMAND_ACCEPTED = 1;
|
||||
COMMAND_REJECTED = 2;
|
||||
BUILD_COMPLETED = 3;
|
||||
BUILD_CANCELED = 4;
|
||||
}
|
||||
required Type command_type = 1;
|
||||
optional string description = 2;
|
||||
}
|
||||
|
||||
message CompileMessage {
|
||||
enum Kind {
|
||||
ERROR = 1;
|
||||
WARNING = 2;
|
||||
INFO = 3;
|
||||
PROGRESS = 4;
|
||||
}
|
||||
required Kind kind = 1;
|
||||
optional string text = 2;
|
||||
optional string source_file_path = 3;
|
||||
optional uint32 line = 4;
|
||||
optional uint32 column = 5;
|
||||
}
|
||||
|
||||
required Type response_type = 1;
|
||||
optional CommandResponse command_response = 2;
|
||||
optional CompileMessage compile_message = 3;
|
||||
}
|
||||
|
||||
required UUID session_id = 1;
|
||||
required Type message_type = 2;
|
||||
optional Request request = 3;
|
||||
optional Response response = 4;
|
||||
optional Failure failure = 5;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,229 @@
|
||||
package org.jetbrains.jpsservice;
|
||||
|
||||
import org.jboss.netty.bootstrap.ClientBootstrap;
|
||||
import org.jboss.netty.channel.*;
|
||||
import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;
|
||||
import org.jboss.netty.handler.codec.protobuf.ProtobufDecoder;
|
||||
import org.jboss.netty.handler.codec.protobuf.ProtobufEncoder;
|
||||
import org.jboss.netty.handler.codec.protobuf.ProtobufVarint32FrameDecoder;
|
||||
import org.jboss.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jpsservice.impl.JpsClientMessageHandler;
|
||||
import org.jetbrains.jpsservice.impl.ProtoUtil;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
/**
|
||||
* @author Eugene Zhuravlev
|
||||
* Date: 8/11/11
|
||||
*/
|
||||
public class Client {
|
||||
private static enum State {
|
||||
DISCONNECTED, CONNECTING, CONNECTED, DISCONNECTING
|
||||
}
|
||||
private final AtomicReference<State> myState = new AtomicReference<State>(State.DISCONNECTED);
|
||||
|
||||
private final ChannelPipelineFactory myPipelineFactory;
|
||||
private final ChannelFactory myChannelFactory;
|
||||
private ChannelFuture myConnectFuture;
|
||||
private final ConcurrentHashMap<UUID, RequestFuture> myHandlers = new ConcurrentHashMap<UUID, RequestFuture>();
|
||||
|
||||
public Client() {
|
||||
myChannelFactory = new NioClientSocketChannelFactory(Executors.newCachedThreadPool(), Executors.newCachedThreadPool(), 1);
|
||||
|
||||
myPipelineFactory = new ChannelPipelineFactory() {
|
||||
public ChannelPipeline getPipeline() throws Exception {
|
||||
return Channels.pipeline(
|
||||
new ProtobufVarint32FrameDecoder(),
|
||||
new ProtobufDecoder(JpsRemoteProto.Message.getDefaultInstance()),
|
||||
new ProtobufVarint32LengthFieldPrepender(),
|
||||
new ProtobufEncoder(),
|
||||
new JpsClientMessageHandler() {
|
||||
|
||||
protected JpsServerResponseHandler getHandler(UUID sessionId) {
|
||||
final RequestFuture future = myHandlers.get(sessionId);
|
||||
return future != null? future.myHandler : null;
|
||||
}
|
||||
|
||||
protected void terminateSession(UUID sessionId) {
|
||||
final RequestFuture future = myHandlers.remove(sessionId);
|
||||
if (future != null) {
|
||||
final JpsServerResponseHandler handler = future.myHandler;
|
||||
try {
|
||||
if (handler != null) {
|
||||
try {
|
||||
handler.sessionTerminated();
|
||||
}
|
||||
catch (Throwable ignored) {
|
||||
ignored.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
future.setDone();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
|
||||
try {
|
||||
super.channelClosed(ctx, e);
|
||||
}
|
||||
finally {
|
||||
for (UUID uuid : new ArrayList<UUID>(myHandlers.keySet())) {
|
||||
terminateSession(uuid);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public Future sendCompileRequest(String projectId, List<String> modules, boolean rebuild, JpsServerResponseHandler handler) throws Throwable {
|
||||
if (myState.get() != State.CONNECTED) {
|
||||
return null;
|
||||
}
|
||||
return sendRequest(
|
||||
rebuild? ProtoUtil.createRebuildRequest(projectId, modules) : ProtoUtil.createMakeRequest(projectId, modules),
|
||||
handler
|
||||
);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Future sendShutdownRequest() throws Throwable {
|
||||
if (myState.get() != State.CONNECTED) {
|
||||
return null;
|
||||
}
|
||||
return sendRequest(ProtoUtil.createShutdownRequest(true), null);
|
||||
}
|
||||
|
||||
private Future sendRequest(JpsRemoteProto.Message.Request request, @Nullable JpsServerResponseHandler handler) {
|
||||
final UUID sessionUUID = UUID.randomUUID();
|
||||
final RequestFuture requestFuture = new RequestFuture(handler);
|
||||
myHandlers.put(sessionUUID, requestFuture);
|
||||
boolean success = false;
|
||||
try {
|
||||
final ChannelFuture future = Channels.write(myConnectFuture.getChannel(), ProtoUtil.toMessage(sessionUUID, request));
|
||||
future.awaitUninterruptibly();
|
||||
success = future.isSuccess();
|
||||
return success? requestFuture : null;
|
||||
}
|
||||
finally {
|
||||
if (!success) {
|
||||
requestFuture.setDone();
|
||||
myHandlers.remove(sessionUUID);
|
||||
handler.sessionTerminated();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean connect(final String host, final int port) throws Throwable {
|
||||
if (myState.compareAndSet(State.DISCONNECTED, State.CONNECTING)) {
|
||||
boolean success = false;
|
||||
|
||||
try {
|
||||
final ClientBootstrap bootstrap = new ClientBootstrap(myChannelFactory);
|
||||
bootstrap.setPipelineFactory(myPipelineFactory);
|
||||
bootstrap.setOption("tcpNoDelay", true);
|
||||
bootstrap.setOption("keepAlive", true);
|
||||
final ChannelFuture future = bootstrap.connect(new InetSocketAddress(host, port));
|
||||
future.awaitUninterruptibly();
|
||||
|
||||
success = future.isSuccess();
|
||||
|
||||
if (success) {
|
||||
myConnectFuture = future;
|
||||
}
|
||||
else {
|
||||
final Throwable reason = future.getCause();
|
||||
if (reason != null) {
|
||||
throw reason;
|
||||
}
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
finally {
|
||||
myState.compareAndSet(State.CONNECTING, success? State.CONNECTED : State.DISCONNECTED);
|
||||
}
|
||||
}
|
||||
// already connected
|
||||
return false;
|
||||
}
|
||||
|
||||
public void disconnect() {
|
||||
if (myState.compareAndSet(State.CONNECTED, State.DISCONNECTING)) {
|
||||
try {
|
||||
final ChannelFuture future = myConnectFuture;
|
||||
if (future != null) {
|
||||
try {
|
||||
final ChannelFuture closeFuture = future.getChannel().close();
|
||||
closeFuture.awaitUninterruptibly();
|
||||
}
|
||||
finally {
|
||||
myChannelFactory.releaseExternalResources();
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
myConnectFuture = null;
|
||||
myState.compareAndSet(State.DISCONNECTING, State.DISCONNECTED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isConnected() {
|
||||
return myState.get() == State.CONNECTED;
|
||||
}
|
||||
|
||||
private static class RequestFuture implements Future {
|
||||
private final Semaphore mySemaphore = new Semaphore(1);
|
||||
private final AtomicBoolean myDone = new AtomicBoolean(false);
|
||||
private final JpsServerResponseHandler myHandler;
|
||||
|
||||
public RequestFuture(JpsServerResponseHandler handler) {
|
||||
myHandler = handler;
|
||||
mySemaphore.acquireUninterruptibly();
|
||||
}
|
||||
|
||||
public void setDone() {
|
||||
if (!myDone.getAndSet(true)) {
|
||||
mySemaphore.release();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean cancel(boolean mayInterruptIfRunning) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isCancelled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isDone() {
|
||||
return myDone.get();
|
||||
}
|
||||
|
||||
public Object get() throws InterruptedException, ExecutionException {
|
||||
while (!isDone()) {
|
||||
mySemaphore.tryAcquire(100L, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Object get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
|
||||
if (!isDone()) {
|
||||
mySemaphore.tryAcquire(timeout, unit);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
+20
@@ -0,0 +1,20 @@
|
||||
package org.jetbrains.jpsservice;
|
||||
|
||||
/**
|
||||
* @author Eugene Zhuravlev
|
||||
* Date: 8/15/11
|
||||
*/
|
||||
public interface JpsServerResponseHandler {
|
||||
void handleCompileMessage(JpsRemoteProto.Message.Response.CompileMessage compileResponse);
|
||||
|
||||
/**
|
||||
*
|
||||
* @param response
|
||||
* @return false
|
||||
*/
|
||||
void handleCommandResponse(JpsRemoteProto.Message.Response.CommandResponse response);
|
||||
|
||||
void handleFailure(JpsRemoteProto.Message.Failure failure);
|
||||
|
||||
void sessionTerminated();
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
package org.jetbrains.jpsservice;
|
||||
|
||||
/**
|
||||
* @author Eugene Zhuravlev
|
||||
* Date: 8/15/11
|
||||
*/
|
||||
public class JpsServerResponseHandlerAdapter implements JpsServerResponseHandler {
|
||||
|
||||
public void handleCompileMessage(JpsRemoteProto.Message.Response.CompileMessage compileResponse) {
|
||||
}
|
||||
|
||||
public void handleCommandResponse(JpsRemoteProto.Message.Response.CommandResponse response) {
|
||||
}
|
||||
|
||||
public void handleFailure(JpsRemoteProto.Message.Failure failure) {
|
||||
}
|
||||
|
||||
public void sessionTerminated() {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
package org.jetbrains.jpsservice;
|
||||
|
||||
import org.jboss.netty.bootstrap.ServerBootstrap;
|
||||
import org.jboss.netty.channel.*;
|
||||
import org.jboss.netty.channel.group.ChannelGroup;
|
||||
import org.jboss.netty.channel.group.ChannelGroupFuture;
|
||||
import org.jboss.netty.channel.group.DefaultChannelGroup;
|
||||
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
|
||||
import org.jboss.netty.handler.codec.protobuf.ProtobufDecoder;
|
||||
import org.jboss.netty.handler.codec.protobuf.ProtobufEncoder;
|
||||
import org.jboss.netty.handler.codec.protobuf.ProtobufVarint32FrameDecoder;
|
||||
import org.jboss.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender;
|
||||
import org.jetbrains.jpsservice.impl.JpsServerMessageHandler;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
/**
|
||||
* @author Eugene Zhuravlev
|
||||
* Date: 8/11/11
|
||||
*/
|
||||
public class Server {
|
||||
public static final int DEFAULT_SERVER_PORT = 7777;
|
||||
private static final int MAX_SIMULTANEOUS_BUILD_SESSIONS = Math.max(2, Runtime.getRuntime().availableProcessors());
|
||||
|
||||
private final ChannelGroup myAllOpenChannels = new DefaultChannelGroup("jps-server");
|
||||
private final ChannelFactory myChannelFactory;
|
||||
private final ChannelPipelineFactory myPipelineFactory;
|
||||
private final ExecutorService myBuildsExecutor;
|
||||
|
||||
public Server() {
|
||||
final ExecutorService threadPool = Executors.newCachedThreadPool();
|
||||
myBuildsExecutor = Executors.newFixedThreadPool(MAX_SIMULTANEOUS_BUILD_SESSIONS);
|
||||
myChannelFactory = new NioServerSocketChannelFactory(threadPool, threadPool, 1);
|
||||
final ChannelRegistrar channelRegistrar = new ChannelRegistrar();
|
||||
final JpsServerMessageHandler messageHandler = new JpsServerMessageHandler(myBuildsExecutor, this);
|
||||
myPipelineFactory = new ChannelPipelineFactory() {
|
||||
public ChannelPipeline getPipeline() throws Exception {
|
||||
return Channels.pipeline(
|
||||
channelRegistrar,
|
||||
new ProtobufVarint32FrameDecoder(),
|
||||
new ProtobufDecoder(JpsRemoteProto.Message.getDefaultInstance()),
|
||||
new ProtobufVarint32LengthFieldPrepender(),
|
||||
new ProtobufEncoder(),
|
||||
messageHandler
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public void start(int listenPort) {
|
||||
final ServerBootstrap bootstrap = new ServerBootstrap(myChannelFactory);
|
||||
bootstrap.setPipelineFactory(myPipelineFactory);
|
||||
bootstrap.setOption("child.tcpNoDelay", true);
|
||||
bootstrap.setOption("child.keepAlive", true);
|
||||
final Channel serverChannel = bootstrap.bind(new InetSocketAddress(listenPort));
|
||||
myAllOpenChannels.add(serverChannel);
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
try {
|
||||
myBuildsExecutor.shutdownNow();
|
||||
final ChannelGroupFuture closeFuture = myAllOpenChannels.close();
|
||||
closeFuture.awaitUninterruptibly();
|
||||
}
|
||||
finally {
|
||||
myChannelFactory.releaseExternalResources();
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
int port = DEFAULT_SERVER_PORT;
|
||||
if (args.length > 0) {
|
||||
try {
|
||||
port = Integer.parseInt(args[0]);
|
||||
}
|
||||
catch (NumberFormatException e) {
|
||||
System.out.println("Error parsing port, using default ("+port+"): " + e.getMessage());
|
||||
}
|
||||
}
|
||||
final Server server = new Server();
|
||||
server.start(port);
|
||||
Runtime.getRuntime().addShutdownHook(new Thread("Shutdown hook thread") {
|
||||
public void run() {
|
||||
server.stop();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private class ChannelRegistrar extends SimpleChannelUpstreamHandler {
|
||||
public void channelOpen(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
|
||||
myAllOpenChannels.add(e.getChannel());
|
||||
super.channelOpen(ctx, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
package org.jetbrains.jpsservice.impl;
|
||||
|
||||
import org.jboss.netty.channel.ChannelHandlerContext;
|
||||
import org.jboss.netty.channel.ExceptionEvent;
|
||||
import org.jboss.netty.channel.MessageEvent;
|
||||
import org.jboss.netty.channel.SimpleChannelHandler;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jpsservice.JpsRemoteProto;
|
||||
import org.jetbrains.jpsservice.JpsServerResponseHandler;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author Eugene Zhuravlev
|
||||
* Date: 8/11/11
|
||||
*/
|
||||
public abstract class JpsClientMessageHandler extends SimpleChannelHandler{
|
||||
|
||||
public final void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
|
||||
final JpsRemoteProto.Message message = (JpsRemoteProto.Message)e.getMessage();
|
||||
final UUID sessionId = ProtoUtil.fromProtoUUID(message.getSessionId());
|
||||
final JpsRemoteProto.Message.Type messageType = message.getMessageType();
|
||||
|
||||
final JpsServerResponseHandler handler = getHandler(sessionId);
|
||||
if (handler == null) {
|
||||
return; // discard message
|
||||
}
|
||||
|
||||
boolean terminateSession = false;
|
||||
|
||||
try {
|
||||
if (messageType == JpsRemoteProto.Message.Type.FAILURE) {
|
||||
terminateSession = true;
|
||||
handler.handleFailure(message.getFailure());
|
||||
}
|
||||
else if (messageType == JpsRemoteProto.Message.Type.RESPONSE) {
|
||||
final JpsRemoteProto.Message.Response response = message.getResponse();
|
||||
final JpsRemoteProto.Message.Response.Type responseType = response.getResponseType();
|
||||
if (responseType == JpsRemoteProto.Message.Response.Type.COMMAND_RESPONSE) {
|
||||
final JpsRemoteProto.Message.Response.CommandResponse commandResponse = response.getCommandResponse();
|
||||
terminateSession = commandResponse.getCommandType() != JpsRemoteProto.Message.Response.CommandResponse.Type.COMMAND_ACCEPTED;
|
||||
handler.handleCommandResponse(commandResponse);
|
||||
}
|
||||
else if (responseType == JpsRemoteProto.Message.Response.Type.COMPILE_MESSAGE) {
|
||||
handler.handleCompileMessage(response.getCompileMessage());
|
||||
}
|
||||
else {
|
||||
throw new Exception("Unknown response: " + response);
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw new Exception("Unknown message received: " + message);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
if (terminateSession) {
|
||||
terminateSession(sessionId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
|
||||
super.exceptionCaught(ctx, e);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected abstract JpsServerResponseHandler getHandler(UUID sessionId);
|
||||
|
||||
protected abstract void terminateSession(UUID sessionId);
|
||||
}
|
||||
+236
@@ -0,0 +1,236 @@
|
||||
package org.jetbrains.jpsservice.impl;
|
||||
|
||||
import org.codehaus.gant.GantBinding;
|
||||
import org.jboss.netty.channel.*;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.ether.ProjectWrapper;
|
||||
import org.jetbrains.jps.Project;
|
||||
import org.jetbrains.jps.listeners.BuildInfoPrinter;
|
||||
import org.jetbrains.jpsservice.JpsRemoteProto;
|
||||
import org.jetbrains.jpsservice.Server;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
||||
/**
|
||||
* @author Eugene Zhuravlev
|
||||
* Date: 8/11/11
|
||||
*/
|
||||
public class JpsServerMessageHandler extends SimpleChannelHandler {
|
||||
private ConcurrentHashMap<String, String> myBuildsInProgress = new ConcurrentHashMap<String, String>();
|
||||
private final ExecutorService myBuildsExecutorService;
|
||||
private final Server myServer;
|
||||
|
||||
public JpsServerMessageHandler(ExecutorService buildsExecutorService, Server server) {
|
||||
myBuildsExecutorService = buildsExecutorService;
|
||||
myServer = server;
|
||||
}
|
||||
|
||||
public void messageReceived(final ChannelHandlerContext ctx, MessageEvent e) throws Exception {
|
||||
final JpsRemoteProto.Message message = (JpsRemoteProto.Message)e.getMessage();
|
||||
final UUID sessionId = ProtoUtil.fromProtoUUID(message.getSessionId());
|
||||
|
||||
JpsRemoteProto.Message responseMessage = null;
|
||||
boolean shutdown = false;
|
||||
|
||||
if (message.getMessageType() != JpsRemoteProto.Message.Type.REQUEST) {
|
||||
responseMessage = ProtoUtil.toMessage(sessionId, ProtoUtil.createFailure("Cannot handle message " + message.toString()));
|
||||
}
|
||||
else if (!message.hasRequest()) {
|
||||
responseMessage = ProtoUtil.toMessage(sessionId, ProtoUtil.createFailure("No request in message: " + message.toString()));
|
||||
}
|
||||
else {
|
||||
final JpsRemoteProto.Message.Request request = message.getRequest();
|
||||
final JpsRemoteProto.Message.Request.Type requestType = request.getRequestType();
|
||||
if (requestType == JpsRemoteProto.Message.Request.Type.COMPILE_REQUEST) {
|
||||
final JpsRemoteProto.Message.Response response = startBuild(sessionId, ctx, request.getCompileRequest());
|
||||
if (response != null) {
|
||||
responseMessage = ProtoUtil.toMessage(sessionId, response);
|
||||
}
|
||||
}
|
||||
else if (requestType == JpsRemoteProto.Message.Request.Type.SHUTDOWN_COMMAND){
|
||||
shutdown = true;
|
||||
responseMessage = ProtoUtil.toMessage(sessionId, ProtoUtil.createCommandAcceptedResponse(null));
|
||||
}
|
||||
else {
|
||||
responseMessage = ProtoUtil.toMessage(sessionId, ProtoUtil.createFailure("Unknown request: " + message));
|
||||
}
|
||||
}
|
||||
if (responseMessage != null) {
|
||||
final ChannelFuture future = Channels.write(ctx.getChannel(), responseMessage);
|
||||
if (shutdown) {
|
||||
future.addListener(new ChannelFutureListener() {
|
||||
public void operationComplete(ChannelFuture future) throws Exception {
|
||||
// todo pay attention to policy
|
||||
myBuildsExecutorService.submit(new Runnable() {
|
||||
public void run() {
|
||||
myServer.stop();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private JpsRemoteProto.Message.Response startBuild(UUID sessionId, final ChannelHandlerContext channelContext, JpsRemoteProto.Message.Request.CompilationRequest compileRequest) {
|
||||
if (!compileRequest.hasProjectId()) {
|
||||
return ProtoUtil.createCommandRejectedResponse("No project specified");
|
||||
}
|
||||
|
||||
final String projectId = compileRequest.getProjectId();
|
||||
final JpsRemoteProto.Message.Request.CompilationRequest.Type commandType = compileRequest.getCommandType();
|
||||
|
||||
if (commandType == JpsRemoteProto.Message.Request.CompilationRequest.Type.CLEAN ||
|
||||
commandType == JpsRemoteProto.Message.Request.CompilationRequest.Type.MAKE ||
|
||||
commandType == JpsRemoteProto.Message.Request.CompilationRequest.Type.REBUILD) {
|
||||
if (myBuildsInProgress.putIfAbsent(projectId, "") != null) {
|
||||
return ProtoUtil.createCommandRejectedResponse("Project is being compiled already");
|
||||
}
|
||||
myBuildsExecutorService.submit(new CompilationTask(sessionId, channelContext, commandType, projectId, compileRequest.getModuleNameList()));
|
||||
return null; // the rest will be handled asynchronously
|
||||
}
|
||||
|
||||
if (commandType == JpsRemoteProto.Message.Request.CompilationRequest.Type.CANCEL) {
|
||||
final String projectInProgress = myBuildsInProgress.remove(projectId);
|
||||
if (projectInProgress == null) {
|
||||
return ProtoUtil.createCommandRejectedResponse("Build for requested project is not running");
|
||||
}
|
||||
// todo: perform cancel
|
||||
return ProtoUtil.createBuildCanceledResponse(projectId);
|
||||
}
|
||||
|
||||
return ProtoUtil.createCommandRejectedResponse("Unsupported command: '" + commandType + "'");
|
||||
}
|
||||
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
|
||||
super.exceptionCaught(ctx, e);
|
||||
}
|
||||
|
||||
private class CompilationTask implements Runnable {
|
||||
|
||||
private final UUID mySessionId;
|
||||
private final ChannelHandlerContext myChannelContext;
|
||||
private final JpsRemoteProto.Message.Request.CompilationRequest.Type myCompileType;
|
||||
private final String myProjectPath;
|
||||
private final List<String> myModules;
|
||||
|
||||
public CompilationTask(UUID sessionId, ChannelHandlerContext channelContext, JpsRemoteProto.Message.Request.CompilationRequest.Type compileType, String projectId, List<String> modules) {
|
||||
mySessionId = sessionId;
|
||||
myChannelContext = channelContext;
|
||||
myCompileType = compileType;
|
||||
myProjectPath = projectId;
|
||||
myModules = modules;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
Channels.write(myChannelContext.getChannel(), ProtoUtil.toMessage(mySessionId, ProtoUtil.createCommandAcceptedResponse("build started")));
|
||||
Throwable error = null;
|
||||
try {
|
||||
final int size = myModules.size();
|
||||
|
||||
final Map<String,String> pathVars = new HashMap<String, String>(); // todo
|
||||
pathVars.put("MAVEN_REPOSITORY", "C:/Users/jeka/.m2/repository");
|
||||
|
||||
final ProjectWrapper proj = ProjectWrapper.load(new GantBinding(), myProjectPath, getStartupScript(), pathVars, myCompileType == JpsRemoteProto.Message.Request.CompilationRequest.Type.MAKE);
|
||||
|
||||
proj.getProject().getBuilder().setBuildInfoPrinter(new BuildInfoPrinter() {
|
||||
public Object printProgressMessage(Project project, String message) {
|
||||
Channels.write(myChannelContext.getChannel(), ProtoUtil.toMessage(mySessionId, ProtoUtil.createCompileProgressMessageResponse(message)));
|
||||
return null;
|
||||
}
|
||||
|
||||
public Object printCompilationErrors(Project project, String compilerName, String messages) {
|
||||
Channels.write(myChannelContext.getChannel(), ProtoUtil.toMessage(mySessionId, ProtoUtil.createCompileErrorMessageResponse(messages, null, -1, -1)));
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
switch (myCompileType) {
|
||||
case REBUILD:
|
||||
proj.rebuild();
|
||||
break;
|
||||
case MAKE:
|
||||
proj.makeModules(null, createMakeFlags());
|
||||
break;
|
||||
case CLEAN:
|
||||
proj.clean();
|
||||
break;
|
||||
}
|
||||
proj.save();
|
||||
}
|
||||
catch (Throwable e) {
|
||||
error = e;
|
||||
}
|
||||
finally {
|
||||
final JpsRemoteProto.Message lastMessage = error != null?
|
||||
ProtoUtil.toMessage(mySessionId, ProtoUtil.createFailure("build failed: ", error)) :
|
||||
ProtoUtil.toMessage(mySessionId, ProtoUtil.createBuildCompletedResponse("build completed"));
|
||||
|
||||
Channels.write(myChannelContext.getChannel(), lastMessage).addListener(new ChannelFutureListener() {
|
||||
public void operationComplete(ChannelFuture future) throws Exception {
|
||||
myBuildsInProgress.remove(myProjectPath);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private String getStartupScript() {
|
||||
return "import org.jetbrains.jps.*\n" +
|
||||
"\n" +
|
||||
//"project.createJavaSdk (\n" +
|
||||
//" \"IDEA jdk\", \n" +
|
||||
//" \"/home/db/develop/jetbrains/jdk1.6.0_22\", \n" +
|
||||
//" { \n" +
|
||||
//" getDelegate ().classpath (\n" +
|
||||
//" \"/home/db/develop/jetbrains/jdk1.6.0_22/jre/lib/plugin.jar\",\n" +
|
||||
//" \"/home/db/develop/jetbrains/jdk1.6.0_22/jre/lib/charsets.jar\",\n" +
|
||||
//" \"/home/db/develop/jetbrains/jdk1.6.0_22/jre/lib/jce.jar\",\n" +
|
||||
//" \"/home/db/develop/jetbrains/jdk1.6.0_22/jre/lib/rt.jar\",\n" +
|
||||
//" \"/home/db/develop/jetbrains/jdk1.6.0_22/jre/lib/management-agent.jar\",\n" +
|
||||
//" \"/home/db/develop/jetbrains/jdk1.6.0_22/jre/lib/resources.jar\",\n" +
|
||||
//" \"/home/db/develop/jetbrains/jdk1.6.0_22/jre/lib/deploy.jar\",\n" +
|
||||
//" \"/home/db/develop/jetbrains/jdk1.6.0_22/jre/lib/jsse.jar\",\n" +
|
||||
//" \"/home/db/develop/jetbrains/jdk1.6.0_22/jre/lib/javaws.jar\",\n" +
|
||||
//" \"/home/db/develop/jetbrains/jdk1.6.0_22/jre/lib/alt-rt.jar\",\n" +
|
||||
//" \"/home/db/develop/jetbrains/jdk1.6.0_22/jre/lib/ext/sunpkcs11.jar\",\n" +
|
||||
//" \"/home/db/develop/jetbrains/jdk1.6.0_22/jre/lib/ext/dnsns.jar\",\n" +
|
||||
//" \"/home/db/develop/jetbrains/jdk1.6.0_22/jre/lib/ext/localedata.jar\",\n" +
|
||||
//" \"/home/db/develop/jetbrains/jdk1.6.0_22/jre/lib/ext/sunjce_provider.jar\",\n" +
|
||||
//" \"/home/db/develop/jetbrains/jdk1.6.0_22/lib/tools.jar\"\n" +
|
||||
//" )\n" +
|
||||
//" }\n" +
|
||||
//")\n" +
|
||||
//"\n" +
|
||||
//"project.projectSdk = project.sdks [\"IDEA jdk\"]\n" +
|
||||
"project.builder.useInProcessJavac = true";
|
||||
}
|
||||
|
||||
private ProjectWrapper.Flags createMakeFlags() {
|
||||
return new ProjectWrapper.Flags() {
|
||||
public boolean tests() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean incremental() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean force() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public PrintStream logStream() {
|
||||
return null; // todo
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
package org.jetbrains.jpsservice.impl;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jpsservice.JpsRemoteProto;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author Eugene Zhuravlev
|
||||
* Date: 8/15/11
|
||||
*/
|
||||
public class ProtoUtil {
|
||||
|
||||
public static JpsRemoteProto.Message.Failure createFailure(final String description) {
|
||||
return createFailure(description, null);
|
||||
}
|
||||
|
||||
public static JpsRemoteProto.Message.Failure createFailure(final String description, @Nullable Throwable reason) {
|
||||
final JpsRemoteProto.Message.Failure.Builder builder = JpsRemoteProto.Message.Failure.newBuilder().setDescription(description);
|
||||
if (reason != null) {
|
||||
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
reason.printStackTrace(new PrintStream(baos));
|
||||
builder.setStacktrace(new String(baos.toByteArray()));
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
public static JpsRemoteProto.Message.Request createMakeRequest(String project, Collection<String> modules) {
|
||||
return createCompileRequest(JpsRemoteProto.Message.Request.CompilationRequest.Type.MAKE, project, modules);
|
||||
}
|
||||
|
||||
public static JpsRemoteProto.Message.Request createRebuildRequest(String project, Collection<String> modules) {
|
||||
return createCompileRequest(JpsRemoteProto.Message.Request.CompilationRequest.Type.REBUILD, project, modules);
|
||||
}
|
||||
|
||||
public static JpsRemoteProto.Message.Request createCleanRequest(String project, Collection<String> modules) {
|
||||
return createCompileRequest(JpsRemoteProto.Message.Request.CompilationRequest.Type.CLEAN, project, modules);
|
||||
}
|
||||
|
||||
public static JpsRemoteProto.Message.Request createCancelRequest(String project) {
|
||||
return createCompileRequest(JpsRemoteProto.Message.Request.CompilationRequest.Type.CANCEL, project, Collections.<String>emptyList());
|
||||
}
|
||||
|
||||
public static JpsRemoteProto.Message.Request createCompileRequest(final JpsRemoteProto.Message.Request.CompilationRequest.Type command, String project, Collection<String> modules) {
|
||||
final JpsRemoteProto.Message.Request.CompilationRequest.Builder builder = JpsRemoteProto.Message.Request.CompilationRequest.newBuilder().setCommandType(command);
|
||||
builder.setProjectId(project);
|
||||
if (modules.size() > 0) {
|
||||
builder.addAllModuleName(modules);
|
||||
}
|
||||
return JpsRemoteProto.Message.Request.newBuilder().setRequestType(JpsRemoteProto.Message.Request.Type.COMPILE_REQUEST).setCompileRequest(builder.build()).build();
|
||||
}
|
||||
|
||||
public static JpsRemoteProto.Message.UUID toProtoUUID(UUID requestId) {
|
||||
return JpsRemoteProto.Message.UUID.newBuilder().setMostSigBits(requestId.getMostSignificantBits()).setLeastSigBits(requestId.getLeastSignificantBits()).build();
|
||||
}
|
||||
|
||||
public static UUID fromProtoUUID(JpsRemoteProto.Message.UUID uuid) {
|
||||
return new UUID(uuid.getMostSigBits(), uuid.getLeastSigBits());
|
||||
}
|
||||
|
||||
public static JpsRemoteProto.Message.Request createShutdownRequest(boolean cancelRunningBuilds) {
|
||||
final JpsRemoteProto.Message.Request.ShutdownCommand.Builder builder = JpsRemoteProto.Message.Request.ShutdownCommand.newBuilder();
|
||||
builder.setShutdownPolicy(
|
||||
cancelRunningBuilds? JpsRemoteProto.Message.Request.ShutdownCommand.ShutdownPolicy.CANCEL_RUNNING_BUILDS : JpsRemoteProto.Message.Request.ShutdownCommand.ShutdownPolicy.WAIT_RUNNING_BUILDS
|
||||
);
|
||||
return JpsRemoteProto.Message.Request.newBuilder().setRequestType(JpsRemoteProto.Message.Request.Type.SHUTDOWN_COMMAND).setShutdownCommand(builder.build()).build();
|
||||
}
|
||||
|
||||
public static JpsRemoteProto.Message.Response createCommandAcceptedResponse(@Nullable String description) {
|
||||
return createCommandResponse(JpsRemoteProto.Message.Response.CommandResponse.Type.COMMAND_ACCEPTED, description);
|
||||
}
|
||||
|
||||
public static JpsRemoteProto.Message.Response createCommandRejectedResponse(@Nullable String description) {
|
||||
return createCommandResponse(JpsRemoteProto.Message.Response.CommandResponse.Type.COMMAND_REJECTED, description);
|
||||
}
|
||||
|
||||
public static JpsRemoteProto.Message.Response createBuildCompletedResponse(@Nullable String description) {
|
||||
return createCommandResponse(JpsRemoteProto.Message.Response.CommandResponse.Type.BUILD_COMPLETED, description);
|
||||
}
|
||||
|
||||
public static JpsRemoteProto.Message.Response createBuildCanceledResponse(@Nullable String description) {
|
||||
return createCommandResponse(JpsRemoteProto.Message.Response.CommandResponse.Type.BUILD_CANCELED, description);
|
||||
}
|
||||
|
||||
public static JpsRemoteProto.Message.Response createCommandResponse(final JpsRemoteProto.Message.Response.CommandResponse.Type type, @Nullable String description) {
|
||||
final JpsRemoteProto.Message.Response.CommandResponse.Builder builder = JpsRemoteProto.Message.Response.CommandResponse.newBuilder().setCommandType(type);
|
||||
if (description != null) {
|
||||
builder.setDescription(description);
|
||||
}
|
||||
return JpsRemoteProto.Message.Response.newBuilder().setResponseType(JpsRemoteProto.Message.Response.Type.COMMAND_RESPONSE).setCommandResponse(builder.build()).build();
|
||||
}
|
||||
|
||||
public static JpsRemoteProto.Message.Response createCompileInfoMessageResponse(String text, String path) {
|
||||
return createCompileMessageResponse(JpsRemoteProto.Message.Response.CompileMessage.Kind.INFO, text, path, -1, -1);
|
||||
}
|
||||
|
||||
public static JpsRemoteProto.Message.Response createCompileProgressMessageResponse(String text) {
|
||||
return createCompileMessageResponse(JpsRemoteProto.Message.Response.CompileMessage.Kind.PROGRESS, text, null, -1, -1);
|
||||
}
|
||||
|
||||
public static JpsRemoteProto.Message.Response createCompileWarningMessageResponse(String text, String path, int line, int column) {
|
||||
return createCompileMessageResponse(JpsRemoteProto.Message.Response.CompileMessage.Kind.WARNING, text, path, line, column);
|
||||
}
|
||||
|
||||
public static JpsRemoteProto.Message.Response createCompileErrorMessageResponse(String text, String path, int line, int column) {
|
||||
return createCompileMessageResponse(JpsRemoteProto.Message.Response.CompileMessage.Kind.ERROR, text, path, line, column);
|
||||
}
|
||||
|
||||
public static JpsRemoteProto.Message.Response createCompileMessageResponse(final JpsRemoteProto.Message.Response.CompileMessage.Kind msgKind, String text, String path, int line, int column) {
|
||||
final JpsRemoteProto.Message.Response.CompileMessage.Builder builder = JpsRemoteProto.Message.Response.CompileMessage.newBuilder().setKind(msgKind);
|
||||
if (text != null) {
|
||||
builder.setText(text);
|
||||
}
|
||||
if (path != null) {
|
||||
builder.setSourceFilePath(path);
|
||||
}
|
||||
if (line >=0) {
|
||||
builder.setLine(line);
|
||||
}
|
||||
if (column >=0) {
|
||||
builder.setColumn(column);
|
||||
}
|
||||
return JpsRemoteProto.Message.Response.newBuilder().setResponseType(JpsRemoteProto.Message.Response.Type.COMPILE_MESSAGE).setCompileMessage(builder.build()).build();
|
||||
}
|
||||
|
||||
public static JpsRemoteProto.Message toMessage(final UUID sessionId, JpsRemoteProto.Message.Response response) {
|
||||
return JpsRemoteProto.Message.newBuilder().setSessionId(toProtoUUID(sessionId)).setMessageType(JpsRemoteProto.Message.Type.RESPONSE).setResponse(response).build();
|
||||
}
|
||||
|
||||
public static JpsRemoteProto.Message toMessage(final UUID sessionId, JpsRemoteProto.Message.Request request) {
|
||||
return JpsRemoteProto.Message.newBuilder().setSessionId(toProtoUUID(sessionId)).setMessageType(JpsRemoteProto.Message.Type.REQUEST).setRequest(request).build();
|
||||
}
|
||||
|
||||
public static JpsRemoteProto.Message toMessage(final UUID sessionId, JpsRemoteProto.Message.Failure failure) {
|
||||
return JpsRemoteProto.Message.newBuilder().setSessionId(toProtoUUID(sessionId)).setMessageType(JpsRemoteProto.Message.Type.FAILURE).setFailure(failure).build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Copyright 2000-2011 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.compiler;
|
||||
|
||||
import com.intellij.execution.ExecutionException;
|
||||
import com.intellij.execution.configurations.GeneralCommandLine;
|
||||
import com.intellij.execution.process.OSProcessHandler;
|
||||
import com.intellij.execution.process.ProcessHandler;
|
||||
import com.intellij.openapi.application.PathManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.projectRoots.JavaSdkType;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.openapi.projectRoots.impl.JavaAwareProjectJdkTableImpl;
|
||||
import com.intellij.openapi.util.ShutDownTracker;
|
||||
import org.jetbrains.jps.Jps;
|
||||
import org.jetbrains.jpsservice.Client;
|
||||
import org.jetbrains.jpsservice.Server;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* @author Eugene Zhuravlev
|
||||
* Date: 9/6/11
|
||||
*/
|
||||
public class JpsServerManager {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.compiler.JpsServerManager");
|
||||
|
||||
public static void main(String[] args) {
|
||||
ensureServerStarted();
|
||||
}
|
||||
|
||||
private static boolean ensureServerStarted() {
|
||||
return Holder.ourServerProcess != null;
|
||||
}
|
||||
|
||||
private static class Holder {
|
||||
private static Client ourServerClient;
|
||||
private static ProcessHandler ourServerProcess;
|
||||
|
||||
static {
|
||||
try {
|
||||
final int port = Server.DEFAULT_SERVER_PORT;
|
||||
final Process process = launchServer(port);
|
||||
final OSProcessHandler processHandler = new OSProcessHandler(process, null);
|
||||
processHandler.startNotify();
|
||||
final Client client = new Client();
|
||||
client.connect("localhost", port);
|
||||
|
||||
ourServerProcess = processHandler;
|
||||
ourServerClient = client;
|
||||
|
||||
ShutDownTracker.getInstance().registerShutdownTask(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
shutdownServer(client, processHandler);
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (Throwable e) {
|
||||
LOG.error(e); // todo
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void shutdownServer(Client client, OSProcessHandler processHandler) {
|
||||
try {
|
||||
final Future future = client.sendShutdownRequest();
|
||||
if (future != null) {
|
||||
future.get(500, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
}
|
||||
catch (Throwable ignored) {
|
||||
LOG.info(ignored);
|
||||
}
|
||||
finally {
|
||||
processHandler.destroyProcess();
|
||||
}
|
||||
}
|
||||
|
||||
private static Process launchServer(int port) throws ExecutionException {
|
||||
final Sdk projectJdk = JavaAwareProjectJdkTableImpl.getInstanceEx().getInternalJdk();
|
||||
final GeneralCommandLine cmdLine = new GeneralCommandLine();
|
||||
cmdLine.setExePath(((JavaSdkType)projectJdk.getSdkType()).getVMExecutablePath(projectJdk));
|
||||
|
||||
final StringBuilder cp = new StringBuilder();
|
||||
cp.append(getResourcePath(Server.class));
|
||||
cp.append(File.pathSeparator).append(getResourcePath(com.google.protobuf.Message.class));
|
||||
cp.append(File.pathSeparator).append(getResourcePath(org.jboss.netty.bootstrap.Bootstrap.class));
|
||||
final String jpsJar = getResourcePath(Jps.class);
|
||||
final File parentFile = new File(jpsJar).getParentFile();
|
||||
final File[] files = parentFile.listFiles();
|
||||
if (files != null) {
|
||||
for (File file : files) {
|
||||
final String name = file.getName();
|
||||
final boolean shouldAdd =
|
||||
name.endsWith("jar") &&
|
||||
(name.startsWith("ant") ||
|
||||
name.startsWith("jps") ||
|
||||
name.startsWith("asm") ||
|
||||
name.startsWith("gant")||
|
||||
name.startsWith("groovy") ||
|
||||
name.startsWith("javac2")
|
||||
);
|
||||
if (shouldAdd) {
|
||||
cp.append(File.pathSeparator).append(file.getPath());
|
||||
}
|
||||
}
|
||||
}
|
||||
cmdLine.addParameter("-classpath");
|
||||
cmdLine.addParameter(cp.toString());
|
||||
|
||||
cmdLine.addParameter("org.jetbrains.jpsservice.Server");
|
||||
cmdLine.addParameter(Integer.toString(port));
|
||||
return cmdLine.createProcess();
|
||||
}
|
||||
|
||||
private static String getResourcePath(Class aClass) {
|
||||
return PathManager.getResourceRoot(aClass, "/" + aClass.getName().replace('.', '/') + ".class");
|
||||
}
|
||||
|
||||
}
|
||||
Binary file not shown.
@@ -42,3 +42,4 @@ xmlrpc-2.0.jar
|
||||
xpp3-1.1.4-min.jar
|
||||
xstream.jar
|
||||
swingx-core-1.6.2.jar
|
||||
netty-3.2.5.Final.jar
|
||||
|
||||
Binary file not shown.
Reference in New Issue
Block a user