diff --git a/python/educational-core/src/com/jetbrains/edu/learning/builtInServer/StepikRestService.java b/python/educational-core/src/com/jetbrains/edu/learning/builtInServer/StepikRestService.java index 5cb9c402f33a..427f5c8fa5de 100644 --- a/python/educational-core/src/com/jetbrains/edu/learning/builtInServer/StepikRestService.java +++ b/python/educational-core/src/com/jetbrains/edu/learning/builtInServer/StepikRestService.java @@ -15,23 +15,54 @@ */ package com.jetbrains.edu.learning.builtInServer; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import com.intellij.ide.RecentProjectsManager; +import com.intellij.ide.RecentProjectsManagerBase; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.project.ProjectManager; +import com.intellij.platform.ProjectSetReader; +import com.jetbrains.edu.learning.StudyTaskManager; +import com.jetbrains.edu.learning.courseFormat.Course; 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.jdom.Document; +import org.jdom.Element; +import org.jdom.JDOMException; +import org.jdom.input.SAXBuilder; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.ide.RestService; +import java.io.File; import java.io.IOException; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; /** * @author meanmail */ public class StepikRestService extends RestService { + public static final String STUDY_PROJECT_XML_PATH = "/.idea/study_project.xml"; private static final Logger LOG = Logger.getInstance(StepikRestService.class.getName()); private static final String SERVICE_NAME = "stepik"; + private static final Pattern OPEN_COURSE = Pattern.compile("/stepik/course/[^/]*-(\\d+)(?:$|\\?|/.*)"); + + private static void openProject(String path) { + String descriptor = String.format("{\"project\": \"%s\"}", path); + JsonObject jsonObject = new JsonParser().parse(descriptor).getAsJsonObject(); + + ApplicationManager.getApplication().invokeAndWait(() -> { + new ProjectSetReader().readDescriptor(jsonObject, null); + activateLastFocusedFrame(); + }); + } @NotNull @Override @@ -41,7 +72,12 @@ public class StepikRestService extends RestService { @Override protected boolean isMethodSupported(@NotNull HttpMethod method) { - return method.equals(HttpMethod.GET); + return method == HttpMethod.GET; + } + + @Override + protected boolean isPrefixlessAllowed() { + return true; } @Nullable @@ -49,7 +85,64 @@ public class StepikRestService extends RestService { public String execute(@NotNull QueryStringDecoder urlDecoder, @NotNull FullHttpRequest request, @NotNull ChannelHandlerContext context) throws IOException { LOG.info("Request: " + urlDecoder.path()); - RestService.sendOk(request, context); - return null; + + String path = urlDecoder.path(); + Matcher matcher = OPEN_COURSE.matcher(path); + if (matcher.matches()) { + int course_id = Integer.parseInt(matcher.group(1)); + LOG.info("Open course: " + course_id); + + RecentProjectsManagerBase recentProjectsManager = (RecentProjectsManagerBase)RecentProjectsManager.getInstance(); + + if (recentProjectsManager == null) { + return null; + } + + RecentProjectsManagerBase.State state = recentProjectsManager.getState(); + + if (state == null) { + return null; + } + + List recentPaths = state.recentPaths; + + LOG.info(recentPaths.toString()); + + Project project = ProjectManager.getInstance().getDefaultProject(); + StudyTaskManager taskManager = new StudyTaskManager(project); + + SAXBuilder parser = new SAXBuilder(); + Document xmlDoc; + + for (String projectPath : recentPaths) { + try { + String studyProjectXML = projectPath + STUDY_PROJECT_XML_PATH; + xmlDoc = parser.build(new File(studyProjectXML)); + Element root = xmlDoc.getRootElement(); + Element component = root.getChild("component"); + if (component == null) { + continue; + } + + taskManager.loadState(component); + Course course = taskManager.getCourse(); + + if (course == null) { + continue; + } + + if (course.getId() == course_id) { + openProject(projectPath); + RestService.sendOk(request, context); + return null; + } + } + catch (JDOMException | IllegalStateException | IOException ignored) { + } + } + } + + RestService.sendStatus(HttpResponseStatus.NOT_FOUND, false, context.channel()); + return "Unknown command"; } }