();
+ //want the first line to be shorter, according to it's prefix
+ String firstLine = toArrayWrapping(str, mySettings.RIGHT_MARGIN - firstLinePrefixLength).get(0);
+ //so now first line is exactly same width we need
+ list.add(firstLine);
+ str = str.substring(firstLine.length());
+ //actually there is one more problem - when first line has unclosed tag, substring should be processed if it's inside
+ boolean unclosedPreTag = lineHasUnclosedPreTag(firstLine);
+ if (unclosedPreTag) {
+ str = PRE_TAG_START + str.replaceAll("^\\s+", "");
+ }
+
+ //getting all another lines according to their prefix
+ List subList = toArrayWrapping(str, mySettings.RIGHT_MARGIN - prefix.length());
+
+ //removing pre tag
+ if (unclosedPreTag) {
+ String firstLineTagRemoved = subList.get(0).substring(PRE_TAG_START.length());
+ subList.set(0, firstLineTagRemoved);
+ }
+ list.addAll(subList);
+ }
}
- List list = mySettings.WRAP_COMMENTS
- ? toArrayWrapping(s, mySettings.RIGHT_MARGIN - prefix.length())
- : toArray(s, "\n", new ArrayList());
+ else {
+ list = toArray(str, "\n", new ArrayList());
+ }
+
if (list == null) {
sb.append('\n');
}
@@ -515,11 +504,11 @@ public class JDParser {
if (line.length() == 0 && !mySettings.JD_KEEP_EMPTY_LINES) continue;
if (i != 0) sb.append(prefix);
if (line.length() == 0 && mySettings.JD_P_AT_EMPTY_LINES && !insidePreTag) {
- sb.append("");
+ sb.append(SELF_CLOSED_P_TAG);
}
else {
sb.append(line);
-
+
// We want to track if we're inside ...
in order to not generate there.
if (PRE_TAG_START.equals(line)) {
insidePreTag = true;
diff --git a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/javadoc/JDTag.java b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/javadoc/JDTag.java
new file mode 100644
index 000000000000..1b3514533179
--- /dev/null
+++ b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/javadoc/JDTag.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2000-2013 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.psi.impl.source.codeStyle.javadoc;
+
+import com.intellij.openapi.util.text.StringUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * User: Lepenkin Y.
+ * Date: 7/1/13
+ * Time: 4:15 PM
+ */
+public enum JDTag {
+ SEE("see"),
+ AUTHOR("author"),
+ VERSION("version"),
+ THROWS("throws"),
+ EXCEPTION("exception"),
+ RETURN("return"),
+ PARAM("param"),
+ SINCE("since"),
+ DEPRECATED("deprecated");
+
+
+ @NotNull private final String myTag;
+
+ JDTag(@NotNull String tag) {
+ this.myTag = tag;
+ }
+
+ @NotNull
+ public String getDescriptionPrefix(@NotNull String prefix) {
+ return prefix + StringUtil.repeatSymbol(' ', getWithEndWhitespace().length());
+ }
+
+ @NotNull
+ public String getWithEndWhitespace() {
+ return "@" + myTag + " ";
+ }
+
+ public boolean tagEqual(@Nullable String tag) {
+ return myTag.equals(tag);
+ }
+}
diff --git a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/javadoc/NameDesc.java b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/javadoc/NameDesc.java
index d7de91b90ecc..6e8ee10d4ad5 100644
--- a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/javadoc/NameDesc.java
+++ b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/javadoc/NameDesc.java
@@ -15,29 +15,25 @@
*/
package com.intellij.psi.impl.source.codeStyle.javadoc;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
/**
*
* @author Dmitry Skavish
*/
public class NameDesc {
+ @NotNull public final String name;
+ @Nullable public final String desc;
- public String name;
- public String desc;
- private String type;
-
- public NameDesc(String name, String desc) {
+ public NameDesc(@NotNull String name, @Nullable String desc) {
this.name = name;
this.desc = desc;
}
- public NameDesc(String name, String desc, String type) {
- this.name = name;
- this.desc = desc;
- this.type = type;
- }
-
+ @NotNull
+ @Override
public String toString() {
- if (type == null) return name;
- return name + ": " + type;
+ return name;
}
}
diff --git a/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavadocFormatterTest.java b/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavadocFormatterTest.java
index b28fcbd6b50a..28e4de5099f6 100644
--- a/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavadocFormatterTest.java
+++ b/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavadocFormatterTest.java
@@ -216,4 +216,140 @@ public class JavadocFormatterTest extends AbstractJavaFormatterTest {
doTextTest(before, after);
}
+
+ public void testReturnTagAlignment() throws Exception {
+ getSettings().getRootSettings().ENABLE_JAVADOC_FORMATTING = true;
+ getSettings().getRootSettings().RIGHT_MARGIN = 80;
+ getSettings().getRootSettings().JD_LEADING_ASTERISKS_ARE_ENABLED = true;
+ getSettings().getRootSettings().WRAP_COMMENTS = true;
+ getSettings().getRootSettings().getCommonSettings(JavaLanguage.INSTANCE).WRAP_LONG_LINES = true;
+
+ String before = " /**\n" +
+ " * @return this is a return value documentation with a very long description that is longer than the right margin. It is more than 200 characters long, not including the comment indent and the asterisk characters, which should be greater than any sane right margin.\n" +
+ " */\n" +
+ " public int method(int parameter) {\n" +
+ " return 0;\n" +
+ " }\n";
+
+ String after = "/**\n" +
+ " * @return this is a return value documentation with a very long description\n" +
+ " * that is longer than the right margin. It is more than 200 characters\n" +
+ " * long, not including the comment indent and the asterisk characters, which\n" +
+ " * should be greater than any sane right margin.\n" +
+ " */\n" +
+ "public int method(int parameter) {\n" +
+ " return 0;\n" +
+ "}\n";
+
+ doClassTest(before, after);
+ }
+
+
+ public void testReturnTagAlignmentWithPreTagOnFirstLine() throws Exception {
+ getSettings().getRootSettings().ENABLE_JAVADOC_FORMATTING = true;
+ getSettings().getRootSettings().RIGHT_MARGIN = 80;
+ getSettings().getRootSettings().JD_LEADING_ASTERISKS_ARE_ENABLED = true;
+ getSettings().getRootSettings().WRAP_COMMENTS = true;
+ getSettings().getRootSettings().getCommonSettings(JavaLanguage.INSTANCE).WRAP_LONG_LINES = true;
+
+ String before = " /**\n" +
+ " * @return this is a return value documentation with a very long description\n" +
+ " * that is longer than the right margin.
\n" +
+ " */\n" +
+ " public int method(int parameter) {\n" +
+ " return 0;\n" +
+ " }";
+
+ String after = "/**\n" +
+ " * @return this is a return value documentation with a very long\n" +
+ " * description\n" +
+ " * that is longer than the right margin.
\n" +
+ " */\n" +
+ "public int method(int parameter) {\n" +
+ " return 0;\n" +
+ "}";
+
+ doClassTest(before, after);
+ }
+
+ public void testSeeTagAlignment() throws Exception {
+ getSettings().getRootSettings().ENABLE_JAVADOC_FORMATTING = true;
+ getSettings().getRootSettings().RIGHT_MARGIN = 80;
+ getSettings().getRootSettings().JD_LEADING_ASTERISKS_ARE_ENABLED = true;
+ getSettings().getRootSettings().WRAP_COMMENTS = true;
+ getSettings().getRootSettings().getCommonSettings(JavaLanguage.INSTANCE).WRAP_LONG_LINES = true;
+
+ String before = " /**\n" +
+ " * @see this is an additional documentation with a very long description that is longer than the right margin. It is more than 200 characters long, not including the comment indent and the asterisk characters which should be greater than any sane right margin\n" +
+ " */\n" +
+ " public int method(int parameter) {\n" +
+ " return 0;\n" +
+ " }";
+
+ String after = "/**\n" +
+ " * @see this is an additional documentation with a very long description\n" +
+ " * that is longer than the right margin. It is more than 200 characters\n" +
+ " * long, not including the comment indent and the asterisk characters which\n" +
+ " * should be greater than any sane right margin\n" +
+ " */\n" +
+ "public int method(int parameter) {\n" +
+ " return 0;\n" +
+ "}";
+
+ doClassTest(before, after);
+ }
+
+ public void testDummySinceTagAlignment() throws Exception {
+ getSettings().getRootSettings().ENABLE_JAVADOC_FORMATTING = true;
+ getSettings().getRootSettings().RIGHT_MARGIN = 80;
+ getSettings().getRootSettings().JD_LEADING_ASTERISKS_ARE_ENABLED = true;
+ getSettings().getRootSettings().WRAP_COMMENTS = true;
+ getSettings().getRootSettings().getCommonSettings(JavaLanguage.INSTANCE).WRAP_LONG_LINES = true;
+
+ String before = " /**\n" +
+ " * @since this is an additional documentation with a very long description that is longer than the right margin. It is more than 200 characters long, not including the comment indent and the asterisk characters which should be greater than any sane right margin\n" +
+ " */\n" +
+ " public int method(int parameter) {\n" +
+ " return 0;\n" +
+ " }";
+
+ String after = "/**\n" +
+ " * @since this is an additional documentation with a very long description\n" +
+ " * that is longer than the right margin. It is more than 200 characters\n" +
+ " * long, not including the comment indent and the asterisk characters which\n" +
+ " * should be greater than any sane right margin\n" +
+ " */\n" +
+ "public int method(int parameter) {\n" +
+ " return 0;\n" +
+ "}";
+
+ doClassTest(before, after);
+ }
+
+ public void testDummyDeprecatedTagAlignment() throws Exception {
+ getSettings().getRootSettings().ENABLE_JAVADOC_FORMATTING = true;
+ getSettings().getRootSettings().RIGHT_MARGIN = 80;
+ getSettings().getRootSettings().JD_LEADING_ASTERISKS_ARE_ENABLED = true;
+ getSettings().getRootSettings().WRAP_COMMENTS = true;
+ getSettings().getRootSettings().getCommonSettings(JavaLanguage.INSTANCE).WRAP_LONG_LINES = true;
+
+ String before = " /**\n" +
+ " * @deprecated this is an additional documentation with a very long description that is longer than the right margin. It is more than 200 characters long, not including the comment indent and the asterisk characters which should be greater than any sane right margin\n" +
+ " */\n" +
+ " public int method(int parameter) {\n" +
+ " return 0;\n" +
+ " }";
+
+ String after = "/**\n" +
+ " * @deprecated this is an additional documentation with a very long\n" +
+ " * description that is longer than the right margin. It is more than 200\n" +
+ " * characters long, not including the comment indent and the asterisk\n" +
+ " * characters which should be greater than any sane right margin\n" +
+ " */\n" +
+ "public int method(int parameter) {\n" +
+ " return 0;\n" +
+ "}";
+
+ doClassTest(before, after);
+ }
}
diff --git a/platform/lang-api/src/com/intellij/execution/configurations/ConfigurationTypeBase.java b/platform/lang-api/src/com/intellij/execution/configurations/ConfigurationTypeBase.java
index e47eb7877d32..b6ab46753b3e 100644
--- a/platform/lang-api/src/com/intellij/execution/configurations/ConfigurationTypeBase.java
+++ b/platform/lang-api/src/com/intellij/execution/configurations/ConfigurationTypeBase.java
@@ -16,12 +16,10 @@
package com.intellij.execution.configurations;
+import com.intellij.util.ArrayUtil;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
/**
* @author yole
@@ -44,10 +42,7 @@ public abstract class ConfigurationTypeBase implements ConfigurationType {
}
protected void addFactory(ConfigurationFactory factory) {
- List newFactories = new ArrayList(myFactories.length + 1);
- Collections.addAll(newFactories, myFactories);
- newFactories.add(factory);
- myFactories = newFactories.toArray(new ConfigurationFactory[newFactories.size()]);
+ myFactories = ArrayUtil.append(myFactories, factory);
}
@Override
diff --git a/platform/platform-resources/src/META-INF/PlatformLangPlugin.xml b/platform/platform-resources/src/META-INF/PlatformLangPlugin.xml
index 250b0110975b..fd2ba06e0064 100644
--- a/platform/platform-resources/src/META-INF/PlatformLangPlugin.xml
+++ b/platform/platform-resources/src/META-INF/PlatformLangPlugin.xml
@@ -88,6 +88,7 @@
+
diff --git a/platform/platform-resources/src/META-INF/RemoteServers.xml b/platform/platform-resources/src/META-INF/RemoteServers.xml
new file mode 100644
index 000000000000..89386b66db40
--- /dev/null
+++ b/platform/platform-resources/src/META-INF/RemoteServers.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ com.intellij.remoteServer.run.DeployToServerConfigurationTypesRegistrar
+
+
+
\ No newline at end of file
diff --git a/platform/remote-servers/api/remote-servers-api.iml b/platform/remote-servers/api/remote-servers-api.iml
new file mode 100644
index 000000000000..deb49db5a58f
--- /dev/null
+++ b/platform/remote-servers/api/remote-servers-api.iml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/platform/remote-servers/api/src/com/intellij/remoteServer/ServerType.java b/platform/remote-servers/api/src/com/intellij/remoteServer/ServerType.java
new file mode 100644
index 000000000000..c3b2029dd957
--- /dev/null
+++ b/platform/remote-servers/api/src/com/intellij/remoteServer/ServerType.java
@@ -0,0 +1,41 @@
+package com.intellij.remoteServer;
+
+import com.intellij.openapi.extensions.ExtensionPointName;
+import com.intellij.openapi.options.UnnamedConfigurable;
+import com.intellij.openapi.project.Project;
+import com.intellij.remoteServer.configuration.ServerConfiguration;
+import com.intellij.remoteServer.deployment.Deployer;
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.*;
+
+/**
+ * @author nik
+ */
+public abstract class ServerType {
+ public static final ExtensionPointName EP_NAME = ExtensionPointName.create("com.intellij.remoteServer.type");
+ private final String myId;
+
+ protected ServerType(String id) {
+ myId = id;
+ }
+
+ public final String getId() {
+ return myId;
+ }
+
+ @NotNull
+ public abstract String getPresentableName();
+
+ @NotNull
+ public abstract Icon getIcon();
+
+ @NotNull
+ public abstract C createDefaultConfiguration();
+
+ @NotNull
+ public abstract UnnamedConfigurable createConfigurable(@NotNull C configuration);
+
+ @NotNull
+ public abstract Deployer createDeployer(Project project);
+}
diff --git a/platform/remote-servers/api/src/com/intellij/remoteServer/configuration/RemoteServer.java b/platform/remote-servers/api/src/com/intellij/remoteServer/configuration/RemoteServer.java
new file mode 100644
index 000000000000..e845adec0be6
--- /dev/null
+++ b/platform/remote-servers/api/src/com/intellij/remoteServer/configuration/RemoteServer.java
@@ -0,0 +1,20 @@
+package com.intellij.remoteServer.configuration;
+
+import com.intellij.remoteServer.ServerType;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author nik
+ */
+public interface RemoteServer {
+ @NotNull
+ String getName();
+
+ @NotNull
+ ServerType getType();
+
+ @NotNull
+ C getConfiguration();
+
+ void setName(String name);
+}
diff --git a/platform/remote-servers/api/src/com/intellij/remoteServer/configuration/RemoteServersManager.java b/platform/remote-servers/api/src/com/intellij/remoteServer/configuration/RemoteServersManager.java
new file mode 100644
index 000000000000..5c29088d9cd3
--- /dev/null
+++ b/platform/remote-servers/api/src/com/intellij/remoteServer/configuration/RemoteServersManager.java
@@ -0,0 +1,30 @@
+package com.intellij.remoteServer.configuration;
+
+import com.intellij.openapi.components.ServiceManager;
+import com.intellij.remoteServer.ServerType;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public abstract class RemoteServersManager {
+ public static RemoteServersManager getInstance() {
+ return ServiceManager.getService(RemoteServersManager.class);
+ }
+
+ public abstract List> getServers();
+
+ public abstract List> getServers(@NotNull ServerType type);
+
+ @Nullable
+ public abstract RemoteServer findByName(@NotNull String name, @NotNull ServerType type);
+
+ public abstract RemoteServer createServer(@NotNull ServerType type, @NotNull String name);
+
+ public abstract void addServer(RemoteServer> server);
+
+ public abstract void removeServer(RemoteServer> server);
+}
diff --git a/platform/remote-servers/api/src/com/intellij/remoteServer/configuration/ServerConfiguration.java b/platform/remote-servers/api/src/com/intellij/remoteServer/configuration/ServerConfiguration.java
new file mode 100644
index 000000000000..255bdb834480
--- /dev/null
+++ b/platform/remote-servers/api/src/com/intellij/remoteServer/configuration/ServerConfiguration.java
@@ -0,0 +1,10 @@
+package com.intellij.remoteServer.configuration;
+
+import com.intellij.openapi.components.PersistentStateComponent;
+
+/**
+ * @author nik
+ */
+public abstract class ServerConfiguration {
+ public abstract PersistentStateComponent> getSerializer();
+}
diff --git a/platform/remote-servers/api/src/com/intellij/remoteServer/deployment/ArtifactDeploymentSource.java b/platform/remote-servers/api/src/com/intellij/remoteServer/deployment/ArtifactDeploymentSource.java
new file mode 100644
index 000000000000..1a3838e9e336
--- /dev/null
+++ b/platform/remote-servers/api/src/com/intellij/remoteServer/deployment/ArtifactDeploymentSource.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2000-2013 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.remoteServer.deployment;
+
+import com.intellij.packaging.artifacts.Artifact;
+import com.intellij.packaging.artifacts.ArtifactPointer;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author nik
+ */
+public interface ArtifactDeploymentSource extends DeploymentSource {
+ @NotNull
+ ArtifactPointer getArtifactPointer();
+
+ @Nullable
+ Artifact getArtifact();
+}
diff --git a/platform/remote-servers/api/src/com/intellij/remoteServer/deployment/Deployer.java b/platform/remote-servers/api/src/com/intellij/remoteServer/deployment/Deployer.java
new file mode 100644
index 000000000000..c16322cecfcc
--- /dev/null
+++ b/platform/remote-servers/api/src/com/intellij/remoteServer/deployment/Deployer.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2000-2013 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.remoteServer.deployment;
+
+import com.intellij.remoteServer.configuration.RemoteServer;
+import com.intellij.remoteServer.configuration.ServerConfiguration;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public abstract class Deployer {
+ @NotNull
+ public abstract List getAvailableDeploymentSources();
+
+ public abstract void startDeployment(@NotNull RemoteServer server, @NotNull DeploymentSource source);
+}
diff --git a/platform/remote-servers/api/src/com/intellij/remoteServer/deployment/DeploymentSource.java b/platform/remote-servers/api/src/com/intellij/remoteServer/deployment/DeploymentSource.java
new file mode 100644
index 000000000000..123ae3eab3a3
--- /dev/null
+++ b/platform/remote-servers/api/src/com/intellij/remoteServer/deployment/DeploymentSource.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2000-2013 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.remoteServer.deployment;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.io.File;
+
+/**
+ * @author nik
+ */
+public interface DeploymentSource {
+ @Nullable
+ File getFile();
+
+ @Nullable
+ String getFilePath();
+
+ @NotNull
+ String getPresentableName();
+
+ @Nullable
+ Icon getIcon();
+
+ boolean isValid();
+}
diff --git a/platform/remote-servers/api/src/com/intellij/remoteServer/deployment/DeploymentSourceUtil.java b/platform/remote-servers/api/src/com/intellij/remoteServer/deployment/DeploymentSourceUtil.java
new file mode 100644
index 000000000000..1d10281e54c0
--- /dev/null
+++ b/platform/remote-servers/api/src/com/intellij/remoteServer/deployment/DeploymentSourceUtil.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2000-2013 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.remoteServer.deployment;
+
+import com.intellij.openapi.components.ServiceManager;
+import com.intellij.openapi.project.Project;
+import com.intellij.packaging.artifacts.ArtifactPointer;
+import org.jdom.Element;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author nik
+ */
+public abstract class DeploymentSourceUtil {
+ public static DeploymentSourceUtil getInstance() {
+ return ServiceManager.getService(DeploymentSourceUtil.class);
+ }
+
+ @NotNull
+ public abstract ArtifactDeploymentSource createArtifactDeploymentSource(@NotNull ArtifactPointer artifactPointer);
+
+ public abstract DeploymentSource loadDeploymentSource(@NotNull Element element, @NotNull Project project);
+
+ public abstract void saveDeploymentSource(@NotNull DeploymentSource source, @NotNull Element element, @NotNull Project project);
+}
diff --git a/platform/remote-servers/impl/remote-servers-impl.iml b/platform/remote-servers/impl/remote-servers-impl.iml
new file mode 100644
index 000000000000..51c6c6f8de63
--- /dev/null
+++ b/platform/remote-servers/impl/remote-servers-impl.iml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/configuration/impl/RemoteServerConfigurable.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/configuration/impl/RemoteServerConfigurable.java
new file mode 100644
index 000000000000..6633e15d6ae5
--- /dev/null
+++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/configuration/impl/RemoteServerConfigurable.java
@@ -0,0 +1,93 @@
+package com.intellij.remoteServer.configuration.impl;
+
+import com.intellij.openapi.options.ConfigurationException;
+import com.intellij.openapi.options.UnnamedConfigurable;
+import com.intellij.openapi.ui.NamedConfigurable;
+import com.intellij.remoteServer.configuration.RemoteServer;
+import com.intellij.remoteServer.configuration.ServerConfiguration;
+import org.jetbrains.annotations.Nls;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.awt.*;
+
+/**
+ * @author nik
+ */
+public class RemoteServerConfigurable extends NamedConfigurable> {
+ private final UnnamedConfigurable myConfigurable;
+ private final RemoteServer> myServer;
+ private String myServerName;
+ private boolean myNew;
+
+ public RemoteServerConfigurable(RemoteServer server, Runnable treeUpdater, boolean isNew) {
+ super(true, treeUpdater);
+ myServer = server;
+ myNew = isNew;
+ myServerName = myServer.getName();
+ C c = server.getConfiguration();
+ myConfigurable = server.getType().createConfigurable(c);
+ }
+
+ @Override
+ public RemoteServer> getEditableObject() {
+ return myServer;
+ }
+
+ @Override
+ public String getBannerSlogan() {
+ return myServer.getName();
+ }
+
+ @Override
+ public JComponent createOptionsPanel() {
+ JComponent component = myConfigurable.createComponent();
+ JPanel panel = new JPanel(new BorderLayout());
+ panel.add(component, BorderLayout.NORTH);
+ return panel;
+ }
+
+ @Nls
+ @Override
+ public String getDisplayName() {
+ return myServerName;
+ }
+
+ @Nullable
+ @Override
+ public String getHelpTopic() {
+ return null;
+ }
+
+ @Override
+ public void setDisplayName(String name) {
+ myServerName = name;
+ }
+
+ @Override
+ public boolean isModified() {
+ return myNew || myConfigurable.isModified() || !myServerName.equals(myServer.getName());
+ }
+
+ @Override
+ public void apply() throws ConfigurationException {
+ myConfigurable.apply();
+ myNew = false;
+ }
+
+ @Override
+ public void reset() {
+ myConfigurable.reset();
+ }
+
+ @Override
+ public void disposeUIResources() {
+ myConfigurable.disposeUIResources();
+ }
+
+ @Nullable
+ @Override
+ public Icon getIcon(boolean expanded) {
+ return myServer.getType().getIcon();
+ }
+}
diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/configuration/impl/RemoteServerImpl.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/configuration/impl/RemoteServerImpl.java
new file mode 100644
index 000000000000..a210be03cd2c
--- /dev/null
+++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/configuration/impl/RemoteServerImpl.java
@@ -0,0 +1,44 @@
+package com.intellij.remoteServer.configuration.impl;
+
+import com.intellij.remoteServer.ServerType;
+import com.intellij.remoteServer.configuration.RemoteServer;
+import com.intellij.remoteServer.configuration.ServerConfiguration;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author nik
+ */
+public class RemoteServerImpl implements RemoteServer {
+ private String myName;
+ private ServerType myType;
+ private C myConfiguration;
+
+ public RemoteServerImpl(String name, ServerType type, C configuration) {
+ myName = name;
+ myType = type;
+ myConfiguration = configuration;
+ }
+
+ @NotNull
+ @Override
+ public String getName() {
+ return myName;
+ }
+
+ @NotNull
+ @Override
+ public ServerType getType() {
+ return myType;
+ }
+
+ @NotNull
+ @Override
+ public C getConfiguration() {
+ return myConfiguration;
+ }
+
+ @Override
+ public void setName(String name) {
+ myName = name;
+ }
+}
diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/configuration/impl/RemoteServerListConfigurable.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/configuration/impl/RemoteServerListConfigurable.java
new file mode 100644
index 000000000000..f2ff8c96d24f
--- /dev/null
+++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/configuration/impl/RemoteServerListConfigurable.java
@@ -0,0 +1,171 @@
+package com.intellij.remoteServer.configuration.impl;
+
+import com.intellij.openapi.actionSystem.ActionGroup;
+import com.intellij.openapi.actionSystem.AnAction;
+import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.actionSystem.CommonShortcuts;
+import com.intellij.openapi.options.ConfigurationException;
+import com.intellij.openapi.options.OptionalConfigurable;
+import com.intellij.openapi.project.DumbAwareAction;
+import com.intellij.openapi.ui.MasterDetailsComponent;
+import com.intellij.openapi.ui.NamedConfigurable;
+import com.intellij.openapi.util.Condition;
+import com.intellij.remoteServer.ServerType;
+import com.intellij.remoteServer.configuration.RemoteServer;
+import com.intellij.remoteServer.configuration.RemoteServersManager;
+import com.intellij.util.IconUtil;
+import com.intellij.util.text.UniqueNameGenerator;
+import org.jetbrains.annotations.Nls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author nik
+ */
+public class RemoteServerListConfigurable extends MasterDetailsComponent implements OptionalConfigurable {
+ private final RemoteServersManager myServersManager;
+
+ public RemoteServerListConfigurable(RemoteServersManager manager) {
+ myServersManager = manager;
+ initTree();
+ }
+
+ @Nls
+ @Override
+ public String getDisplayName() {
+ return "Clouds";
+ }
+
+ @Override
+ public void reset() {
+ myRoot.removeAllChildren();
+ for (RemoteServer> server : myServersManager.getServers()) {
+ addServerNode(server, false);
+ }
+ super.reset();
+ }
+
+ private MyNode addServerNode(RemoteServer> server, boolean isNew) {
+ MyNode node = new MyNode(new RemoteServerConfigurable(server, TREE_UPDATER, isNew));
+ addNode(node, myRoot);
+ return node;
+ }
+
+ @Override
+ protected void processRemovedItems() {
+ Set> servers = new HashSet>();
+ for (NamedConfigurable> configurable : getConfiguredServers()) {
+ servers.add(configurable.getEditableObject());
+ }
+
+ List> toDelete = new ArrayList>();
+ for (RemoteServer> server : myServersManager.getServers()) {
+ if (!servers.contains(server)) {
+ toDelete.add(server);
+ }
+ }
+ for (RemoteServer> server : toDelete) {
+ myServersManager.removeServer(server);
+ }
+ }
+
+ @Override
+ public void apply() throws ConfigurationException {
+ super.apply();
+ Set> servers = new HashSet>(myServersManager.getServers());
+ for (NamedConfigurable> configurable : getConfiguredServers()) {
+ RemoteServer> server = configurable.getEditableObject();
+ server.setName(configurable.getDisplayName());
+ if (!servers.contains(server)) {
+ myServersManager.addServer(server);
+ }
+ }
+ }
+
+ @Nullable
+ @Override
+ protected ArrayList createActions(boolean fromPopup) {
+ ArrayList actions = new ArrayList();
+ actions.add(new AddRemoteServerGroup());
+ actions.add(new MyDeleteAction());
+ return actions;
+ }
+
+ @Override
+ public boolean needDisplay() {
+ return ServerType.EP_NAME.getExtensions().length > 0;
+ }
+
+ @Override
+ protected boolean wasObjectStored(Object editableObject) {
+ return true;
+ }
+
+ private List>> getConfiguredServers() {
+ List>> configurables = new ArrayList>>();
+ for (int i = 0; i < myRoot.getChildCount(); i++) {
+ MyNode node = (MyNode)myRoot.getChildAt(i);
+ configurables.add((NamedConfigurable>)node.getConfigurable());
+ }
+ return configurables;
+ }
+
+ private class AddRemoteServerGroup extends ActionGroup implements ActionGroupWithPreselection {
+ private AddRemoteServerGroup() {
+ super("Add", "", IconUtil.getAddIcon());
+ registerCustomShortcutSet(CommonShortcuts.INSERT, myTree);
+ }
+
+ @NotNull
+ @Override
+ public AnAction[] getChildren(@Nullable AnActionEvent e) {
+ ServerType[] serverTypes = ServerType.EP_NAME.getExtensions();
+ AnAction[] actions = new AnAction[serverTypes.length];
+ for (int i = 0; i < serverTypes.length; i++) {
+ actions[i] = new AddRemoteServerAction(serverTypes[i]);
+ }
+ return actions;
+ }
+
+ @Override
+ public ActionGroup getActionGroup() {
+ return this;
+ }
+
+ @Override
+ public int getDefaultIndex() {
+ return 0;
+ }
+ }
+
+ private class AddRemoteServerAction extends DumbAwareAction {
+ private final ServerType> myServerType;
+
+ private AddRemoteServerAction(ServerType> serverType) {
+ super(serverType.getPresentableName(), null, serverType.getIcon());
+ myServerType = serverType;
+ }
+
+ @Override
+ public void actionPerformed(AnActionEvent e) {
+ String name = UniqueNameGenerator.generateUniqueName(myServerType.getPresentableName(), new Condition() {
+ @Override
+ public boolean value(String s) {
+ for (NamedConfigurable> configurable : getConfiguredServers()) {
+ if (configurable.getDisplayName().equals(s)) {
+ return false;
+ }
+ }
+ return true;
+ }
+ });
+ MyNode node = addServerNode(myServersManager.createServer(myServerType, name), true);
+ selectNodeInTree(node);
+ }
+ }
+}
diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/configuration/impl/RemoteServerState.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/configuration/impl/RemoteServerState.java
new file mode 100644
index 000000000000..fcf6f2dc6c56
--- /dev/null
+++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/configuration/impl/RemoteServerState.java
@@ -0,0 +1,18 @@
+package com.intellij.remoteServer.configuration.impl;
+
+import com.intellij.util.xmlb.annotations.Attribute;
+import com.intellij.util.xmlb.annotations.Tag;
+import org.jdom.Element;
+
+/**
+* @author nik
+*/
+@Tag("remote-server")
+public class RemoteServerState {
+ @Attribute("name")
+ public String myName;
+ @Attribute("type")
+ public String myTypeId;
+ @Tag("configuration")
+ public Element myConfiguration;
+}
diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/configuration/impl/RemoteServersManagerImpl.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/configuration/impl/RemoteServersManagerImpl.java
new file mode 100644
index 000000000000..3065bbc9f435
--- /dev/null
+++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/configuration/impl/RemoteServersManagerImpl.java
@@ -0,0 +1,125 @@
+package com.intellij.remoteServer.configuration.impl;
+
+import com.intellij.openapi.components.ComponentSerializationUtil;
+import com.intellij.openapi.components.PersistentStateComponent;
+import com.intellij.openapi.components.State;
+import com.intellij.openapi.components.Storage;
+import com.intellij.openapi.components.StoragePathMacros;
+import com.intellij.remoteServer.ServerType;
+import com.intellij.remoteServer.configuration.RemoteServer;
+import com.intellij.remoteServer.configuration.RemoteServersManager;
+import com.intellij.remoteServer.configuration.ServerConfiguration;
+import com.intellij.util.xmlb.SkipDefaultValuesSerializationFilters;
+import com.intellij.util.xmlb.XmlSerializer;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @author nik
+ */
+@State(name = "RemoteServers", storages = {
+ @Storage(file = StoragePathMacros.APP_CONFIG + "/remote-servers.xml")
+})
+public class RemoteServersManagerImpl extends RemoteServersManager implements PersistentStateComponent {
+ public static final SkipDefaultValuesSerializationFilters SERIALIZATION_FILTERS = new SkipDefaultValuesSerializationFilters();
+ private List> myServers = new ArrayList>();
+ private List myUnknownServers = new ArrayList();
+
+ @Override
+ public List> getServers() {
+ return Collections.unmodifiableList(myServers);
+ }
+
+ @Override
+ public List> getServers(@NotNull ServerType type) {
+ List> servers = new ArrayList>();
+ for (RemoteServer> server : myServers) {
+ if (server.getType().equals(type)) {
+ servers.add((RemoteServer)server);
+ }
+ }
+ return servers;
+ }
+
+ @Nullable
+ @Override
+ public RemoteServer findByName(@NotNull String name, @NotNull ServerType type) {
+ for (RemoteServer> server : myServers) {
+ if (server.getType().equals(type) && server.getName().equals(name)) {
+ return (RemoteServer)server;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public RemoteServer createServer(@NotNull ServerType type, @NotNull String name) {
+ return new RemoteServerImpl(name, type, type.createDefaultConfiguration());
+ }
+
+ @Override
+ public void addServer(RemoteServer> server) {
+ myServers.add(server);
+ }
+
+ @Override
+ public void removeServer(RemoteServer> server) {
+ myServers.remove(server);
+ }
+
+ @Nullable
+ @Override
+ public RemoteServersManagerState getState() {
+ RemoteServersManagerState state = new RemoteServersManagerState();
+ for (RemoteServer> server : myServers) {
+ RemoteServerState serverState = new RemoteServerState();
+ serverState.myName = server.getName();
+ serverState.myTypeId = server.getType().getId();
+ serverState.myConfiguration = XmlSerializer.serialize(server.getConfiguration().getSerializer().getState(), SERIALIZATION_FILTERS);
+ state.myServers.add(serverState);
+ }
+ state.myServers.addAll(myUnknownServers);
+ return state;
+ }
+
+ @Override
+ public void loadState(RemoteServersManagerState state) {
+ myUnknownServers.clear();
+ myServers.clear();
+ for (RemoteServerState server : state.myServers) {
+ ServerType> type = findServerType(server.myTypeId);
+ if (type == null) {
+ myUnknownServers.add(server);
+ }
+ else {
+ myServers.add(createConfiguration(type, server));
+ }
+ }
+ }
+
+ private static RemoteServerImpl createConfiguration(ServerType type, RemoteServerState server) {
+ C configuration = type.createDefaultConfiguration();
+ PersistentStateComponent> serializer = configuration.getSerializer();
+ loadConfiguration(server, serializer);
+ return new RemoteServerImpl(server.myName, type, configuration);
+ }
+
+ private static void loadConfiguration(RemoteServerState server, PersistentStateComponent serializer) {
+ S deserialize = (S)XmlSerializer.deserialize(server.myConfiguration, ComponentSerializationUtil.getStateClass(serializer.getClass()));
+ serializer.loadState(deserialize);
+ }
+
+ @Nullable
+ private static ServerType> findServerType(@NotNull String typeId) {
+ for (ServerType serverType : ServerType.EP_NAME.getExtensions()) {
+ if (serverType.getId().equals(typeId)) {
+ return serverType;
+ }
+ }
+ return null;
+ }
+}
diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/configuration/impl/RemoteServersManagerState.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/configuration/impl/RemoteServersManagerState.java
new file mode 100644
index 000000000000..0f233f675354
--- /dev/null
+++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/configuration/impl/RemoteServersManagerState.java
@@ -0,0 +1,16 @@
+package com.intellij.remoteServer.configuration.impl;
+
+import com.intellij.util.xmlb.annotations.AbstractCollection;
+import com.intellij.util.xmlb.annotations.Property;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public class RemoteServersManagerState {
+ @Property(surroundWithTag = false)
+ @AbstractCollection(surroundWithTag = false)
+ public List myServers = new ArrayList();
+}
diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/deployment/impl/ArtifactDeploymentSourceImpl.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/deployment/impl/ArtifactDeploymentSourceImpl.java
new file mode 100644
index 000000000000..3be71fea8ff7
--- /dev/null
+++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/deployment/impl/ArtifactDeploymentSourceImpl.java
@@ -0,0 +1,88 @@
+package com.intellij.remoteServer.deployment.impl;
+
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.packaging.artifacts.Artifact;
+import com.intellij.packaging.artifacts.ArtifactPointer;
+import com.intellij.packaging.elements.ArtifactRootElement;
+import com.intellij.packaging.elements.CompositePackagingElement;
+import com.intellij.remoteServer.deployment.ArtifactDeploymentSource;
+import com.intellij.remoteServer.deployment.DeploymentSource;
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.*;
+import java.io.File;
+
+/**
+ * @author nik
+ */
+public class ArtifactDeploymentSourceImpl implements ArtifactDeploymentSource, DeploymentSource {
+ private final ArtifactPointer myPointer;
+
+ public ArtifactDeploymentSourceImpl(@NotNull ArtifactPointer pointer) {
+ myPointer = pointer;
+ }
+
+ @NotNull
+ @Override
+ public ArtifactPointer getArtifactPointer() {
+ return myPointer;
+ }
+
+ @Override
+ public Artifact getArtifact() {
+ return myPointer.getArtifact();
+ }
+
+ @Override
+ public File getFile() {
+ final String path = getFilePath();
+ return path != null ? new File(path) : null;
+ }
+
+ @Override
+ public String getFilePath() {
+ final Artifact artifact = getArtifact();
+ if (artifact != null) {
+ String outputPath = artifact.getOutputPath();
+ if (outputPath != null) {
+ final CompositePackagingElement> rootElement = artifact.getRootElement();
+ if (!(rootElement instanceof ArtifactRootElement>)) {
+ outputPath += "/" + rootElement.getName();
+ }
+ return FileUtil.toSystemDependentName(outputPath);
+ }
+ }
+ return null;
+ }
+
+ @NotNull
+ @Override
+ public String getPresentableName() {
+ return myPointer.getArtifactName();
+ }
+
+ @Override
+ public Icon getIcon() {
+ final Artifact artifact = getArtifact();
+ return artifact != null ? artifact.getArtifactType().getIcon() : null;
+ }
+
+ @Override
+ public boolean isValid() {
+ return getArtifact() != null;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof ArtifactDeploymentSourceImpl)) return false;
+
+ return myPointer.equals(((ArtifactDeploymentSourceImpl)o).myPointer);
+
+ }
+
+ @Override
+ public int hashCode() {
+ return myPointer.hashCode();
+ }
+}
diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/deployment/impl/DeploymentSourceUtilImpl.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/deployment/impl/DeploymentSourceUtilImpl.java
new file mode 100644
index 000000000000..1acb1cba85ab
--- /dev/null
+++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/deployment/impl/DeploymentSourceUtilImpl.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2000-2013 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.remoteServer.deployment.impl;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.packaging.artifacts.ArtifactPointer;
+import com.intellij.packaging.artifacts.ArtifactPointerManager;
+import com.intellij.remoteServer.deployment.ArtifactDeploymentSource;
+import com.intellij.remoteServer.deployment.DeploymentSource;
+import com.intellij.remoteServer.deployment.DeploymentSourceUtil;
+import org.jdom.Element;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author nik
+ */
+public class DeploymentSourceUtilImpl extends DeploymentSourceUtil {
+ @NotNull
+ @Override
+ public ArtifactDeploymentSource createArtifactDeploymentSource(@NotNull ArtifactPointer artifactPointer) {
+ return new ArtifactDeploymentSourceImpl(artifactPointer);
+ }
+
+ @Override
+ public DeploymentSource loadDeploymentSource(@NotNull Element element, @NotNull Project project) {
+ ArtifactPointerManager artifactPointerManager = ArtifactPointerManager.getInstance(project);
+ Element artifact = element.getChild("artifact");
+ return createArtifactDeploymentSource(artifactPointerManager.createPointer(artifact.getAttributeValue("name")));
+ }
+
+ @Override
+ public void saveDeploymentSource(@NotNull DeploymentSource source, @NotNull Element element, @NotNull Project project) {
+ if (source instanceof ArtifactDeploymentSource) {
+ String artifactName = ((ArtifactDeploymentSource)source).getArtifactPointer().getArtifactName();
+ element.addContent(new Element("artifact").setAttribute("name", artifactName));
+ }
+ }
+}
diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/run/DeployToServerConfigurationType.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/run/DeployToServerConfigurationType.java
new file mode 100644
index 000000000000..166b6c2c464b
--- /dev/null
+++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/run/DeployToServerConfigurationType.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2000-2013 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.remoteServer.run;
+
+import com.intellij.execution.configuration.ConfigurationFactoryEx;
+import com.intellij.execution.configurations.ConfigurationTypeBase;
+import com.intellij.execution.configurations.RunConfiguration;
+import com.intellij.openapi.project.Project;
+import com.intellij.remoteServer.ServerType;
+import com.intellij.remoteServer.configuration.RemoteServer;
+import com.intellij.remoteServer.configuration.RemoteServersManager;
+import com.intellij.remoteServer.deployment.DeploymentSource;
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public class DeployToServerConfigurationType extends ConfigurationTypeBase {
+ private ServerType> myServerType;
+
+ public DeployToServerConfigurationType(ServerType> serverType) {
+ super(serverType.getId() + "-deploy", serverType.getPresentableName() + " Deployment",
+ "Deploy to " + serverType.getPresentableName() + " run configuration", serverType.getIcon());
+ addFactory(new DeployToServerConfigurationFactory());
+ myServerType = serverType;
+ }
+
+ public class DeployToServerConfigurationFactory extends ConfigurationFactoryEx {
+ public DeployToServerConfigurationFactory() {
+ super(DeployToServerConfigurationType.this);
+ }
+
+ @Override
+ public void onNewConfigurationCreated(@NotNull RunConfiguration configuration) {
+ DeployToServerRunConfiguration deployConfiguration = (DeployToServerRunConfiguration)configuration;
+ if (deployConfiguration.getServerName() == null) {
+ RemoteServer> server = ContainerUtil.getFirstItem(RemoteServersManager.getInstance().getServers(myServerType));
+ if (server != null) {
+ deployConfiguration.setServerName(server.getName());
+ }
+ }
+
+ if (deployConfiguration.getDeploymentSource() == null) {
+ List sources = deployConfiguration.getDeployer().getAvailableDeploymentSources();
+ DeploymentSource source = ContainerUtil.getFirstItem(sources);
+ if (source != null) {
+ deployConfiguration.setDeploymentSource(source);
+ }
+ }
+ }
+
+ @Override
+ public RunConfiguration createTemplateConfiguration(Project project) {
+ return new DeployToServerRunConfiguration(project, this, "", myServerType);
+ }
+ }
+}
diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/run/DeployToServerConfigurationTypesRegistrar.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/run/DeployToServerConfigurationTypesRegistrar.java
new file mode 100644
index 000000000000..422cc5c6523e
--- /dev/null
+++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/run/DeployToServerConfigurationTypesRegistrar.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2000-2013 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.remoteServer.run;
+
+import com.intellij.execution.configurations.ConfigurationType;
+import com.intellij.openapi.components.ApplicationComponent;
+import com.intellij.openapi.extensions.ExtensionPoint;
+import com.intellij.openapi.extensions.Extensions;
+import com.intellij.remoteServer.ServerType;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author nik
+ */
+public class DeployToServerConfigurationTypesRegistrar implements ApplicationComponent {
+ @Override
+ public void initComponent() {
+ //todo[nik] improve this: configuration types should be loaded lazily
+ ExtensionPoint point = Extensions.getRootArea().getExtensionPoint(ConfigurationType.CONFIGURATION_TYPE_EP);
+ for (ServerType serverType : ServerType.EP_NAME.getExtensions()) {
+ point.registerExtension(new DeployToServerConfigurationType(serverType));
+ }
+ }
+
+ @Override
+ public void disposeComponent() {
+ }
+
+ @NotNull
+ @Override
+ public String getComponentName() {
+ return "DeployToServerConfigurationTypesRegistrar";
+ }
+}
diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/run/DeployToServerRunConfiguration.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/run/DeployToServerRunConfiguration.java
new file mode 100644
index 000000000000..6ba8cf1a3068
--- /dev/null
+++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/run/DeployToServerRunConfiguration.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2000-2013 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.remoteServer.run;
+
+import com.intellij.execution.ExecutionException;
+import com.intellij.execution.Executor;
+import com.intellij.execution.configurations.ConfigurationFactory;
+import com.intellij.execution.configurations.RunConfigurationBase;
+import com.intellij.execution.configurations.RunProfileState;
+import com.intellij.execution.configurations.RuntimeConfigurationException;
+import com.intellij.execution.runners.ExecutionEnvironment;
+import com.intellij.openapi.options.SettingsEditor;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.InvalidDataException;
+import com.intellij.openapi.util.WriteExternalException;
+import com.intellij.remoteServer.ServerType;
+import com.intellij.remoteServer.configuration.RemoteServer;
+import com.intellij.remoteServer.configuration.RemoteServersManager;
+import com.intellij.remoteServer.configuration.ServerConfiguration;
+import com.intellij.remoteServer.deployment.Deployer;
+import com.intellij.remoteServer.deployment.DeploymentSource;
+import com.intellij.remoteServer.deployment.DeploymentSourceUtil;
+import org.jdom.Element;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author nik
+ */
+public class DeployToServerRunConfiguration extends RunConfigurationBase {
+ public static final String SERVER_NAME_ATTRIBUTE = "server-name";
+ public static final String SOURCE_ELEMENT = "source";
+ private final ServerType myServerType;
+ private final Deployer myDeployer;
+ private String myServerName;
+ private DeploymentSource myDeploymentSource;
+
+ public DeployToServerRunConfiguration(Project project, ConfigurationFactory factory, String name, ServerType serverType) {
+ super(project, factory, name);
+ myServerType = serverType;
+ myDeployer = myServerType.createDeployer(project);
+ }
+
+ public String getServerName() {
+ return myServerName;
+ }
+
+ @NotNull
+ public Deployer getDeployer() {
+ return myDeployer;
+ }
+
+ @Override
+ public SettingsEditor getConfigurationEditor() {
+ return new DeployToServerSettingsEditor(myServerType, myDeployer, getProject());
+ }
+
+ @Nullable
+ @Override
+ public RunProfileState getState(@NotNull Executor executor, @NotNull ExecutionEnvironment env) throws ExecutionException {
+ String serverName = getServerName();
+ if (serverName == null) {
+ throw new ExecutionException("Server is not specified");
+ }
+
+ RemoteServer server = RemoteServersManager.getInstance().findByName(serverName, myServerType);
+ if (server == null) {
+ throw new ExecutionException("Server '" + serverName + " not found");
+ }
+
+ if (myDeploymentSource == null) {
+ throw new ExecutionException("Deployment is not selected");
+ }
+
+ return new DeployToServerState(env, myDeployer, server, myDeploymentSource);
+ }
+
+ @Override
+ public void checkConfiguration() throws RuntimeConfigurationException {
+ }
+
+ public void setServerName(String serverName) {
+ myServerName = serverName;
+ }
+
+ public DeploymentSource getDeploymentSource() {
+ return myDeploymentSource;
+ }
+
+ public void setDeploymentSource(DeploymentSource deploymentSource) {
+ myDeploymentSource = deploymentSource;
+ }
+
+ @Override
+ public void readExternal(Element element) throws InvalidDataException {
+ super.readExternal(element);
+ myServerName = element.getAttributeValue(SERVER_NAME_ATTRIBUTE);
+ Element sourceElement = element.getChild(SOURCE_ELEMENT);
+ myDeploymentSource = sourceElement != null ? DeploymentSourceUtil.getInstance().loadDeploymentSource(sourceElement, getProject()) : null;
+ }
+
+ @Override
+ public void writeExternal(Element element) throws WriteExternalException {
+ if (myServerName != null) {
+ element.setAttribute(SERVER_NAME_ATTRIBUTE, myServerName);
+ }
+ if (myDeploymentSource != null) {
+ Element source = new Element(SOURCE_ELEMENT);
+ DeploymentSourceUtil.getInstance().saveDeploymentSource(myDeploymentSource, source, getProject());
+ element.addContent(source);
+ }
+ super.writeExternal(element);
+ }
+}
diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/run/DeployToServerRunner.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/run/DeployToServerRunner.java
new file mode 100644
index 000000000000..a4b9008c5183
--- /dev/null
+++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/run/DeployToServerRunner.java
@@ -0,0 +1,22 @@
+package com.intellij.remoteServer.run;
+
+import com.intellij.execution.configurations.RunProfile;
+import com.intellij.execution.executors.DefaultRunExecutor;
+import com.intellij.execution.runners.DefaultProgramRunner;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author nik
+ */
+public class DeployToServerRunner extends DefaultProgramRunner {
+ @NotNull
+ @Override
+ public String getRunnerId() {
+ return "DeployToServer";
+ }
+
+ @Override
+ public boolean canRun(@NotNull String executorId, @NotNull RunProfile profile) {
+ return executorId.equals(DefaultRunExecutor.EXECUTOR_ID) && profile instanceof DeployToServerRunConfiguration;
+ }
+}
diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/run/DeployToServerSettingsEditor.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/run/DeployToServerSettingsEditor.java
new file mode 100644
index 000000000000..a2283cb1c024
--- /dev/null
+++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/run/DeployToServerSettingsEditor.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2000-2013 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.remoteServer.run;
+
+import com.intellij.openapi.options.ConfigurationException;
+import com.intellij.openapi.options.SettingsEditor;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.ComboBox;
+import com.intellij.remoteServer.ServerType;
+import com.intellij.remoteServer.configuration.RemoteServer;
+import com.intellij.remoteServer.configuration.RemoteServersManager;
+import com.intellij.remoteServer.configuration.ServerConfiguration;
+import com.intellij.remoteServer.deployment.Deployer;
+import com.intellij.remoteServer.deployment.DeploymentSource;
+import com.intellij.ui.ColoredListCellRendererWrapper;
+import com.intellij.ui.ListCellRendererWrapper;
+import com.intellij.ui.SimpleTextAttributes;
+import com.intellij.ui.SortedComboBoxModel;
+import com.intellij.util.ui.FormBuilder;
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.*;
+import java.util.Comparator;
+
+/**
+ * @author nik
+ */
+public class DeployToServerSettingsEditor extends SettingsEditor {
+ private ComboBox myServerComboBox;
+ private ComboBox mySourceComboBox;
+ private final SortedComboBoxModel myServerListModel;
+ private final SortedComboBoxModel mySourceListModel;
+
+ public DeployToServerSettingsEditor(final ServerType> type, Deployer deployer, Project project) {
+ myServerListModel = new SortedComboBoxModel(String.CASE_INSENSITIVE_ORDER);
+ for (RemoteServer extends ServerConfiguration> server : RemoteServersManager.getInstance().getServers(type)) {
+ myServerListModel.add(server.getName());
+ }
+
+ myServerComboBox = new ComboBox(myServerListModel);
+ myServerComboBox.setRenderer(new ColoredListCellRendererWrapper() {
+ @Override
+ protected void doCustomize(JList list, String value, int index, boolean selected, boolean hasFocus) {
+ if (value == null) return;
+ SimpleTextAttributes attributes = RemoteServersManager.getInstance().findByName(value, type) == null
+ ? SimpleTextAttributes.ERROR_ATTRIBUTES : SimpleTextAttributes.REGULAR_ATTRIBUTES;
+ append(value, attributes);
+ }
+ });
+
+ mySourceListModel = new SortedComboBoxModel(new Comparator() {
+ @Override
+ public int compare(DeploymentSource o1, DeploymentSource o2) {
+ return o1.getPresentableName().compareToIgnoreCase(o2.getPresentableName());
+ }
+ });
+ mySourceListModel.addAll(deployer.getAvailableDeploymentSources());
+ mySourceComboBox = new ComboBox(mySourceListModel);
+ mySourceComboBox.setRenderer(new ListCellRendererWrapper() {
+ @Override
+ public void customize(JList list, DeploymentSource value, int index, boolean selected, boolean hasFocus) {
+ if (value == null) return;
+ setIcon(value.getIcon());
+ setText(value.getPresentableName());
+ }
+ });
+ }
+
+ @Override
+ protected void resetEditorFrom(DeployToServerRunConfiguration configuration) {
+ String serverName = configuration.getServerName();
+ if (serverName != null && !myServerListModel.getItems().contains(serverName)) {
+ myServerListModel.add(serverName);
+ }
+ myServerComboBox.setSelectedItem(serverName);
+ mySourceComboBox.setSelectedItem(configuration.getDeploymentSource());
+ }
+
+ @Override
+ protected void applyEditorTo(DeployToServerRunConfiguration configuration) throws ConfigurationException {
+ configuration.setServerName(myServerListModel.getSelectedItem());
+ configuration.setDeploymentSource(mySourceListModel.getSelectedItem());
+ }
+
+ @NotNull
+ @Override
+ protected JComponent createEditor() {
+ return FormBuilder.createFormBuilder()
+ .addLabeledComponent("Server:", myServerComboBox)
+ .addLabeledComponent("Deployment:", mySourceComboBox)
+ .getPanel();
+ }
+
+ @Override
+ protected void disposeEditor() {
+
+ }
+}
diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/run/DeployToServerState.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/run/DeployToServerState.java
new file mode 100644
index 000000000000..ec88486bcdcb
--- /dev/null
+++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/run/DeployToServerState.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2000-2013 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.remoteServer.run;
+
+import com.intellij.execution.ExecutionException;
+import com.intellij.execution.ExecutionResult;
+import com.intellij.execution.Executor;
+import com.intellij.execution.configurations.ConfigurationPerRunnerSettings;
+import com.intellij.execution.configurations.RunProfileState;
+import com.intellij.execution.configurations.RunnerSettings;
+import com.intellij.execution.runners.ExecutionEnvironment;
+import com.intellij.execution.runners.ProgramRunner;
+import com.intellij.remoteServer.configuration.RemoteServer;
+import com.intellij.remoteServer.configuration.ServerConfiguration;
+import com.intellij.remoteServer.deployment.Deployer;
+import com.intellij.remoteServer.deployment.DeploymentSource;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author nik
+ */
+public class DeployToServerState implements RunProfileState {
+ private final ExecutionEnvironment myExecutionEnvironment;
+ @NotNull private final Deployer myDeployer;
+ @NotNull private final RemoteServer myServer;
+ @NotNull private final DeploymentSource mySource;
+
+ public DeployToServerState(@NotNull ExecutionEnvironment executionEnvironment,
+ @NotNull Deployer deployer,
+ @NotNull RemoteServer server,
+ @NotNull DeploymentSource deploymentSource) {
+ myExecutionEnvironment = executionEnvironment;
+ myDeployer = deployer;
+ myServer = server;
+ mySource = deploymentSource;
+ }
+
+ @Nullable
+ @Override
+ public ExecutionResult execute(Executor executor, @NotNull ProgramRunner runner) throws ExecutionException {
+ myDeployer.startDeployment(myServer, mySource);
+ return null;
+ }
+
+ @Override
+ public RunnerSettings getRunnerSettings() {
+ return myExecutionEnvironment.getRunnerSettings();
+ }
+
+ @Override
+ public ConfigurationPerRunnerSettings getConfigurationSettings() {
+ return myExecutionEnvironment.getConfigurationSettings();
+ }
+}
diff --git a/plugins/google-app-engine/google-app-engine.iml b/plugins/google-app-engine/google-app-engine.iml
index 52217861ad17..ab104003fd25 100644
--- a/plugins/google-app-engine/google-app-engine.iml
+++ b/plugins/google-app-engine/google-app-engine.iml
@@ -24,6 +24,7 @@
+
diff --git a/plugins/google-app-engine/resources/META-INF/google-app-engine-plugin.xml b/plugins/google-app-engine/resources/META-INF/google-app-engine-plugin.xml
index 9ce7afc50bb8..c8853454480d 100644
--- a/plugins/google-app-engine/resources/META-INF/google-app-engine-plugin.xml
+++ b/plugins/google-app-engine/resources/META-INF/google-app-engine-plugin.xml
@@ -22,6 +22,8 @@
+
+
diff --git a/plugins/google-app-engine/source/com/intellij/appengine/actions/AppEngineUploader.java b/plugins/google-app-engine/source/com/intellij/appengine/actions/AppEngineUploader.java
index a6dc462fa684..2e7dae2262ea 100644
--- a/plugins/google-app-engine/source/com/intellij/appengine/actions/AppEngineUploader.java
+++ b/plugins/google-app-engine/source/com/intellij/appengine/actions/AppEngineUploader.java
@@ -16,6 +16,7 @@
package com.intellij.appengine.actions;
import com.intellij.CommonBundle;
+import com.intellij.appengine.cloud.AppEngineServerConfiguration;
import com.intellij.appengine.descriptor.dom.AppEngineWebApp;
import com.intellij.appengine.facet.AppEngineAccountDialog;
import com.intellij.appengine.facet.AppEngineFacet;
@@ -105,7 +106,9 @@ public class AppEngineUploader {
}
@Nullable
- public static AppEngineUploader createUploader(@NotNull Project project, @NotNull Artifact artifact) {
+ public static AppEngineUploader createUploader(@NotNull Project project,
+ @NotNull Artifact artifact,
+ @Nullable AppEngineServerConfiguration configuration) {
final String explodedPath = artifact.getOutputPath();
if (explodedPath == null) {
Messages.showErrorDialog(project, "Output path isn't specified for '" + artifact.getName() + "' artifact", CommonBundle.getErrorTitle());
@@ -150,7 +153,7 @@ public class AppEngineUploader {
String password = null;
String email = null;
try {
- email = AppEngineAccountDialog.getStoredEmail(project);
+ email = AppEngineAccountDialog.getStoredEmail(configuration, project);
password = AppEngineAccountDialog.getStoredPassword(project, email);
}
catch (PasswordSafeException e) {
@@ -158,7 +161,7 @@ public class AppEngineUploader {
LOG.info(e);
}
if (StringUtil.isEmpty(email) || StringUtil.isEmpty(password)) {
- final AppEngineAccountDialog dialog = new AppEngineAccountDialog(project);
+ final AppEngineAccountDialog dialog = new AppEngineAccountDialog(project, configuration);
dialog.show();
if (!dialog.isOK()) return null;
diff --git a/plugins/google-app-engine/source/com/intellij/appengine/actions/UploadApplicationAction.java b/plugins/google-app-engine/source/com/intellij/appengine/actions/UploadApplicationAction.java
index df6daaf5cbd3..15fb4051d1db 100644
--- a/plugins/google-app-engine/source/com/intellij/appengine/actions/UploadApplicationAction.java
+++ b/plugins/google-app-engine/source/com/intellij/appengine/actions/UploadApplicationAction.java
@@ -57,7 +57,7 @@ public class UploadApplicationAction extends AnAction {
return;
}
}
- final AppEngineUploader uploader = AppEngineUploader.createUploader(project, artifact);
+ final AppEngineUploader uploader = AppEngineUploader.createUploader(project, artifact, null);
if (uploader != null) {
uploader.startUploading();
}
diff --git a/plugins/google-app-engine/source/com/intellij/appengine/cloud/AppEngineCloudType.java b/plugins/google-app-engine/source/com/intellij/appengine/cloud/AppEngineCloudType.java
new file mode 100644
index 000000000000..d90d1f20b103
--- /dev/null
+++ b/plugins/google-app-engine/source/com/intellij/appengine/cloud/AppEngineCloudType.java
@@ -0,0 +1,147 @@
+/*
+ * Copyright 2000-2013 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.appengine.cloud;
+
+import com.intellij.appengine.actions.AppEngineUploader;
+import com.intellij.appengine.util.AppEngineUtil;
+import com.intellij.openapi.options.ConfigurationException;
+import com.intellij.openapi.options.UnnamedConfigurable;
+import com.intellij.openapi.project.Project;
+import com.intellij.packaging.artifacts.Artifact;
+import com.intellij.packaging.artifacts.ArtifactPointerManager;
+import com.intellij.remoteServer.ServerType;
+import com.intellij.remoteServer.configuration.RemoteServer;
+import com.intellij.remoteServer.deployment.ArtifactDeploymentSource;
+import com.intellij.remoteServer.deployment.Deployer;
+import com.intellij.remoteServer.deployment.DeploymentSource;
+import com.intellij.remoteServer.deployment.DeploymentSourceUtil;
+import com.intellij.util.ui.FormBuilder;
+import icons.GoogleAppEngineIcons;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.awt.*;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public class AppEngineCloudType extends ServerType {
+
+ public AppEngineCloudType() {
+ super("google-app-engine");
+ }
+
+ @NotNull
+ @Override
+ public String getPresentableName() {
+ return "Google App Engine";
+ }
+
+ @NotNull
+ @Override
+ public Icon getIcon() {
+ return GoogleAppEngineIcons.AppEngine;
+ }
+
+ @NotNull
+ @Override
+ public AppEngineServerConfiguration createDefaultConfiguration() {
+ return new AppEngineServerConfiguration();
+ }
+
+ @NotNull
+ @Override
+ public UnnamedConfigurable createConfigurable(@NotNull AppEngineServerConfiguration configuration) {
+ return new AppEngineCloudConfigurable(configuration);
+ }
+
+ @NotNull
+ @Override
+ public Deployer createDeployer(Project project) {
+ return new AppEngineDeployer(project);
+ }
+
+ private static class AppEngineCloudConfigurable implements UnnamedConfigurable {
+ private final JTextField myEmailField;
+ private final AppEngineServerConfiguration myConfiguration;
+
+ public AppEngineCloudConfigurable(AppEngineServerConfiguration configuration) {
+ myConfiguration = configuration;
+ myEmailField = new JTextField();
+ myEmailField.setPreferredSize(new Dimension(250, myEmailField.getPreferredSize().height));
+ }
+
+ @Nullable
+ @Override
+ public JComponent createComponent() {
+ return FormBuilder.createFormBuilder().addLabeledComponent("E-mail:", myEmailField).getPanel();
+ }
+
+ @Override
+ public boolean isModified() {
+ return !myEmailField.getText().equals(myConfiguration.getEmail());
+ }
+
+ @Override
+ public void apply() throws ConfigurationException {
+ myConfiguration.setEmail(myEmailField.getText());
+ }
+
+ @Override
+ public void reset() {
+ myEmailField.setText(myConfiguration.getEmail());
+ }
+
+ @Override
+ public void disposeUIResources() {
+ }
+ }
+
+ private static class AppEngineDeployer extends Deployer {
+ private final Project myProject;
+
+ public AppEngineDeployer(Project project) {
+ myProject = project;
+ }
+
+ @NotNull
+ @Override
+ public List getAvailableDeploymentSources() {
+ List artifacts = AppEngineUtil.collectWebArtifacts(myProject, true);
+ List sources = new ArrayList();
+ ArtifactPointerManager pointerManager = ArtifactPointerManager.getInstance(myProject);
+ for (Artifact artifact : artifacts) {
+ sources.add(DeploymentSourceUtil.getInstance().createArtifactDeploymentSource(pointerManager.createPointer(artifact)));
+ }
+ return sources;
+ }
+
+ @Override
+ public void startDeployment(@NotNull RemoteServer server,
+ @NotNull DeploymentSource source) {
+ Artifact artifact = ((ArtifactDeploymentSource)source).getArtifact();
+ if (artifact == null) return;
+
+ AppEngineUploader uploader = AppEngineUploader.createUploader(myProject, artifact, server.getConfiguration());
+ if (uploader != null) {
+ uploader.startUploading();
+ }
+ }
+ }
+}
diff --git a/plugins/google-app-engine/source/com/intellij/appengine/cloud/AppEngineServerConfiguration.java b/plugins/google-app-engine/source/com/intellij/appengine/cloud/AppEngineServerConfiguration.java
new file mode 100644
index 000000000000..9291f376fc7d
--- /dev/null
+++ b/plugins/google-app-engine/source/com/intellij/appengine/cloud/AppEngineServerConfiguration.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2000-2013 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.appengine.cloud;
+
+import com.intellij.openapi.components.PersistentStateComponent;
+import com.intellij.remoteServer.configuration.ServerConfiguration;
+import com.intellij.util.xmlb.XmlSerializerUtil;
+import com.intellij.util.xmlb.annotations.Attribute;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author nik
+ */
+public class AppEngineServerConfiguration extends ServerConfiguration implements PersistentStateComponent {
+ private String myEmail;
+
+ @Attribute("email")
+ public String getEmail() {
+ return myEmail;
+ }
+
+ public void setEmail(String email) {
+ myEmail = email;
+ }
+
+ @Nullable
+ @Override
+ public AppEngineServerConfiguration getState() {
+ return this;
+ }
+
+ @Override
+ public void loadState(AppEngineServerConfiguration state) {
+ XmlSerializerUtil.copyBean(state, this);
+ }
+
+ @Override
+ public PersistentStateComponent> getSerializer() {
+ return this;
+ }
+}
diff --git a/plugins/google-app-engine/source/com/intellij/appengine/facet/AppEngineAccountDialog.java b/plugins/google-app-engine/source/com/intellij/appengine/facet/AppEngineAccountDialog.java
index df9222554dcc..3e4cda649855 100644
--- a/plugins/google-app-engine/source/com/intellij/appengine/facet/AppEngineAccountDialog.java
+++ b/plugins/google-app-engine/source/com/intellij/appengine/facet/AppEngineAccountDialog.java
@@ -16,6 +16,7 @@
package com.intellij.appengine.facet;
import com.intellij.CommonBundle;
+import com.intellij.appengine.cloud.AppEngineServerConfiguration;
import com.intellij.ide.passwordSafe.PasswordSafe;
import com.intellij.ide.passwordSafe.PasswordSafeException;
import com.intellij.ide.util.PropertiesComponent;
@@ -39,12 +40,14 @@ public class AppEngineAccountDialog extends DialogWrapper {
private JPasswordField myPasswordField;
private JTextField myUserEmailField;
private final Project myProject;
+ @Nullable private final AppEngineServerConfiguration myConfiguration;
- public AppEngineAccountDialog(@NotNull Project project) {
+ public AppEngineAccountDialog(@NotNull Project project, @Nullable AppEngineServerConfiguration configuration) {
super(project);
myProject = project;
+ myConfiguration = configuration;
setTitle("AppEngine Account");
- myUserEmailField.setText(StringUtil.notNullize(getStoredEmail(project)));
+ myUserEmailField.setText(StringUtil.notNullize(getStoredEmail(myConfiguration, project)));
init();
}
@@ -67,14 +70,22 @@ public class AppEngineAccountDialog extends DialogWrapper {
}
@Nullable
- public static String getStoredEmail(@NotNull Project project) {
- return PropertiesComponent.getInstance(project).getValue(EMAIL_KEY);
+ public static String getStoredEmail(@Nullable AppEngineServerConfiguration configuration, @NotNull Project project) {
+ if (configuration != null) {
+ return configuration.getEmail();
+ }
+ return PropertiesComponent.getInstance(project).getValue(EMAIL_KEY);//todo[nik] remove this
}
@Override
protected void doOKAction() {
final String email = getEmail();
- PropertiesComponent.getInstance(myProject).setValue(EMAIL_KEY, email);
+ if (myConfiguration != null) {
+ myConfiguration.setEmail(email);
+ }
+ else {
+ PropertiesComponent.getInstance(myProject).setValue(EMAIL_KEY, email);
+ }
if (myRememberPasswordCheckBox.isSelected()) {
try {
PasswordSafe.getInstance().storePassword(myProject, AppEngineAccountDialog.class, getPasswordKey(email), getPassword());
diff --git a/resources/src/idea/RichPlatformPlugin.xml b/resources/src/idea/RichPlatformPlugin.xml
index a2c79d736efb..dcb2acda4d18 100644
--- a/resources/src/idea/RichPlatformPlugin.xml
+++ b/resources/src/idea/RichPlatformPlugin.xml
@@ -385,6 +385,7 @@
+