• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

devonfw / IDEasy / 22283847745

22 Feb 2026 07:34PM UTC coverage: 70.75% (+0.3%) from 70.474%
22283847745

Pull #1714

github

web-flow
Merge 8263a112b into 379acdc9d
Pull Request #1714: #404: #1713: advanced logging

4064 of 6348 branches covered (64.02%)

Branch coverage included in aggregate %.

10635 of 14428 relevant lines covered (73.71%)

3.1 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

85.93
cli/src/main/java/com/devonfw/tools/ide/tool/custom/CustomToolsMapper.java
1
package com.devonfw.tools.ide.tool.custom;
2

3
import java.util.ArrayList;
4
import java.util.List;
5

6
import org.slf4j.Logger;
7
import org.slf4j.LoggerFactory;
8

9
import com.devonfw.tools.ide.context.IdeContext;
10
import com.devonfw.tools.ide.environment.VariableLine;
11
import com.devonfw.tools.ide.json.JsonMapping;
12
import com.devonfw.tools.ide.json.StandardJsonObjectMapper;
13
import com.devonfw.tools.ide.os.OperatingSystem;
14
import com.devonfw.tools.ide.os.SystemArchitecture;
15
import com.devonfw.tools.ide.os.SystemInfo;
16
import com.fasterxml.jackson.databind.ObjectMapper;
17

18
/**
19
 * Mapper of {@link CustomTools} from/to JSON or legacy properties.
20
 */
