Skip to content

Commit 757afec

Browse files
Merge pull request #453 from chathuranga-jayanath-99/handle-adding-new-properties
Handle adding new properties to the POM
2 parents 113aa3a + 818c6b4 commit 757afec

File tree

8 files changed

+214
-0
lines changed

8 files changed

+214
-0
lines changed

org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/SynapseLanguageService.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@
7777
import org.eclipse.lemminx.customservice.synapse.parser.OverviewPageDetailsResponse;
7878
import org.eclipse.lemminx.customservice.synapse.parser.UpdateConfigRequest;
7979
import org.eclipse.lemminx.customservice.synapse.parser.UpdateDependencyRequest;
80+
import org.eclipse.lemminx.customservice.synapse.parser.UpdatePropertyRequest;
8081
import org.eclipse.lemminx.customservice.synapse.parser.UpdateResponse;
8182
import org.eclipse.lemminx.customservice.synapse.parser.config.ConfigParser;
8283
import org.eclipse.lemminx.customservice.synapse.parser.config.ConfigurableEntry;
@@ -642,6 +643,12 @@ public CompletableFuture<SignatureHelp> signatureHelp(ExpressionParam params) {
642643
return CompletableFuture.supplyAsync(() -> ExpressionSignatureProvider.getFunctionSignatures(params));
643644
}
644645

