Skip to content

Commit 3a5dadc

Browse files
committed
#48 added way to define custom class through its name as action preprocessor extension
1 parent 299d282 commit 3a5dadc

File tree

23 files changed

+281
-26
lines changed

23 files changed

+281
-26
lines changed

jcp-tests/jcp-test-android/app/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ dependencies {
4343
preprocess {
4444
sources = android.sourceSets.main.java.srcDirs
4545
keepComments = false
46+
actionPreprocessorExtension = "com.igormaznitsa.jcp.extension.LogPreprocessorExtension"
4647
vars = [
4748
'action.text' : 'Non-secret action!',
4849
'remove.secret': 'true'

jcp-tests/jcp-test-ant/src/test/resources/build.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
targetEncoding="UTF-8"
2121
preserveIndents="true"
2222
dontOverwriteSameContent="false"
23+
actionPreprocessorExtension="com.igormaznitsa.jcp.extension.LogPreprocessorExtension"
2324
>
2425
<excludeFolders>
2526
<folder>**/excluded1</folder>

jcp-tests/jcp-test-gradle-5/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ preprocess {
5656
allowWhitespaces = true
5757
preserveIndents = true
5858
dontOverwriteSameContent = false
59+
actionPreprocessorExtension = "com.igormaznitsa.jcp.extension.LogPreprocessorExtension"
5960
vars = ['some.test.global': 'Some Test Global Value']
6061
}
6162
task(changeSourceFolder) {

jcp-tests/jcp-test-gradle-6/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ preprocess {
5656
allowWhitespaces = true
5757
preserveIndents = true
5858
dontOverwriteSameContent = false
59+
actionPreprocessorExtension = "com.igormaznitsa.jcp.extension.LogPreprocessorExtension"
5960
vars = ['some.test.global': 'Some Test Global Value']
6061
}
6162
task(changeSourceFolder) {

jcp-tests/jcp-test-gradle-7/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ preprocess {
5656
allowWhitespaces = true
5757
preserveIndents = true
5858
dontOverwriteSameContent = false
59+
actionPreprocessorExtension = "com.igormaznitsa.jcp.extension.LogPreprocessorExtension"
5960
vars = ['some.test.global': 'Some Test Global Value']
6061
}
6162
task(changeSourceFolder) {

jcp-tests/jcp-test-gradle-8/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ preprocess {
5656
allowWhitespaces = true
5757
preserveIndents = true
5858
dontOverwriteSameContent = false
59+
actionPreprocessorExtension = "com.igormaznitsa.jcp.extension.LogPreprocessorExtension"
5960
vars = ['some.test.global': 'Some Test Global Value']
6061
}
6162
task(changeSourceFolder) {

jcp-tests/jcp-test-maven/pom.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@
4747
<vars>
4848
<some.test.global>Some Test Global Value</some.test.global>
4949
</vars>
50+
<actionPreprocessorExtension>com.igormaznitsa.jcp.extension.LogPreprocessorExtension
51+
</actionPreprocessorExtension>
5052
<sourceEncoding>UTF-8</sourceEncoding>
5153
<targetEncoding>UTF-8</targetEncoding>
5254
<ignoreMissingSources>false</ignoreMissingSources>

jcp-tests/jcp-test-maven/src/main/java/com/igormaznitsa/jcp/it/maven/Main.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
//$public class MainTwo {
55
//#//
6+
//#action 1,2,3
67
public class Main {
78

89
//$$public MainTwo(){
@@ -25,6 +26,7 @@ public Main(){
2526
}
2627
}
2728

29+
//#action $hello1("getProperty")
2830
public String getProperty() {
2931
return "/*$mvn.project.property.my.custom.property$*/";
3032
}

jcp/src/main/java/com/igormaznitsa/jcp/JcpPreprocessor.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import static com.igormaznitsa.jcp.utils.PreprocessorUtils.readWholeTextFileIntoArray;
2626
import static com.igormaznitsa.jcp.utils.PreprocessorUtils.throwPreprocessorException;
2727

28+
import com.igormaznitsa.jcp.cmdline.ActionPreprocessorExtensionHandler;
2829
import com.igormaznitsa.jcp.cmdline.AllowWhitespaceDirectiveHandler;
2930
import com.igormaznitsa.jcp.cmdline.CareForLastEolHandler;
3031
import com.igormaznitsa.jcp.cmdline.ClearTargetHandler;
@@ -104,6 +105,7 @@ public final class JcpPreprocessor {
104105
new PreserveIndentDirectiveHandler(),
105106
new ExcludeFoldersHandler(),
106107
new KeepAttributesHandler(),
108+
new ActionPreprocessorExtensionHandler(),
107109
new UnknownAsFalseHandler()
108110
};
109111
private final PreprocessorContext context;

jcp/src/main/java/com/igormaznitsa/jcp/ant/PreprocessTask.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ public class PreprocessTask extends Task implements PreprocessorLogger, SpecialV
7878
private boolean allowWhitespaces = false;
7979
private boolean preserveIndents = false;
8080
private boolean dontOverwriteSameContent = false;
81+
private String actionPreprocessorExtension = null;
8182
private Map<String, Value> antVariables = new HashMap<>();
8283

8384
private void registerConfigFiles(final PreprocessorContext context) {
@@ -169,6 +170,13 @@ PreprocessorContext makePreprocessorContext() {
169170
);
170171
}
171172

173+
if (this.getActionPreprocessorExtension() != null) {
174+
info("Instantiating action preprocessor extension: " + this.getActionPreprocessorExtension());
175+
context.setPreprocessorExtension(
176+
PreprocessorUtils.findAndInstantiatePreprocessorExtensionForClassName(
177+
this.getActionPreprocessorExtension().trim()));
178+
}
179+
172180
this.registerConfigFiles(context);
173181
this.fillGlobalVars(context);
174182

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package com.igormaznitsa.jcp.cmdline;
2+
3+
import com.igormaznitsa.jcp.context.PreprocessorContext;
4+
import com.igormaznitsa.jcp.extension.PreprocessorExtension;
5+
import com.igormaznitsa.jcp.utils.PreprocessorUtils;
6+
import java.util.Locale;
7+
8+
public class ActionPreprocessorExtensionHandler implements CommandLineHandler {
9+
10+
private static final String ARG_NAME = "/EA:";
11+
12+
@Override
13+
public String getDescription() {
14+
return "class to be used for action directives, the class must be in the classpath and contain default constructor.";
15+
}
16+
17+
@Override
18+
public boolean processCommandLineKey(final String key, final PreprocessorContext context) {
19+
boolean result = false;
20+
21+
if (!key.isEmpty() && key.toUpperCase(Locale.ENGLISH).startsWith(ARG_NAME)) {
22+
final String tail = PreprocessorUtils.extractTrimmedTail(ARG_NAME, key);
23+
24+
if (tail.isEmpty()) {
25+
result = true;
26+
} else {
27+
final PreprocessorExtension preprocessorExtension =
28+
PreprocessorUtils.findAndInstantiatePreprocessorExtensionForClassName(tail);
29+
context.setPreprocessorExtension(preprocessorExtension);
30+
result = true;
31+
}
32+
}
33+
return result;
34+
}
35+
36+
@Override
37+
public String getKeyName() {
38+
return ARG_NAME;
39+
}
40+
}

jcp/src/main/java/com/igormaznitsa/jcp/cmdline/ExcludedFileExtensionsHandler.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ public class ExcludedFileExtensionsHandler implements CommandLineHandler {
3939
@Override
4040
public String getDescription() {
4141
return
42-
"comma separated file extensions (case insensetive) to be excluded from preprocess and copy (by default " +
42+
"comma separated file extensions (case insensitive) to be excluded from preprocess and copy (by default " +
4343
String.join(",", PreprocessorContext.DEFAULT_EXCLUDED_EXTENSIONS) + ')';
4444
}
4545

jcp/src/main/java/com/igormaznitsa/jcp/directives/ActionDirectiveHandler.java

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@
3434
import java.io.StringReader;
3535
import java.util.ArrayList;
3636
import java.util.List;
37-
import java.util.Objects;
3837

3938
/**
4039
* The class implements the //#action directive handler
@@ -44,25 +43,21 @@
4443
public class ActionDirectiveHandler extends AbstractDirectiveHandler {
4544

4645
@Override
47-
4846
public String getName() {
4947
return "action";
5048
}
5149

5250
@Override
53-
5451
public String getReference() {
5552
return "call user extension with comma separated arguments";
5653
}
5754

5855
@Override
59-
6056
public DirectiveArgumentType getArgumentType() {
6157
return DirectiveArgumentType.MULTIEXPRESSION;
6258
}
6359

6460
@Override
65-
6661
public AfterDirectiveProcessingBehaviour execute(final String string,
6762
final PreprocessorContext context) {
6863
if (context.getPreprocessorExtension() != null) {
@@ -77,9 +72,14 @@ public AfterDirectiveProcessingBehaviour execute(final String string,
7772
results[index++] = val;
7873
}
7974

80-
if (!Objects.requireNonNull(context.getPreprocessorExtension())
81-
.processAction(context, results)) {
82-
throw context.makeException("Extension can't process action ", null);
75+
if (context.getPreprocessorExtension() == null) {
76+
throw context.makeException(
77+
"Detected action directive but there is no any provided action preprocessor extension to process it",
78+
null);
79+
}
80+
81+
if (!context.getPreprocessorExtension().processAction(context, results)) {
82+
throw context.makeException("Unable to process an action", null);
8383
}
8484
} catch (IOException ex) {
8585
throw context.makeException("Unexpected string detected [" + string + ']', ex);

jcp/src/main/java/com/igormaznitsa/jcp/exceptions/PreprocessorException.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ public class PreprocessorException extends RuntimeException {
3535
private static final long serialVersionUID = 2857499664112391862L;
3636

3737
private final String processingString;
38-
private transient final FilePositionInfo[] includeStack;
38+
private final transient FilePositionInfo[] includeStack;
3939

4040
public PreprocessorException(final String message, final String processedText,
4141
final FilePositionInfo[] includeStack, final Throwable cause) {
@@ -139,7 +139,7 @@ public int getLineNumber() {
139139

140140

141141
public String getProcessingString() {
142-
return processingString;
142+
return this.processingString;
143143
}
144144

145145

jcp/src/main/java/com/igormaznitsa/jcp/expression/functions/FunctionDefinedByUser.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ public int getArity() {
7474
public Value execute(final PreprocessorContext context, final Value[] values) {
7575
return Objects.requireNonNull(
7676
context.getPreprocessorExtension(), "Preprocessor extension must not be null")
77-
.processUserFunction(name, values);
77+
.processUserFunction(context, name, values);
7878
}
7979

8080
@Override
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package com.igormaznitsa.jcp.extension;
2+
3+
4+
import com.igormaznitsa.jcp.containers.TextFileDataContainer;
5+
import com.igormaznitsa.jcp.context.PreprocessorContext;
6+
import com.igormaznitsa.jcp.expression.Value;
7+
import java.util.Arrays;
8+
import java.util.regex.Matcher;
9+
import java.util.regex.Pattern;
10+
11+
/**
12+
* Preprocessor extension which just make info logging for arguments of action calls and also
13+
* can log user function calls, their arity should be provided in the end of function name like '$hello2(1,2)'
14+
*
15+
* @since 7.1.2
16+
*/
17+
public class LogPreprocessorExtension implements PreprocessorExtension {
18+
19+
private static final Pattern PATTERN = Pattern.compile("^(\\D+)(\\d+)?$");
20+
21+
private static String findPosition(final PreprocessorContext context) {
22+
if (context == null) {
23+
return "";
24+
}
25+
if (context.getPreprocessingState().getCurrentIncludeStack().isEmpty()) {
26+
return "";
27+
} else {
28+
final TextFileDataContainer dataContainer =
29+
context.getPreprocessingState().getCurrentIncludeStack().get(0);
30+
return (dataContainer.getFile() == null ? "<unknown>" : dataContainer.getFile().getName())
31+
+ ':'
32+
+ (dataContainer.getLastReadStringIndex() + 1);
33+
}
34+
}
35+
36+
@Override
37+
public boolean processAction(final PreprocessorContext context, final Value[] parameters) {
38+
context.logInfo(String.format("Called action: %s at %s", Arrays.toString(parameters),
39+
findPosition(context)));
40+
return true;
41+
}
42+
43+
@Override
44+
public Value processUserFunction(final PreprocessorContext context, final String functionName,
45+
final Value[] arguments) {
46+
context.logInfo(
47+
String.format("Called user function '%s'(%s) at %s",
48+
functionName, Arrays.toString(arguments),
49+
findPosition(context)));
50+
return Value.BOOLEAN_TRUE;
51+
}
52+
53+
@Override
54+
public int getUserFunctionArity(final String functionName) {
55+
final Matcher matcher = PATTERN.matcher(functionName);
56+
if (matcher.find() && matcher.group(2) != null) {
57+
return Integer.parseInt(matcher.group(2));
58+
}
59+
return 0;
60+
}
61+
}

jcp/src/main/java/com/igormaznitsa/jcp/extension/PreprocessorExtension.java

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,29 @@ public interface PreprocessorExtension {
5050
* must not be null
5151
* @param arguments the function arguments as an array, must not be null
5252
* @return a calculated value, it must not be null
53+
* @see #processUserFunction(PreprocessorContext, String, Value[])
54+
* @deprecated since 7.1.2
5355
*/
56+
@Deprecated
57+
default Value processUserFunction(String functionName, Value[] arguments) {
58+
throw new UnsupportedOperationException("Use version with PreprocessorContext for call");
59+
}
5460

55-
Value processUserFunction(String functionName, Value[] arguments);
61+
/**
62+
* Call to process a user function (such functions start with $)
63+
*
64+
* @param context the current preprocessor context, must not be null
65+
* @param functionName the name of the function (without $ and in low case),
66+
* must not be null
67+
* @param arguments the function arguments as an array, must not be null
68+
* @return a calculated value, it must not be null
69+
* @see #processUserFunction(String, Value[])
70+
* @since 7.1.2
71+
*/
72+
default Value processUserFunction(PreprocessorContext context, String functionName,
73+
Value[] arguments) {
74+
return this.processUserFunction(functionName, arguments);
75+
}
5676

5777
/**
5878
* When a preprocessor meets a user defined function (the function starts with

jcp/src/main/java/com/igormaznitsa/jcp/gradle/JcpTask.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.igormaznitsa.jcp.gradle;
22

3+
import static com.igormaznitsa.jcp.utils.PreprocessorUtils.findAndInstantiatePreprocessorExtensionForClassName;
34
import static com.igormaznitsa.jcp.utils.PreprocessorUtils.findCommentRemoverForId;
45
import static java.util.Collections.emptyMap;
56

@@ -66,6 +67,12 @@ public class JcpTask extends DefaultTask {
6667
* Encoding for text write operations.
6768
*/
6869
private final Property<String> targetEncoding;
70+
/**
71+
* Property contains preprocessor action extension class name or blank string if not provided.
72+
*
73+
* @since 7.1.2
74+
*/
75+
private final Property<String> actionPreprocessorExtension;
6976
/**
7077
* Flag to ignore missing source folders, if false then mojo fail for any
7178
* missing source folder, if true then missing folder will be ignored.
@@ -157,6 +164,7 @@ public class JcpTask extends DefaultTask {
157164

158165
@Inject
159166
public JcpTask(final ObjectFactory factory) {
167+
this.actionPreprocessorExtension = factory.property(String.class).convention("");
160168
this.allowWhitespaces = factory.property(Boolean.class).convention(false);
161169
this.careForLastEol = factory.property(Boolean.class).convention(false);
162170
this.clearTarget = factory.property(Boolean.class).convention(false);
@@ -278,6 +286,11 @@ public Property<File> getBaseDir() {
278286
return baseDir;
279287
}
280288

289+
@Input
290+
public Property<String> getActionPreprocessorExtension() {
291+
return actionPreprocessorExtension;
292+
}
293+
281294
@Input
282295
public Property<Boolean> getCareForLastEol() {
283296
return careForLastEol;
@@ -415,6 +428,14 @@ public void warning(final String message) {
415428
preprocessorContext.setUnknownVariableAsFalse(this.unknownVarAsFalse.get());
416429
preprocessorContext.setVerbose(this.verbose.get());
417430

431+
if (!this.actionPreprocessorExtension.get().trim().isEmpty()) {
432+
final String className = this.actionPreprocessorExtension.get().trim();
433+
logger.info(
434+
String.format("Detected action preprocessor extension class name: %s", className));
435+
preprocessorContext.setPreprocessorExtension(
436+
findAndInstantiatePreprocessorExtensionForClassName(className));
437+
}
438+
418439
this.vars.getOrElse(emptyMap()).entrySet().stream()
419440
.filter(e -> {
420441
if (e.getValue() == null) {

0 commit comments

Comments
 (0)