1
+ /*
2
+ * Licensed to the Apache Software Foundation (ASF) under one
3
+ * or more contributor license agreements. See the NOTICE file
4
+ * distributed with this work for additional information
5
+ * regarding copyright ownership. The ASF licenses this file
6
+ * to you under the Apache License, Version 2.0 (the
7
+ * "License") you may not use this file except in compliance
8
+ * with the License. You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing,
13
+ * software distributed under the License is distributed on an
14
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
+ * KIND, either express or implied. See the License for the
16
+ * specific language governing permissions and limitations
17
+ * under the License.
18
+ */
19
+
20
+ package com.github.jengelman.gradle.plugins.shadow.transformers
21
+
22
+ import com.github.jengelman.gradle.plugins.shadow.ShadowStats
23
+ import com.github.jengelman.gradle.plugins.shadow.relocation.RelocateClassContext
24
+ import com.github.jengelman.gradle.plugins.shadow.relocation.Relocator
25
+ import org.apache.commons.io.IOUtils
26
+ import org.apache.commons.io.output.CloseShieldOutputStream
27
+ import org.apache.logging.log4j.core.config.plugins.processor.PluginCache
28
+ import org.apache.logging.log4j.core.config.plugins.processor.PluginEntry
29
+ import org.apache.tools.zip.ZipOutputStream
30
+ import org.gradle.api.file.FileTreeElement
31
+
32
+ import java.util.zip.ZipEntry
33
+
34
+ import static org.apache.logging.log4j.core.config.plugins.processor.PluginProcessor.PLUGIN_CACHE_FILE;
35
+
36
+ /**
37
+ * Modified from the maven equivalent to work with gradle
38
+ *
39
+ * @author Paul Nelson Baker
40
+ * @see <a href =" https://www.linkedin.com/in/paul-n-baker/" >LinkedIn</a>
41
+ * @see <a href =" https://github.com/paul-nelson-baker/" >GitHub</a>
42
+ * @see <a href =" https://github.com/edwgiz/maven-shaded-log4j-transformer" >edwgiz/maven-shaded-log4j-transformer</a>
43
+ * @see <a href =" https://github.com/edwgiz/maven-shaded-log4j-transformer/blob/master/src/main/java/com/github/edwgiz/mavenShadePlugin/log4j2CacheTransformer/PluginsCacheFileTransformer.java" >PluginsCacheFileTransformer.java</a>
44
+ */
45
+ class Log4j2PluginsCacheFileTransformer implements Transformer {
46
+
47
+ private final List<File > temporaryFiles;
48
+ private final List<Relocator > relocators;
49
+
50
+ public Log4j2PluginsCacheFileTransformer () {
51
+ temporaryFiles = new ArrayList<> ();
52
+ relocators = new ArrayList<> ();
53
+ }
54
+
55
+ @Override
56
+ boolean canTransformResource (FileTreeElement element ) {
57
+ return PLUGIN_CACHE_FILE == element. name
58
+ }
59
+
60
+ @Override
61
+ void transform (TransformerContext context ) {
62
+ def inputStream = context. is
63
+ def temporaryFile = File . createTempFile(" Log4j2Plugins" , " .dat" )
64
+ temporaryFile. deleteOnExit()
65
+ temporaryFiles. add(temporaryFile)
66
+ IOUtils . copy(inputStream, new FileOutputStream (temporaryFile))
67
+ def contextRelocators = context. relocators
68
+ if (contextRelocators != null ) {
69
+ this . relocators. addAll(contextRelocators)
70
+ }
71
+ }
72
+
73
+ @Override
74
+ boolean hasTransformedResource () {
75
+ // This functionality matches the original plugin, however, I'm not clear what
76
+ // the exact logic is. From what I can tell temporaryFiles should be never be empty
77
+ // if anything has been performed.
78
+ def hasTransformedMultipleFiles = temporaryFiles. size() > 1
79
+ def hasAtLeastOneFileAndRelocator = ! temporaryFiles. isEmpty() && ! relocators. isEmpty()
80
+ def hasTransformedResources = hasTransformedMultipleFiles || hasAtLeastOneFileAndRelocator
81
+ return hasTransformedResources
82
+ }
83
+
84
+ @Override
85
+ void modifyOutputStream (ZipOutputStream jos ) {
86
+ PluginCache pluginCache = new PluginCache ()
87
+ pluginCache. loadCacheFiles(getUrlEnumeration())
88
+ relocatePlugins(pluginCache)
89
+ zipOutputStream. putNextEntry(new ZipEntry (PLUGIN_CACHE_FILE ))
90
+ pluginCache. writeCache(new CloseShieldOutputStream (zipOutputStream))
91
+ temporaryFiles. clear()
92
+ }
93
+
94
+ private Enumeration<URL > getUrlEnumeration () {
95
+ def urls = temporaryFiles. collect({ it. toURL() }). asList()
96
+ return Collections . enumeration(urls)
97
+ }
98
+
99
+ private void relocatePlugins (PluginCache pluginCache ) {
100
+ for (Map<String , PluginEntry > currentMap : pluginCache. getAllCategories(). values()) {
101
+ pluginEntryLoop :
102
+ for (PluginEntry currentPluginEntry : currentMap. values()) {
103
+ String className = currentPluginEntry. getClassName();
104
+ RelocateClassContext relocateClassContext = new RelocateClassContext (className, new ShadowStats ());
105
+ for (Relocator currentRelocator : relocators) {
106
+ // If we have a relocator that can relocate our current entry...
107
+ boolean canRelocateClass = currentRelocator. canRelocateClass(relocateClassContext);
108
+ if (canRelocateClass) {
109
+ // Then we perform that relocation and update the plugin entry to reflect the new value.
110
+ String relocatedClassName = currentRelocator. relocateClass(relocateClassContext);
111
+ currentPluginEntry. setClassName(relocatedClassName);
112
+ continue pluginEntryLoop;
113
+ }
114
+ }
115
+ }
116
+ }
117
+ }
118
+ }
0 commit comments