646+
@Override
647+
public CompletableFuture<UpdateResponse> updateProperty(UpdatePropertyRequest request) {
648+
UpdateResponse response = PomParser.updateProperty(projectUri, request);
649+
return CompletableFuture.supplyAsync(() -> response);
650+
}
651+
645652
@Override
646653
public CompletableFuture<UpdateResponse> updateDependency(UpdateDependencyRequest request) {
647654
UpdateResponse response = PomParser.updateDependency(projectUri, request);

org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/customservice/ISynapseLanguageService.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@
6363
import org.eclipse.lemminx.customservice.synapse.parser.OverviewPageDetailsResponse;
6464
import org.eclipse.lemminx.customservice.synapse.parser.UpdateConfigRequest;
6565
import org.eclipse.lemminx.customservice.synapse.parser.UpdateDependencyRequest;
66+
import org.eclipse.lemminx.customservice.synapse.parser.UpdatePropertyRequest;
6667
import org.eclipse.lemminx.customservice.synapse.parser.UpdateResponse;
6768
import org.eclipse.lemminx.customservice.synapse.parser.config.ConfigurableEntry;
6869
import org.eclipse.lemminx.customservice.synapse.resourceFinder.ResourceUsagesRequest;
@@ -229,6 +230,9 @@ public interface ISynapseLanguageService {
229230
@JsonRequest
230231
CompletableFuture<OverviewPageDetailsResponse> getOverviewPageDetails();
231232

233+
@JsonRequest
234+
CompletableFuture<UpdateResponse> updateProperty(UpdatePropertyRequest request);
235+
232236
@JsonRequest
233237
CompletableFuture<UpdateResponse> updateDependency(UpdateDependencyRequest request);
234238

org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/customservice/synapse/parser/BuildDetails.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,24 @@
1616
public class BuildDetails {
1717

1818
private AdvanceDetails advanceDetails;
19+
private Node enableFatCar;
1920
private DockerDetails dockerDetails;
2021

2122
BuildDetails() {
2223
advanceDetails = new AdvanceDetails();
2324
dockerDetails = new DockerDetails();
2425
}
2526

27+
public Node getEnableFatCar() {
28+
29+
return enableFatCar;
30+
}
31+
32+
public void setEnableFatCar(Node enableFatCar) {
33+
34+
this.enableFatCar = enableFatCar;
35+
}
36+
2637
public AdvanceDetails getAdvanceDetails() {
2738
return this.advanceDetails;
2839
}

org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/customservice/synapse/parser/Constants.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ private Constants() { }
6363
public static final String ZIP = "zip";
6464
public static final String CAR = "car";
6565
public static final String DOCKER_FILE_BASE_IMAGE = "dockerfile.base.image";
66+
public static final String FAT_CAR_ENABLE = "fat.car.enable";
6667
public static final String CIPHER_TOOL_ENABLE = "ciphertool.enable";
6768
public static final String KEY_STORE_ALIAS = "keystore.alias";
6869
public static final String KEY_STORE_PASSWORD = "keystore.password";
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/*
2+
* Copyright (c) 2025, WSO2 LLC. (http://www.wso2.com).
3+
*
4+
* All rights reserved. This program and the accompanying materials
5+
* are made available under the terms of the Eclipse Public License v2.0
6+
* which accompanies this distribution, and is available at
7+
* http://www.eclipse.org/legal/epl-v20.html
8+
*
9+
* SPDX-License-Identifier: EPL-2.0
10+
*
11+
* Contributors:
12+
* WSO2 LLC - support for WSO2 Micro Integrator Configuration
13+
*/
14+
15+
package org.eclipse.lemminx.customservice.synapse.parser;
16+
17+
import org.eclipse.lsp4j.Range;
18+
19+
public class PropertyDetails {
20+
21+
private String name;
22+
private String value;
23+
private Range range;
24+
25+
public String getName() {
26+
27+
return name;
28+
}
29+
30+
public void setName(String name) {
31+
32+
this.name = name;
33+
}
34+
35+
public String getValue() {
36+
37+
return value;
38+
}
39+
40+
public void setValue(String value) {
41+
42+
this.value = value;
43+
}
44+
45+
public Range getRange() {
46+
47+
return range;
48+
}
49+
50+
public void setRange(Range range) {
51+
52+
this.range = range;
53+
}
54+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/*
2+
* Copyright (c) 2025, WSO2 LLC. (http://www.wso2.com).
3+
*
4+
* All rights reserved. This program and the accompanying materials
5+
* are made available under the terms of the Eclipse Public License v2.0
6+
* which accompanies this distribution, and is available at
7+
* http://www.eclipse.org/legal/epl-v20.html
8+
*
9+
* SPDX-License-Identifier: EPL-2.0
10+
*
11+
* Contributors:
12+
* WSO2 LLC - support for WSO2 Micro Integrator Configuration
13+
*/
14+
15+
package org.eclipse.lemminx.customservice.synapse.parser;
16+
17+
import java.util.List;
18+
19+
public class UpdatePropertyRequest {
20+
21+
public List<PropertyDetails> properties;
22+
}

org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/customservice/synapse/parser/pom/PluginHandler.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,8 @@ private void processProperties(String qName, String value, int valueStartLine, i
262262
pomDetailsResponse.getBuildDetails().getDockerDetails().
263263
setKeyStoreAlias(new Node(value, Either.forLeft(range)));
264264
break;
265+
case Constants.FAT_CAR_ENABLE: pomDetailsResponse.getBuildDetails().setEnableFatCar(
266+
new Node(value, Either.forLeft(range)));
265267
case Constants.CIPHER_TOOL_ENABLE:
266268
pomDetailsResponse.getBuildDetails().getDockerDetails().setCipherToolEnable(
267269
new Node(value, Either.forLeft(range)));

org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/customservice/synapse/parser/pom/PomParser.java

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@
1919
import org.eclipse.lemminx.customservice.synapse.parser.DeployPluginDetails;
2020
import org.eclipse.lemminx.customservice.synapse.parser.DependencyDetails;
2121
import org.eclipse.lemminx.customservice.synapse.parser.OverviewPageDetailsResponse;
22+
import org.eclipse.lemminx.customservice.synapse.parser.PropertyDetails;
2223
import org.eclipse.lemminx.customservice.synapse.parser.UpdateDependencyRequest;
24+
import org.eclipse.lemminx.customservice.synapse.parser.UpdatePropertyRequest;
2325
import org.eclipse.lemminx.customservice.synapse.parser.UpdateResponse;
2426
import org.eclipse.lemminx.customservice.synapse.utils.Constant;
2527
import org.eclipse.lsp4j.Position;
@@ -37,6 +39,7 @@
3739
import javax.xml.parsers.SAXParser;
3840
import javax.xml.parsers.SAXParserFactory;
3941
import javax.xml.stream.Location;
42+
import javax.xml.stream.XMLInputFactory;
4043
import javax.xml.stream.XMLStreamConstants;
4144
import javax.xml.stream.XMLStreamException;
4245
import javax.xml.stream.XMLStreamReader;
@@ -52,6 +55,8 @@
5255
import java.io.StringReader;
5356
import java.io.StringWriter;
5457
import java.nio.file.Files;
58+
import java.util.ArrayDeque;
59+
import java.util.Deque;
5560
import java.util.List;
5661
import java.util.logging.Level;
5762
import java.util.logging.Logger;
@@ -63,12 +68,52 @@ public class PomParser {
6368
private static DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
6469
private static TransformerFactory transformerFactory = TransformerFactory.newInstance();
6570
private static boolean hasDependencies = false;
71+
private static boolean hasProperties = false;
6672

6773
public static void getPomDetails(String projectUri, OverviewPageDetailsResponse detailsResponse) {
6874
pomDetailsResponse = detailsResponse;
6975
extractPomContent(projectUri);
7076
}
7177

78+
public static UpdateResponse updateProperty(String projectUri, UpdatePropertyRequest request) {
79+
try {
80+
DocumentBuilder builder = factory.newDocumentBuilder();
81+
Document document = builder.newDocument();
82+
UpdateResponse updateResponse = new UpdateResponse();
83+
StringBuilder elementInString = new StringBuilder();
84+
List<String> pomContent = readPom(projectUri);
85+
assert pomContent != null;
86+
Element propertiesElement = null;
87+
Range initialRange = getPropertiesRange(pomContent);
88+
if (!hasProperties) {
89+
propertiesElement = document.createElement(Constants.PROPERTIES);
90+
}
91+
for (PropertyDetails property : request.properties) {
92+
if (property.getRange() != null) {
93+
updateResponse.add(new TextEdit(property.getRange(),
94+
elementToString(createPropertyElement(document, property))));
95+
} else {
96+
if (propertiesElement != null) {
97+
propertiesElement.appendChild(createPropertyElement(document, property));
98+
} else {
99+
elementInString.append(elementToString(createPropertyElement(document, property)));
100+
}
101+
}
102+
}
103+
String value =
104+
(propertiesElement != null) ? elementToString(propertiesElement) : elementInString.toString();
105+
if (StringUtils.isEmpty(value)) {
106+
return null;
107+
}
108+
// Add the new content inside the <properties> section
109+
updateResponse.add(new TextEdit(new Range(initialRange.getStart(), initialRange.getStart()), value));
110+
return updateResponse;
111+
} catch (ParserConfigurationException e) {
112+
LOGGER.log(Level.SEVERE, "Error parsing the POM file : " + e.getMessage());
113+
return null;
114+
}
115+
}
116+
72117
public static UpdateResponse updateDependency(String projectUri, UpdateDependencyRequest request) {
73118
try {
74119
DocumentBuilder builder = factory.newDocumentBuilder();
@@ -300,6 +345,68 @@ private static List<String> readPom(String projectUri) {
300345
}
301346
}
302347

348+
private static Range getPropertiesRange(List<String> pomContent) {
349+
if (pomContent == null || pomContent.isEmpty()) {
350+
return null;
351+
}
352+
XMLStreamReader reader = null;
353+
try {
354+
reader = getXMLReader(pomContent);
355+
Deque<String> elementStack = new ArrayDeque<>();
356+
int startLine = -1, startChar = -1;
357+
int endLine = -1, endChar = -1;
358+
359+
while (reader.hasNext()) {
360+
int event = reader.next();
361+
362+
if (event == XMLStreamConstants.START_ELEMENT) {
363+
String localName = reader.getLocalName();
364+
elementStack.push(localName);
365+
366+
if (Constants.PROPERTIES.equals(localName) && elementStack.size() == 2 &&
367+
Constant.PROJECT.equals(elementStack.peekLast())) {
368+
hasProperties = true;
369+
startLine = reader.getLocation().getLineNumber();
370+
startChar = reader.getLocation().getColumnNumber() + localName.length() + 2; // After <properties>
371+
}
372+
}
373+
374+
if (event == XMLStreamConstants.END_ELEMENT) {
375+
String localName = reader.getLocalName();
376+
377+
if (Constants.PROPERTIES.equals(localName) && startLine != -1 && elementStack.size() == 2 &&
378+
Constant.PROJECT.equals(elementStack.peekLast())) {
379+
endLine = reader.getLocation().getLineNumber();
380+
endChar = reader.getLocation().getColumnNumber(); // At </properties>
381+
break;
382+
}
383+
384+
elementStack.pop();
385+
}
386+
}
387+
388+
if (startLine == -1 || endLine == -1 || startChar == -1 || endChar == -1) {
389+
return null;
390+
}
391+
392+
Position start = new Position(startLine, startChar);
393+
Position end = new Position(endLine, endChar);
394+
return new Range(start, end);
395+
396+
} catch (Exception e) {
397+
LOGGER.log(Level.SEVERE, "Error reading the POM file: " + e.getMessage());
398+
return null;
399+
} finally {
400+
if (reader != null) {
401+
try {
402+
reader.close();
403+
} catch (XMLStreamException e) {
404+
LOGGER.log(Level.WARNING, "Error closing XMLStreamReader: " + e.getMessage());
405+
}
406+
}
407+
}
408+
}
409+
303410
private static Position getDependenciesStartPosition(List<String> pomContent) {
304411
try {
305412
XMLStreamReader reader = getXMLReader(pomContent);
@@ -345,6 +452,12 @@ private static Position getDependenciesStartPosition(List<String> pomContent) {
345452
}
346453
}
347454

455+
private static Element createPropertyElement(Document document, PropertyDetails propertyDetails) {
456+
Element property = document.createElement(propertyDetails.getName());
457+
property.setTextContent(propertyDetails.getValue());
458+
return property;
459+
}
460+
348461
private static Element createDependencyElement(Document document, DependencyDetails dependencyDetails) {
349462
Element dependency = document.createElement(Constants.DEPENDENCY);
350463
Element groupId = document.createElement(Constants.GROUP_ID);

0 commit comments

Comments
 (0)