From e99bd4dd1773cde85d5847bdca3a35105e9740d9 Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Tue, 3 Feb 2015 10:09:41 +0100 Subject: [PATCH] ProjectSetRequestHandler as REST API --- build/restApiDocGenerator/gulpfile.js | 2 +- .../intellij/platform/ProjectSetReader.java | 25 +++------ .../platform/ProjectSetRequestHandler.coffee | 35 +++++++++++++ .../platform/ProjectSetRequestHandler.java | 51 +++++++++++++------ .../src/org/jetbrains/ide/RestService.java | 14 ++++- platform/platform-tests/platform-tests.iml | 1 + .../com/intellij/platform/ProjectSetTest.java | 33 ++++++++---- 7 files changed, 114 insertions(+), 47 deletions(-) create mode 100644 platform/platform-impl/src/com/intellij/platform/ProjectSetRequestHandler.coffee diff --git a/build/restApiDocGenerator/gulpfile.js b/build/restApiDocGenerator/gulpfile.js index e583e04c7c23..49e284850ec1 100644 --- a/build/restApiDocGenerator/gulpfile.js +++ b/build/restApiDocGenerator/gulpfile.js @@ -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"}) diff --git a/platform/platform-impl/src/com/intellij/platform/ProjectSetReader.java b/platform/platform-impl/src/com/intellij/platform/ProjectSetReader.java index 25139a1db98b..fbee288da767 100644 --- a/platform/platform-impl/src/com/intellij/platform/ProjectSetReader.java +++ b/platform/platform-impl/src/com/intellij/platform/ProjectSetReader.java @@ -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 processors = new HashMap(); - 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> 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 processors, final ProjectSetProcessor.Context context, final Iterator> iterator) { diff --git a/platform/platform-impl/src/com/intellij/platform/ProjectSetRequestHandler.coffee b/platform/platform-impl/src/com/intellij/platform/ProjectSetRequestHandler.coffee new file mode 100644 index 000000000000..ce1f91fdcffd --- /dev/null +++ b/platform/platform-impl/src/com/intellij/platform/ProjectSetRequestHandler.coffee @@ -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": "" +} +### \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/platform/ProjectSetRequestHandler.java b/platform/platform-impl/src/com/intellij/platform/ProjectSetRequestHandler.java index 865de871a26d..8a9ad24adfd4 100644 --- a/platform/platform-impl/src/com/intellij/platform/ProjectSetRequestHandler.java +++ b/platform/platform-impl/src/com/intellij/platform/ProjectSetRequestHandler.java @@ -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; } } diff --git a/platform/platform-impl/src/org/jetbrains/ide/RestService.java b/platform/platform-impl/src/org/jetbrains/ide/RestService.java index cdce90716e3b..09de2c549fdd 100644 --- a/platform/platform-impl/src/org/jetbrains/ide/RestService.java +++ b/platform/platform-impl/src/org/jetbrains/ide/RestService.java @@ -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. diff --git a/platform/platform-tests/platform-tests.iml b/platform/platform-tests/platform-tests.iml index 03e1830fb5d4..ad0fefcfb786 100644 --- a/platform/platform-tests/platform-tests.iml +++ b/platform/platform-tests/platform-tests.iml @@ -25,5 +25,6 @@ + \ No newline at end of file diff --git a/platform/platform-tests/testSrc/com/intellij/platform/ProjectSetTest.java b/platform/platform-tests/testSrc/com/intellij/platform/ProjectSetTest.java index da3c82f3579c..e346ea9c2f29 100644 --- a/platform/platform-tests/testSrc/com/intellij/platform/ProjectSetTest.java +++ b/platform/platform-tests/testSrc/com/intellij/platform/ProjectSetTest.java @@ -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>> 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> 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>() { @Override public int compare(@NotNull Pair o1, @NotNull Pair 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() { @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); + } }