Skip to content

Commit c839275

Browse files
authored
Merge pull request wildfly#6270 from bstansberry/WFCORE-7082
[WFCORE-7082] Provide utilities to produce canonical representations …
2 parents 0268e48 + 94ef052 commit c839275

File tree

1 file changed

+154
-0
lines changed

1 file changed

+154
-0
lines changed
Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
/*
2+
* Copyright The WildFly Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
package org.jboss.as.controller;
6+
7+
import org.jboss.dmr.ModelNode;
8+
import org.jboss.dmr.ModelType;
9+
10+
/**
11+
* Provides utilities related to working with names of JBoss Modules modules.
12+
*/
13+
public final class ModuleIdentifierUtil {
14+
15+
/**
16+
* Provides the canonical string representation of a module identifier from a string
17+
* of the form {@code name[:slot]}. The canonical representation will not include
18+
* slot information if the slot is {@code main}.
19+
*
20+
* @param moduleSpec a module name specification in the form {@code name[:slot]}. Cannot be {@code null}
21+
* @return the canonical representation. Will not return @{code null}
22+
*/
23+
public static String canonicalModuleIdentifier(String moduleSpec) {
24+
// Note: this is taken from org.jboss.modules.ModuleIdentifier.fromString and lightly adapted.
25+
26+
if (moduleSpec == null) {
27+
throw new IllegalArgumentException("Module specification is null");
28+
} else if (moduleSpec.isEmpty()) {
29+
throw new IllegalArgumentException("Empty module specification");
30+
} else {
31+
StringBuilder b = new StringBuilder();
32+
33+
int c;
34+
int i;
35+
for(i = 0; i < moduleSpec.length(); i = moduleSpec.offsetByCodePoints(i, 1)) {
36+
c = moduleSpec.codePointAt(i);
37+
if (c == 92) {
38+
b.appendCodePoint(c);
39+
i = moduleSpec.offsetByCodePoints(i, 1);
40+
if (i >= moduleSpec.length()) {
41+
throw new IllegalArgumentException("Name has an unterminated escape");
42+
}
43+
44+
c = moduleSpec.codePointAt(i);
45+
b.appendCodePoint(c);
46+
} else {
47+
if (c == 58) {
48+
i = moduleSpec.offsetByCodePoints(i, 1);
49+
if (i == moduleSpec.length()) {
50+
throw new IllegalArgumentException("Slot is empty");
51+
}
52+
break;
53+
}
54+
55+
b.appendCodePoint(c);
56+
}
57+
}
58+
59+
String name = b.toString();
60+
b.setLength(0);
61+
if (i >= moduleSpec.length()) {
62+
return canonicalModuleIdentifier(name, null);
63+
} else {
64+
do {
65+
c = moduleSpec.codePointAt(i);
66+
b.appendCodePoint(c);
67+
i = moduleSpec.offsetByCodePoints(i, 1);
68+
} while(i < moduleSpec.length());
69+
70+
return canonicalModuleIdentifier(name, b.toString());
71+
}
72+
}
73+
74+
}
75+
76+
/**
77+
* Provides the canonical string representation of a module identifier from a base
78+
* module name and an optional slot. The canonical representation will not include
79+
* slot information if the slot is {@code main}.
80+
*
81+
* @param name the base module name. Cannot be {@code null}
82+
* @param slot the module slot. May be @{code null}
83+
*
84+
* @return the canonical representation. Will not return @{code null}
85+
*/
86+
public static String canonicalModuleIdentifier(String name, String slot) {
87+
if (name == null) {
88+
throw new IllegalArgumentException("name is null");
89+
}
90+
String escaped = escapeName(name);
91+
return slot == null || "main".equals(slot) ? escaped : escaped + ":" + escapeSlot(slot);
92+
}
93+
94+
/**
95+
* A {@link ParameterCorrector} that {@link #canonicalModuleIdentifier(String) canonicalizes}
96+
* values that are meant to represent JBoss Modules module names.
97+
*/
98+
public static final ParameterCorrector MODULE_NAME_CORRECTOR = new ParameterCorrector() {
99+
@Override
100+
public ModelNode correct(ModelNode newValue, ModelNode currentValue) {
101+
if (ModelType.STRING.equals(newValue.getType())) {
102+
String orig = newValue.asString();
103+
String corrected = canonicalModuleIdentifier(orig);
104+
if (!orig.equals(corrected)) {
105+
newValue.set(corrected);
106+
}
107+
}
108+
return newValue;
109+
}
110+
};
111+
112+
private static String escapeName(String name) {
113+
// Note: this is taken from org.jboss.modules.ModuleIdentifier.escapeName
114+
StringBuilder b = new StringBuilder();
115+
boolean escaped = false;
116+
int i = 0;
117+
118+
while(i < name.length()) {
119+
int c = name.codePointAt(i);
120+
switch (c) {
121+
case 58:
122+
case 92:
123+
escaped = true;
124+
b.append('\\');
125+
default:
126+
b.appendCodePoint(c);
127+
i = name.offsetByCodePoints(i, 1);
128+
}
129+
}
130+
131+
return escaped ? b.toString() : name;
132+
}
133+
134+
private static String escapeSlot(String slot) {
135+
// Note: this is taken from org.jboss.modules.ModuleIdentifier.escapeSlot
136+
StringBuilder b = new StringBuilder();
137+
boolean escaped = false;
138+
int i = 0;
139+
140+
while(i < slot.length()) {
141+
int c = slot.codePointAt(i);
142+
switch (c) {
143+
case 92:
144+
escaped = true;
145+
b.append('\\');
146+
default:
147+
b.appendCodePoint(c);
148+
i = slot.offsetByCodePoints(i, 1);
149+
}
150+
}
151+
152+
return escaped ? b.toString() : slot;
153+
}
154+
}

0 commit comments

Comments
 (0)