21
public class CustomToolsMapper extends StandardJsonObjectMapper<CustomTools> {
22

23
  private static final Logger LOG = LoggerFactory.getLogger(CustomToolsMapper.class);
3✔
24

25
  private static final CustomToolsMapper INSTANCE = new CustomToolsMapper();
5✔
26

27
  private final ObjectMapper MAPPER = JsonMapping.create();
3✔
28

29
  private CustomToolsMapper() {
30
    super(CustomTools.class);
3✔
31
  }
1✔
32

33
  @Override
34
  public String getStandardFilename() {
35

36
    return "ide-custom-tools.json";
2✔
37
  }
38

39
  /**
40
   * @param customTools the {@link CustomTools} to convert.
41
   * @param context the {@link IdeContext}.
42
   * @return the converted {@link List} of {@link CustomToolMetadata}.
43
   */
44
  public static List<CustomToolMetadata> convert(CustomTools customTools, IdeContext context) {
45

46
    String repositoryUrl = customTools.url();
3✔
47
    List<CustomTool> tools = customTools.tools();
3✔
48
    List<CustomToolMetadata> result = new ArrayList<>(tools.size());
6✔
49
    for (CustomTool customTool : tools) {
10✔
50
      result.add(convert(customTool, repositoryUrl, context));
7✔
51
    }
1✔
52
    return result;
2✔
53
  }
54

55
  private static CustomToolMetadata convert(CustomTool customTool, String repositoryUrl, IdeContext context) {
56

57
    String tool = customTool.name();
3✔
58
    String version = customTool.version();
3✔
59
    SystemInfo systemInfo = context.getSystemInfo();
3✔
60
    String repoUrl = customTool.url();
3✔
61
    if ((repoUrl == null) || repoUrl.isEmpty()) {
5!
62
      repoUrl = repositoryUrl;
×
63
    }
64
    int capacity = repoUrl.length() + 2 * tool.length() + 2 * version.length() + 7;
15✔
65
    OperatingSystem os;
66
    if (customTool.osAgnostic()) {
3✔
67
      os = null;
3✔
68
    } else {
69
      os = systemInfo.getOs();
3✔
70
      capacity += os.toString().length() + 1;
8✔
71
    }
72
    SystemArchitecture arch;
73
    if (customTool.archAgnostic()) {
3✔
74
      arch = null;
3✔
75
    } else {
76
      arch = systemInfo.getArchitecture();
3✔
77
      capacity += arch.toString().length() + 1;
8✔
78
    }
79
    StringBuilder sb = new StringBuilder(capacity);
5✔
80
    sb.append(repoUrl);
4✔
81
    char last = repoUrl.charAt(repoUrl.length() - 1);
7✔
82
    if ((last != '/') && (last != '\\')) {
3!
83
      sb.append('/');
×
84
    }
85
    sb.append(tool);
4✔
86
    sb.append('/');
4✔
87
    sb.append(version);
4✔
88
    sb.append('/');
4✔
89
    sb.append(tool);
4✔
90
    sb.append('-');
4✔
91
    sb.append(version);
4✔
92
    if (os != null) {
2✔
93
      sb.append('-');
4✔
94
      sb.append(os);
4✔
95
    }
96
    if (arch != null) {
2✔
97
      sb.append('-');
4✔
98
      sb.append(arch);
4✔
99
    }
100
    sb.append(".tgz");
4✔
101
    String url = sb.toString();
3✔
102
    return new CustomToolMetadata(tool, version, os, arch, url, null, repoUrl);
11✔
103
  }
104

105
  /**
106
   * Retrieves custom tools from a devonfw-ide legacy config.
107
   *
108
   * @param customToolsContent String of custom tools
109
   * @return {@link CustomTools}.
110
   */
111
  public static CustomTools parseCustomToolsFromLegacyConfig(String customToolsContent) {
112
    List<String> customToolEntries = VariableLine.parseArray(customToolsContent);
3✔
113
    if (customToolEntries.isEmpty()) {
3✔
114
      return null;
2✔
115
    }
116
    List<CustomTool> customTools = new ArrayList<>(customToolEntries.size());
6✔
117
    String defaultUrl = null;
2✔
118
    for (String customToolConfig : customToolEntries) {
10✔
119
      CustomTool customTool = parseCustomToolFromLegacyConfig(customToolConfig);
3✔
120
      if (customTool == null) {
2!
121
        LOG.warn("Invalid custom tool entry: {}", customToolConfig);
×
122
      } else {
123
        String url = customTool.url();
3✔
124
        if (defaultUrl == null) {
2✔
125
          if ((url == null) || url.isEmpty()) {
5!
126
            LOG.warn("First custom tool entry has no URL specified: {}", customToolConfig);
5✔
127
          } else {
128
            defaultUrl = url;
2✔
129
            customTool = customTool.withoutUrl();
4✔
130
          }
131
        } else if (defaultUrl.equals(url)) {
4!
132
          customTool = customTool.withoutUrl();
×
133
        }
134
        customTools.add(customTool);
4✔
135
      }
136
    }
1✔
137
    if (customTools.isEmpty() || (defaultUrl == null)) {
5!
138
      return null;
2✔
139
    }
140
    return new CustomTools(defaultUrl, customTools);
6✔
141
  }
142

143
  private static CustomTool parseCustomToolFromLegacyConfig(String customToolConfig) {
144
    int firstColon = customToolConfig.indexOf(":");
4✔
145
    if (firstColon < 0) {
2!
146
      return null;
×
147
    }
148
    String toolName = customToolConfig.substring(0, firstColon);
5✔
149
    int secondColon = customToolConfig.indexOf(":", firstColon + 1);
7✔
150
    if (secondColon < 0) {
2!
151
      return null;
×
152
    }
153
    String version = customToolConfig.substring(firstColon + 1, secondColon);
7✔
154
    int thirdColon = customToolConfig.indexOf(":", secondColon + 1);
7✔
155
    boolean osAgnostic = false;
2✔
156
    boolean archAgnostic = false;
2✔
157
    String url = null;
2✔
158
    if (thirdColon > 0) {
2✔
159
      if (customToolConfig.substring(secondColon + 1, thirdColon).equals("all")) {
9!
160
        osAgnostic = true;
2✔
161
        archAgnostic = true;
2✔
162
        url = customToolConfig.substring(thirdColon + 1);
7✔
163
      } else {
164
        url = customToolConfig.substring(secondColon + 1);
×
165
      }
166
    }
167
    return new CustomTool(toolName, version, osAgnostic, archAgnostic, url);
9✔
168
  }
169

170
  /**
171
   * @return the singleton instance of {@link CustomToolsMapper}.
172
   */
173
  public static CustomToolsMapper get() {
174

175
    return INSTANCE;
2✔
176
  }
177

178
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc