ProjectSetRequestHandler as REST API

This commit is contained in:
Vladimir Krivosheev
2015-02-03 10:12:08 +01:00
parent c7c47fa57f
commit e99bd4dd17
7 changed files with 114 additions and 47 deletions
+1 -1
View File
@@ -2,7 +2,7 @@ var gulp = require('gulp')
var apidoc = require('gulp-apidoc')
var path = require('path')
var sources = path.normalize("../../platform/platform-impl/src/org/jetbrains/ide")
var sources = path.normalize("../../platform/platform-impl/src")
gulp.task('apidoc', function () {
apidoc.exec({src: sources, dest: (process.env.HOME || process.env.HOMEPATH || process.env.USERPROFILE) + "/idea-rest-api"})
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* Copyright 2000-2015 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.
@@ -15,13 +15,14 @@
*/
package com.intellij.platform;
import com.google.gson.*;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Pair;
import com.intellij.projectImport.ProjectSetProcessor;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
import org.intellij.lang.annotations.Language;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -31,29 +32,17 @@ import java.util.*;
* @author Dmitry Avdeev
*/
public class ProjectSetReader {
public void readDescriptor(@Language("JSON") @NotNull String descriptor, @Nullable ProjectSetProcessor.Context context) {
ProjectSetProcessor[] extensions = ProjectSetProcessor.EXTENSION_POINT_NAME.getExtensions();
public void readDescriptor(@NotNull JsonObject descriptor, @Nullable ProjectSetProcessor.Context context) {
Map<String, ProjectSetProcessor> processors = new HashMap<String, ProjectSetProcessor>();
for (ProjectSetProcessor extension : extensions) {
for (ProjectSetProcessor extension : ProjectSetProcessor.EXTENSION_POINT_NAME.getExtensions()) {
processors.put(extension.getId(), extension);
}
JsonElement parse;
try {
parse = new JsonParser().parse(descriptor);
}
catch (JsonSyntaxException e) {
LOG.error(e);
return;
}
Iterator<Map.Entry<String, JsonElement>> iterator = parse.getAsJsonObject().entrySet().iterator();
if (context == null) {
context = new ProjectSetProcessor.Context();
}
context.directoryName = "";
runProcessor(processors, context, iterator);
runProcessor(processors, context, descriptor.entrySet().iterator());
}
private static void runProcessor(final Map<String, ProjectSetProcessor> processors, final ProjectSetProcessor.Context context, final Iterator<Map.Entry<String, JsonElement>> iterator) {
@@ -0,0 +1,35 @@
###
@apiDefine OpenProjectSetRequestExample
@apiExample {json} Request-Example:
{
"vcs": {
"git": {"url": "https://github.com/JetBrains/idea-templates.git"}
},
"project": "/spring/SpringApp"
}
###
###
@apiDefine OpenProjectSetRequestExampleMulti
@apiExample {json} Request-Example (multi-repository):
{
"vcs": {
"git": [
{
"url": "git@git.labs.intellij.net:idea/community"
},
{
"url": "git://git.jetbrains.org/idea/android.git",
"targetDir": "android"
},
{
"url": "git://git.jetbrains.org/idea/adt-tools-base.git",
"targetDir": "android/tools-base"
}
]
},
"project": ""
}
###
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* Copyright 2000-2015 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.
@@ -15,42 +15,61 @@
*/
package com.intellij.platform;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.intellij.openapi.application.ApplicationManager;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.HttpMethod;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.handler.codec.http.QueryStringDecoder;
import org.intellij.lang.annotations.Language;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.ide.HttpRequestHandler;
import org.jetbrains.io.Responses;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.ide.RestService;
import java.io.IOException;
import java.nio.charset.Charset;
/**
* @author Dmitry Avdeev
*
* @api {post} /openProjectSet Open project
* @apiName openProjectSet
* @apiGroup Platform
* @apiDescription Checkout a repository from source control and then open an IDEA project from it.
*
* @apiParam (properties) {Object} vcs The map of the VCS.
* @apiParam (properties) {String} project The path to project to be opened.
*
* @apiUse OpenProjectSetRequestExample
* @apiUse OpenProjectSetRequestExampleMulti
*/
public class ProjectSetRequestHandler extends HttpRequestHandler {
public class ProjectSetRequestHandler extends RestService {
@Override
public boolean isSupported(@NotNull FullHttpRequest request) {
return request.method() == HttpMethod.POST && "/openProjectSet".equals(request.uri());
protected boolean isMethodSupported(@NotNull HttpMethod method) {
return method == HttpMethod.POST;
}
@NotNull
@Override
protected String getServiceName() {
return "openProjectSet";
}
@Override
public boolean process(@NotNull QueryStringDecoder urlDecoder, @NotNull FullHttpRequest request, @NotNull ChannelHandlerContext context)
throws IOException {
protected boolean isPrefixlessAllowed() {
return true;
}
@Language("JSON") final String desc = request.content().toString(Charset.defaultCharset());
@Nullable
@Override
public String execute(@NotNull QueryStringDecoder urlDecoder, @NotNull FullHttpRequest request, @NotNull ChannelHandlerContext context) throws IOException {
final JsonObject descriptor = new JsonParser().parse(createJsonReader(request)).getAsJsonObject();
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
new ProjectSetReader().readDescriptor(desc, null);
new ProjectSetReader().readDescriptor(descriptor, null);
}
});
Responses.sendStatus(HttpResponseStatus.OK, context.channel(), request);
return true;
sendOk(request, context);
return null;
}
}
@@ -51,8 +51,13 @@ public abstract class RestService extends HttpRequestHandler {
return false;
}
String prefix = "rest";
String uri = request.uri();
if (isPrefixlessAllowed() && checkPrefix(uri, getServiceName())) {
return true;
}
String prefix = "rest";
String serviceName = getServiceName();
int minLength = 1 + prefix.length() + 1 + serviceName.length();
if (uri.length() >= minLength &&
@@ -70,6 +75,13 @@ public abstract class RestService extends HttpRequestHandler {
return false;
}
/**
* Service url must be "/rest/$serviceName", but to preserve backward compatibility, prefixless path could be also supported
*/
protected boolean isPrefixlessAllowed() {
return false;
}
@NotNull
/**
* Use human-readable name or UUID if it is an internal service.
@@ -25,5 +25,6 @@
<orderEntry type="library" name="Netty" level="project" />
<orderEntry type="library" name="http-client" level="project" />
<orderEntry type="module" module-name="jps-model-impl" scope="TEST" />
<orderEntry type="library" name="gson" level="project" />
</component>
</module>
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* Copyright 2000-2015 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.
@@ -15,14 +15,16 @@
*/
package com.intellij.platform;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.project.ex.ProjectManagerEx;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vcs.VcsCheckoutProcessor;
import com.intellij.openapi.vfs.CharsetToolkit;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.projectImport.ProjectSetProcessor;
@@ -30,11 +32,13 @@ import com.intellij.testFramework.LightPlatformTestCase;
import com.intellij.testFramework.PlatformTestCase;
import com.intellij.testFramework.PlatformTestUtil;
import com.intellij.util.containers.ContainerUtil;
import org.intellij.lang.annotations.Language;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;
/**
@@ -52,8 +56,6 @@ public class ProjectSetTest extends LightPlatformTestCase {
}
public void testProjectSetReader() throws IOException {
ProjectSetReader reader = new ProjectSetReader();
final Ref<List<Pair<String, String>>> ref = Ref.create();
PlatformTestUtil.registerExtension(ProjectSetProcessor.EXTENSION_POINT_NAME, new ProjectSetProcessor() {
@Override
@@ -67,10 +69,9 @@ public class ProjectSetTest extends LightPlatformTestCase {
}
}, myTestRootDisposable);
@Language("JSON") String descriptor = FileUtil.loadFile(new File(getTestDataPath() + "descriptor.json"));
ProjectSetProcessor.Context context = new ProjectSetProcessor.Context();
context.directory = getSourceRoot();
reader.readDescriptor(descriptor, context);
readDescriptor(new File(getTestDataPath() + "descriptor.json"), context);
List<Pair<String, String>> entries = ref.get();
assertEquals(2, entries.size());
@@ -96,11 +97,10 @@ public class ProjectSetTest extends LightPlatformTestCase {
}
}, myTestRootDisposable);
@Language("JSON") String descriptor = FileUtil.loadFile(new File(getTestDataPath() + "vcs.json"));
ProjectSetProcessor.Context context = new ProjectSetProcessor.Context();
context.directoryName = "newDir";
context.directory = getSourceRoot();
new ProjectSetReader().readDescriptor(descriptor, context);
readDescriptor(new File(getTestDataPath() + "vcs.json"), context);
Collections.sort(pairs, new Comparator<Pair<String, String>>() {
@Override
public int compare(@NotNull Pair<String, String> o1, @NotNull Pair<String, String> o2) {
@@ -112,10 +112,9 @@ public class ProjectSetTest extends LightPlatformTestCase {
}
public void testOpenProject() throws IOException {
@Language("JSON") String descriptor = FileUtil.loadFile(new File(getTestDataPath() + "project.json"));
ProjectSetProcessor.Context context = new ProjectSetProcessor.Context();
context.directory = VfsUtil.findFileByIoFile(new File(getTestDataPath()), true);
new ProjectSetReader().readDescriptor(descriptor, context);
readDescriptor(new File(getTestDataPath() + "project.json"), context);
Project[] projects = ProjectManager.getInstance().getOpenProjects();
Project project = ContainerUtil.find(projects, new Condition<Project>() {
@Override
@@ -131,4 +130,16 @@ public class ProjectSetTest extends LightPlatformTestCase {
public void setUp() throws Exception {
super.setUp();
}
private static void readDescriptor(@NotNull File descriptor, @Nullable ProjectSetProcessor.Context context) throws IOException {
InputStreamReader input = new InputStreamReader(new FileInputStream(descriptor), CharsetToolkit.UTF8_CHARSET);
JsonElement parse;
try {
parse = new JsonParser().parse(input);
}
finally {
input.close();
}
new ProjectSetReader().readDescriptor(parse.getAsJsonObject(), context);
}
}