diff --git a/tcwebhooks-core/src/main/java/webhook/teamcity/payload/format/WebHookPayloadNameValuePairsTemplate.java b/tcwebhooks-core/src/main/java/webhook/teamcity/payload/format/WebHookPayloadNameValuePairsTemplate.java new file mode 100644 index 00000000..96f955d3 --- /dev/null +++ b/tcwebhooks-core/src/main/java/webhook/teamcity/payload/format/WebHookPayloadNameValuePairsTemplate.java @@ -0,0 +1,116 @@ +package webhook.teamcity.payload.format; + +import java.io.IOException; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.List; + +import org.apache.http.NameValuePair; +import org.apache.http.client.utils.URLEncodedUtils; +import org.apache.http.message.BasicNameValuePair; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + +import webhook.teamcity.payload.PayloadTemplateEngineType; +import webhook.teamcity.payload.WebHookContentObjectSerialiser; +import webhook.teamcity.payload.WebHookPayload; +import webhook.teamcity.payload.WebHookPayloadManager; +import webhook.teamcity.payload.WebHookTemplateContent; +import webhook.teamcity.payload.content.WebHookPayloadContent; +import webhook.teamcity.payload.content.WebHookPayloadContentAssemblyException; +import webhook.teamcity.payload.template.render.WebHookStringRenderer; +import webhook.teamcity.payload.template.render.WwwFormUrlEncodedToHtmlPrettyPrintingRenderer; +import webhook.teamcity.payload.variableresolver.VariableMessageBuilder; +import webhook.teamcity.payload.variableresolver.WebHookVariableResolverManager; + +public class WebHookPayloadNameValuePairsTemplate extends WebHookPayloadGeneric implements WebHookPayload, WebHookContentObjectSerialiser { + + public static final String FORMAT_SHORT_NAME = "nvpairsTemplate"; + public static final String FORMAT_CONTENT_TYPE = "application/x-www-form-urlencoded"; + + Integer rank = 101; + String charset = "UTF-8"; + + Gson gson = new GsonBuilder().create(); + + public WebHookPayloadNameValuePairsTemplate(WebHookPayloadManager manager, WebHookVariableResolverManager variableResolverManager){ + super(manager, variableResolverManager); + } + + @Override + public void register(){ + myManager.registerPayloadFormat(this); + } + + @Override + public String getFormatDescription() { + return "Name Value Pairs - urlencoded (standard template)"; + } + + @Override + public String getFormatShortName() { + return FORMAT_SHORT_NAME; + } + + @Override + public String getFormatToolTipText() { + return "Send a x-www-form-urlencoded payload with content from a standard template"; + } + + @Override + protected String getStatusAsString(WebHookPayloadContent content, WebHookTemplateContent webHookTemplateContent){ + VariableMessageBuilder builder = this.myVariableResolverFactory.createVariableMessageBuilder(webHookTemplateContent.getTemplateText(), this.myVariableResolverFactory.buildVariableResolver(this, content, content.getAllParameters())); + try { + return URLEncodedUtils.format(parseToNvPairs(builder.build()), Charset.forName(getCharset())); + } catch (IOException ex) { + throw new WebHookPayloadContentAssemblyException("Failed to parse template input. Check the input is correct"); + } + } + + @Override + public String getContentType() { + return FORMAT_CONTENT_TYPE; + } + + @Override + public Integer getRank() { + return this.rank; + } + + @Override + public void setRank(Integer rank) { + this.rank = rank; + } + + @Override + public String getCharset() { + return this.charset; + } + + @Override + public WebHookStringRenderer getWebHookStringRenderer() { + return new WwwFormUrlEncodedToHtmlPrettyPrintingRenderer(); + } + + @Override + public Object serialiseObject(Object object) { + return object; + } + + @Override + public PayloadTemplateEngineType getTemplateEngineType() { + return PayloadTemplateEngineType.STANDARD; + } + + public List parseToNvPairs(String s) throws IOException { + List nvPairs = new ArrayList<>(); + for (String line : s.split("\n")) { + if (! line.trim().isEmpty()) { + String[] item = line.trim().split("=", 2); + nvPairs.add(new BasicNameValuePair(item[0], item[1])); + } + } + return nvPairs; + } +} diff --git a/tcwebhooks-core/src/test/java/webhook/teamcity/payload/template/NameValuePairsTemplateRenderingTest.java b/tcwebhooks-core/src/test/java/webhook/teamcity/payload/template/NameValuePairsTemplateRenderingTest.java new file mode 100644 index 00000000..b30fa7fe --- /dev/null +++ b/tcwebhooks-core/src/test/java/webhook/teamcity/payload/template/NameValuePairsTemplateRenderingTest.java @@ -0,0 +1,86 @@ +package webhook.teamcity.payload.template; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.util.Date; +import java.util.SortedMap; +import java.util.TreeMap; + +import jetbrains.buildServer.messages.Status; +import jetbrains.buildServer.serverSide.SBuildServer; +import jetbrains.buildServer.serverSide.SFinishedBuild; + +import org.junit.Test; + +import webhook.teamcity.BuildStateEnum; +import webhook.teamcity.MockSBuildType; +import webhook.teamcity.MockSProject; +import webhook.teamcity.MockSRunningBuild; +import webhook.teamcity.payload.WebHookPayloadDefaultTemplates; +import webhook.teamcity.payload.WebHookPayloadManager; +import webhook.teamcity.payload.WebHookTemplateManager; +import webhook.teamcity.payload.content.WebHookPayloadContentAssemblyException; +import webhook.teamcity.payload.format.WebHookPayloadNameValuePairsTemplate; +import webhook.teamcity.payload.template.render.WebHookStringRenderer.WebHookHtmlRendererException; +import webhook.teamcity.payload.variableresolver.WebHookVariableResolverManager; +import webhook.teamcity.payload.variableresolver.WebHookVariableResolverManagerImpl; +import webhook.teamcity.payload.variableresolver.standard.WebHooksBeanUtilsVariableResolverFactory; +import webhook.teamcity.settings.entity.WebHookTemplateJaxHelperImpl; +import webhook.teamcity.settings.entity.WebHookTemplateJaxTestHelper; + +public class NameValuePairsTemplateRenderingTest { + + SBuildServer mockServer = mock(SBuildServer.class); + WebHookTemplateManager wtm; + WebHookPayloadManager wpm = new WebHookPayloadManager(mockServer); + WebHookTemplateJaxHelperImpl webHookTemplateJaxHelper = new WebHookTemplateJaxTestHelper(); + + @Test + public void TestNvPairsTemplatesWithHtmlRenderer() throws WebHookHtmlRendererException, WebHookPayloadContentAssemblyException { + when(mockServer.getRootUrl()).thenReturn("http://test.url"); + wtm = new WebHookTemplateManager(null, null); + AbstractXmlBasedWebHookTemplate wht = new TestNvPairsXmlTemplate(wtm, wpm, webHookTemplateJaxHelper); + wht.register(); + + MockSBuildType sBuildType = new MockSBuildType("Test Build", "A Test Build", "bt1"); + String triggeredBy = "SubVersion"; + MockSRunningBuild sRunningBuild = new MockSRunningBuild(sBuildType, triggeredBy, Status.NORMAL, "Running", "TestBuild01"); + SFinishedBuild previousBuild = mock(SFinishedBuild.class); + when (previousBuild.getFinishDate()).thenReturn(new Date()); + MockSProject sProject = new MockSProject("Test Project", "A test project", "project1", "ATestProject", sBuildType); + sBuildType.setProject(sProject); + SBuildServer mockServer = mock(SBuildServer.class); + when(mockServer.getRootUrl()).thenReturn("http://test.url"); + + WebHookVariableResolverManager variableResolverManager = new WebHookVariableResolverManagerImpl(); + variableResolverManager.registerVariableResolverFactory(new WebHooksBeanUtilsVariableResolverFactory()); + + + WebHookPayloadManager wpm = new WebHookPayloadManager(mockServer); + WebHookPayloadNameValuePairsTemplate whp = new WebHookPayloadNameValuePairsTemplate(wpm, variableResolverManager); + whp.register(); + SortedMap extraParameters = new TreeMap<>(); + + extraParameters.put("item1", "content1"); + extraParameters.put("item2", "content2"); + extraParameters.put("item3", "content3"); + extraParameters.put("item4", "content4"); + extraParameters.put("item5", "content5"); + extraParameters.put("item6", "This is a $weird string with % and ' and # and stuff"); + + + + //WebHookPayloadContent content = new WebHookPayloadContent(mockServer, sRunningBuild, previousBuild, BuildStateEnum.BUILD_SUCCESSFUL, extraParameters, extraParameters, WebHookPayloadDefaultTemplates.getDefaultEnabledPayloadTemplates()); + String result = whp.buildFinished(sRunningBuild, previousBuild, extraParameters, WebHookPayloadDefaultTemplates.getDefaultEnabledPayloadTemplates(), wht.getBranchTemplateForState(BuildStateEnum.BUILD_SUCCESSFUL)); + System.out.println("Template instance: " + wht.getBranchTemplateForState(BuildStateEnum.BUILD_SUCCESSFUL)); + System.out.println("Template content: " + whp.getWebHookStringRenderer().render(wht.getBranchTemplateForState(BuildStateEnum.BUILD_SUCCESSFUL).getTemplateText())); + System.out.println("Result: " + result); + System.out.println("Rendered result: " + whp.getWebHookStringRenderer().render(result)); + + assertEquals(result, "content3=content4&bar=foo&content5=This+is+a+%24weird+string+with+%25+and+%27+and+%23+and+stuff"); + + } + +} diff --git a/tcwebhooks-core/src/test/java/webhook/teamcity/payload/template/TestNvPairsXmlTemplate.java b/tcwebhooks-core/src/test/java/webhook/teamcity/payload/template/TestNvPairsXmlTemplate.java new file mode 100644 index 00000000..4ef0c97e --- /dev/null +++ b/tcwebhooks-core/src/test/java/webhook/teamcity/payload/template/TestNvPairsXmlTemplate.java @@ -0,0 +1,27 @@ +package webhook.teamcity.payload.template; + +import webhook.teamcity.payload.WebHookPayloadManager; +import webhook.teamcity.payload.WebHookTemplateManager; +import webhook.teamcity.settings.entity.WebHookTemplateJaxHelper; + +public class TestNvPairsXmlTemplate extends AbstractXmlBasedWebHookTemplate { + + private static final String CONF_PROPERTIES = "webhook/teamcity/payload/template/TestNVPairsTemplate.xml"; + + + public TestNvPairsXmlTemplate(WebHookTemplateManager templateManager, WebHookPayloadManager payloadManager, + WebHookTemplateJaxHelper webHookTemplateJaxHelper) { + super(templateManager, payloadManager, webHookTemplateJaxHelper); + } + + @Override + public String getXmlFileName() { + return CONF_PROPERTIES; + } + + @Override + public String getLoggingName() { + return "TestNvPairsXmlTemplate"; + } + +} diff --git a/tcwebhooks-core/src/test/resources/webhook/teamcity/payload/template/TestNVPairsTemplate.xml b/tcwebhooks-core/src/test/resources/webhook/teamcity/payload/template/TestNVPairsTemplate.xml new file mode 100644 index 00000000..31c7a88c --- /dev/null +++ b/tcwebhooks-core/src/test/resources/webhook/teamcity/payload/template/TestNVPairsTemplate.xml @@ -0,0 +1,31 @@ + + + Microsoft Teams (light) + A template for Microsoft Teams. Has a different look + and feel. + + + + + + \ No newline at end of file