From de18d5bf86be15b00fa2bbf018f0d858e233451c Mon Sep 17 00:00:00 2001 From: Evgeny Zakrevsky Date: Tue, 23 Oct 2012 16:15:45 +0400 Subject: [PATCH] Tasks. Generic Web Connector. GET and POST types of requests. --- .../tasks/generic/GenericWebRepository.java | 95 +++++++++++++++---- .../generic/GenericWebRepositoryEditor.java | 80 +++++++++++----- .../generic/GenericWebRepositoryType.java | 2 +- plugins/tasks/tasks-core/tasks-core.iml | 2 + 4 files changed, 132 insertions(+), 47 deletions(-) diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericWebRepository.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericWebRepository.java index 5667f41a08e7..989ac869e27d 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericWebRepository.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericWebRepository.java @@ -9,7 +9,9 @@ import com.intellij.tasks.impl.BaseRepositoryImpl; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.xmlb.annotations.Tag; import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.HttpMethod; import org.apache.commons.httpclient.methods.GetMethod; +import org.apache.commons.httpclient.methods.PostMethod; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; @@ -26,6 +28,8 @@ public class GenericWebRepository extends BaseRepositoryImpl { private String myTasksListURL = ""; private String myTaskPattern = ""; private String myLoginURL = ""; + private String myLoginMethodType = GenericWebRepositoryEditor.GET; + private String myGetTasksMethodType = GenericWebRepositoryEditor.GET; final static String SERVER_URL_PLACEHOLDER = "{serverUrl}"; final static String USERNAME_PLACEHOLDER = "{username}"; @@ -33,7 +37,10 @@ public class GenericWebRepository extends BaseRepositoryImpl { final static String ID_PLACEHOLDER = "{id}"; final static String SUMMARY_PLACEHOLDER = "{summary}"; final static String QUERY_PLACEHOLDER = "{query}"; + final static String MAX_COUNT_PLACEHOLDER = "{count}"; + //todo final static String DESCRIPTION_PLACEHOLDER = "{description}"; + //todo final static String PAGE_PLACEHOLDER = "{page}"; @SuppressWarnings({"UnusedDeclaration"}) @@ -49,6 +56,8 @@ public class GenericWebRepository extends BaseRepositoryImpl { myTasksListURL = other.getTasksListURL(); myTaskPattern = other.getTaskPattern(); myLoginURL = other.getLoginURL(); + myLoginMethodType = other.getLoginMethodType(); + myGetTasksMethodType = other.getGetTasksMethodType(); } @Override @@ -57,10 +66,16 @@ public class GenericWebRepository extends BaseRepositoryImpl { if (!isLoginAnonymously()) login(httpClient); - final GetMethod getMethod = new GetMethod(getFullTasksUrl(query != null ? query : "")); - httpClient.executeMethod(getMethod); - if (getMethod.getStatusCode() != 200) throw new Exception("Cannot get tasks: HTTP status code " + getMethod.getStatusCode()); - final String response = getMethod.getResponseBodyAsString(Integer.MAX_VALUE); + final List placeholders = getPlaceholders(myTaskPattern); + if (!placeholders.contains(ID_PLACEHOLDER) || !placeholders.contains(SUMMARY_PLACEHOLDER)) { + throw new Exception("Incorrect Task Pattern"); + } + + //todo add possibility to select method type + final HttpMethod method = getTaskListsMethod(query != null ? query : "", max); + httpClient.executeMethod(method); + if (method.getStatusCode() != 200) throw new Exception("Cannot get tasks: HTTP status code " + method.getStatusCode()); + final String response = method.getResponseBodyAsString(); final String taskPatternWithoutPlaceholders = myTaskPattern.replaceAll("\\{.+?\\}", ""); Matcher matcher = Pattern @@ -68,11 +83,6 @@ public class GenericWebRepository extends BaseRepositoryImpl { Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL | Pattern.UNICODE_CASE | Pattern.CANON_EQ) .matcher(response); - final List placeholders = getPlaceholders(myTaskPattern); - if (matcher.groupCount() != 2 || !placeholders.contains(ID_PLACEHOLDER) || !placeholders.contains(SUMMARY_PLACEHOLDER)) { - throw new Exception("Incorrect Task Pattern"); - } - List tasks = new ArrayList(); while (matcher.find()) { final String id = matcher.group(placeholders.indexOf(ID_PLACEHOLDER) + 1); @@ -86,12 +96,42 @@ public class GenericWebRepository extends BaseRepositoryImpl { return tasks.toArray(new Task[tasks.size()]); } + private HttpMethod getTaskListsMethod(final String query, final int max) { + String requestUrl = getFullTasksUrl(query, max); + return GenericWebRepositoryEditor.GET.equals(myGetTasksMethodType) ? new GetMethod(requestUrl) : getPostMethodFromURL(requestUrl); + } + private void login(final HttpClient httpClient) throws Exception { - final GetMethod method = new GetMethod(getFullLoginUrl()); + final HttpMethod method = getLoginMethod(); httpClient.executeMethod(method); if (method.getStatusCode() != 200) throw new Exception("Cannot login: HTTP status code " + method.getStatusCode()); } + private HttpMethod getLoginMethod() { + String requestUrl = getFullLoginUrl(); + return GenericWebRepositoryEditor.GET.equals(myLoginMethodType) ? new GetMethod(requestUrl) : getPostMethodFromURL(requestUrl); + } + + private static HttpMethod getPostMethodFromURL(final String requestUrl) { + int n = requestUrl.indexOf('?'); + if (n == -1) { + return new PostMethod(requestUrl); + } + + PostMethod postMethod = new PostMethod(requestUrl.substring(0, n)); + n = requestUrl.indexOf('?'); + String[] requestParams = requestUrl.substring(n + 1).split("&"); + for (String requestParam : requestParams) { + String[] nv = requestParam.split("="); + if (nv.length == 1) { + postMethod.addParameter(nv[0], ""); + } else { + postMethod.addParameter(nv[0], nv[1]); + } + } + return postMethod; + } + private static List getPlaceholders(String value) { if (value == null) { return ContainerUtil.emptyList(); @@ -105,21 +145,18 @@ public class GenericWebRepository extends BaseRepositoryImpl { return vars; } - private String getFullTasksUrl(final String query) { + private String getFullTasksUrl(final String query, final int max) { return getTasksListURL() - .replaceAll(placeholder2regexp(SERVER_URL_PLACEHOLDER), getUrl()) - .replaceAll(placeholder2regexp(QUERY_PLACEHOLDER), query); + .replaceAll(Pattern.quote(SERVER_URL_PLACEHOLDER), getUrl()) + .replaceAll(Pattern.quote(QUERY_PLACEHOLDER), encodeUrl(query)) + .replaceAll(Pattern.quote(MAX_COUNT_PLACEHOLDER), String.valueOf(max)); } private String getFullLoginUrl() { return getLoginURL() - .replaceAll(placeholder2regexp(SERVER_URL_PLACEHOLDER), getUrl()) - .replaceAll(placeholder2regexp(USERNAME_PLACEHOLDER), getUsername()) - .replaceAll(placeholder2regexp(PASSWORD_PLACEHOLDER), getPassword()); - } - - private static String placeholder2regexp(String placeholder) { - return placeholder.replaceAll("\\{", "\\\\{"); + .replaceAll(Pattern.quote(SERVER_URL_PLACEHOLDER), getUrl()) + .replaceAll(Pattern.quote(USERNAME_PLACEHOLDER), encodeUrl(getUsername())) + .replaceAll(Pattern.quote(PASSWORD_PLACEHOLDER), encodeUrl(getPassword())); } @Nullable @@ -158,6 +195,8 @@ public class GenericWebRepository extends BaseRepositoryImpl { if (!Comparing.equal(getTasksListURL(), that.getTasksListURL())) return false; if (!Comparing.equal(getTaskPattern(), that.getTaskPattern())) return false; if (!Comparing.equal(getLoginURL(), that.getLoginURL())) return false; + if (!Comparing.equal(getLoginMethodType(), that.getLoginMethodType())) return false; + if (!Comparing.equal(getGetTasksMethodType(), that.getGetTasksMethodType())) return false; return true; } @@ -184,4 +223,20 @@ public class GenericWebRepository extends BaseRepositoryImpl { public void setLoginURL(final String loginURL) { myLoginURL = loginURL; } + + public void setLoginMethodType(final String loginMethodType) { + myLoginMethodType = loginMethodType; + } + + public void setGetTasksMethodType(final String getTasksMethodType) { + myGetTasksMethodType = getTasksMethodType; + } + + public String getLoginMethodType() { + return myLoginMethodType; + } + + public String getGetTasksMethodType() { + return myGetTasksMethodType; + } } diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericWebRepositoryEditor.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericWebRepositoryEditor.java index 6e476417564f..ab9119779fc3 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericWebRepositoryEditor.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericWebRepositoryEditor.java @@ -1,41 +1,52 @@ package com.intellij.tasks.generic; +import com.intellij.ide.highlighter.HtmlFileType; import com.intellij.openapi.actionSystem.ActionManager; import com.intellij.openapi.actionSystem.IdeActions; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.EditorFactory; import com.intellij.openapi.keymap.KeymapUtil; import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.ComboBox; import com.intellij.tasks.config.BaseRepositoryEditor; import com.intellij.ui.TextFieldWithAutoCompletion; +import com.intellij.ui.TextFieldWithAutoCompletionContributor; import com.intellij.ui.components.JBLabel; import com.intellij.util.Consumer; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.ui.FormBuilder; +import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.Nullable; import javax.swing.*; +import java.awt.*; +import java.util.ArrayList; import static com.intellij.tasks.generic.GenericWebRepository.*; +import static com.intellij.ui.TextFieldWithAutoCompletion.StringsCompletionProvider; /** * User: Evgeny.Zakrevsky * Date: 10/4/12 */ public class GenericWebRepositoryEditor extends BaseRepositoryEditor { + public static final String POST = "POST"; + public static final String GET = "GET"; private JBLabel myTasksListURLLabel; private JBLabel myTaskPatternLabel; private TextFieldWithAutoCompletion myTasksListURLText; - private TextFieldWithAutoCompletion myTaskPatternText; + private Editor myTaskPatternText; private JBLabel myLoginURLLabel; private TextFieldWithAutoCompletion myLoginURLText; + private ComboBox myLoginMethodType; + private ComboBox myGetTasksMethodType; public GenericWebRepositoryEditor(final Project project, final GenericWebRepository repository, final Consumer changeListener) { super(project, repository, changeListener); - myUrlLabel.setText("{serverUrl}:"); - myUsernameLabel.setText("{username}:"); - myPasswordLabel.setText("{password}:"); + myUrlLabel.setText("Server URL"); } @Override @@ -43,13 +54,16 @@ public class GenericWebRepositoryEditor extends BaseRepositoryEditor completionList1 = ContainerUtil.newArrayList(SERVER_URL_PLACEHOLDER, QUERY_PLACEHOLDER, MAX_COUNT_PLACEHOLDER); + myTasksListURLText = TextFieldWithAutoCompletion.create(myProject, completionList1, null, false, myRepository.getTasksListURL()); installListener(myTasksListURLText.getDocument()); + myGetTasksMethodType = new ComboBox(new String[]{GET, POST}, -1); + myGetTasksMethodType.setSelectedItem(myRepository.getGetTasksMethodType()); + installListener(myGetTasksMethodType); + JPanel tasksPanel = new JPanel(new BorderLayout(UIUtil.DEFAULT_HGAP, UIUtil.DEFAULT_VGAP)); + tasksPanel.add(myTasksListURLText, BorderLayout.CENTER); + tasksPanel.add(myGetTasksMethodType, BorderLayout.EAST); myTaskPatternLabel = new JBLabel("Task Pattern:", SwingConstants.RIGHT); - myTaskPatternText = - TextFieldWithAutoCompletion - .create(myProject, ContainerUtil.newArrayList("({id}.+?)", "({summary}.+?)"), null, false, myRepository.getTaskPattern()); - installListener(myTaskPatternText.getDocument()); + final Document document = EditorFactory.getInstance().createDocument(myRepository.getTaskPattern()); + myTaskPatternText = EditorFactory.getInstance().createEditor(document, myProject, HtmlFileType.INSTANCE, false); + final ArrayList completionList2 = ContainerUtil.newArrayList("({id}.+?)", "({summary}.+?)"); + TextFieldWithAutoCompletionContributor + .installCompletion(document, myProject, new StringsCompletionProvider(completionList2, null), true); + installListener(document); + myTaskPatternText.getSettings().setLineMarkerAreaShown(false); + myTaskPatternText.getSettings().setFoldingOutlineShown(false); + //todo correct resizing + //todo completion + //todo completion without whitespace before cursor String useCompletionText = ". Use " + KeymapUtil @@ -79,25 +112,20 @@ public class GenericWebRepositoryEditor extends BaseRepositoryEditorAvailable placeholders: " + SERVER_URL_PLACEHOLDER + ", " + USERNAME_PLACEHOLDER + ", " + PASSWORD_PLACEHOLDER + + useCompletionText + "") + .addLabeledComponent(myTasksListURLLabel, tasksPanel) + .addTooltip( + "Available placeholders: " + SERVER_URL_PLACEHOLDER + ", " + MAX_COUNT_PLACEHOLDER + ", " + QUERY_PLACEHOLDER + + " (use for faster tasks search)" + useCompletionText + "") + .addLabeledComponent(myTaskPatternLabel, myTaskPatternText.getComponent()) + .addTooltip( + "Task pattern should be a regexp with two matching groups: ({id}.+?) and ({summary}.+?)" + useCompletionText + "") .getPanel(); } - @Override - public void dispose() { - super.dispose(); - if (myTasksListURLText != null && myTasksListURLText.getEditor() != null) - EditorFactory.getInstance().releaseEditor(myTasksListURLText.getEditor()); - if (myLoginURLText.getEditor() != null) EditorFactory.getInstance().releaseEditor(myLoginURLText.getEditor()); - if (myTaskPatternText.getEditor() != null) EditorFactory.getInstance().releaseEditor(myTaskPatternText.getEditor()); - } - @Override public void setAnchor(@Nullable final JComponent anchor) { super.setAnchor(anchor); diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericWebRepositoryType.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericWebRepositoryType.java index 4317bd459e4e..20ad197ab8f8 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericWebRepositoryType.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericWebRepositoryType.java @@ -18,7 +18,7 @@ public class GenericWebRepositoryType extends BaseRepositoryType + +