jps server module; initial

This commit is contained in:
Eugene Zhuravlev
2011-09-09 15:07:54 +02:00
parent a8ea3cf018
commit a7cf17aaf9
15 changed files with 4683 additions and 0 deletions
@@ -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
@@ -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();
}
@@ -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);
}
}
}
@@ -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);
}
@@ -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.
+1
View File
@@ -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.