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.ZipEntry
30
+ import org.apache.tools.zip.ZipOutputStream
31
+ import org.gradle.api.file.FileTreeElement
32
+
33
+ import static org.apache.logging.log4j.core.config.plugins.processor.PluginProcessor.PLUGIN_CACHE_FILE;
34
+
35
+ /**
36
+ * Modified from the maven equivalent to work with gradle
37
+ *
38
+ * @author Paul Nelson Baker
39
+ * @see <a href =" https://www.linkedin.com/in/paul-n-baker/" >LinkedIn</a>
40
+ * @see <a href =" https://github.com/paul-nelson-baker/" >GitHub</a>
41
+ * @see <a href =" https://github.com/edwgiz/maven-shaded-log4j-transformer" >edwgiz/maven-shaded-log4j-transformer</a>
42
+ * @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>
43
+ */
44
+ class Log4j2PluginsCacheFileTransformer implements Transformer {
45
+
46
+ private final List<File > temporaryFiles;
47
+ private final List<Relocator > relocators;
48
+
49
+ public Log4j2PluginsCacheFileTransformer () {
50
+ temporaryFiles = new ArrayList<> ();
51
+ relocators = new ArrayList<> ();
52
+ }
53
+
54
+ @Override
55
+ boolean canTransformResource (FileTreeElement element ) {
56
+ return PLUGIN_CACHE_FILE == element. name
57
+ }
58
+
59
+ @Override
60
+ void transform (TransformerContext context ) {
61
+ def inputStream = context. is
62
+ def temporaryFile = File . createTempFile(" Log4j2Plugins" , " .dat" )
63
+ temporaryFile. deleteOnExit()
64
+ temporaryFiles. add(temporaryFile)
65
+ IOUtils . copy(inputStream, new FileOutputStream (temporaryFile))
66
+ def contextRelocators = context. relocators
67
+ if (contextRelocators != null ) {
68
+ this . relocators. addAll(contextRelocators)
69
+ }
70
+ }
71
+
72
+ @Override
73
+ boolean hasTransformedResource () {
74
+ // This functionality matches the original plugin, however, I'm not clear what
75
+ // the exact logic is. From what I can tell temporaryFiles should be never be empty
76
+ // if anything has been performed.
77
+ def hasTransformedMultipleFiles = temporaryFiles. size() > 1
78
+ def hasAtLeastOneFileAndRelocator = ! temporaryFiles. isEmpty() && ! relocators. isEmpty()
79
+ def hasTransformedResources = hasTransformedMultipleFiles || hasAtLeastOneFileAndRelocator
80
+ return hasTransformedResources
81
+ }
82
+
83
+ @Override
84
+ void modifyOutputStream (ZipOutputStream zipOutputStream ) {
85
+ PluginCache pluginCache = new PluginCache ()
86
+ pluginCache. loadCacheFiles(getUrlEnumeration())
87
+ relocatePlugins(pluginCache)
88
+ zipOutputStream. putNextEntry(new ZipEntry (PLUGIN_CACHE_FILE ))
89
+ pluginCache. writeCache(new CloseShieldOutputStream (zipOutputStream))
90
+ temporaryFiles. clear()
91
+ }
92
+
93
+ private Enumeration<URL > getUrlEnumeration () {
94
+ def urls = temporaryFiles. collect({ it. toURL() }). asList()
95
+ return Collections . enumeration(urls)
96
+ }
97
+
98
+ private void relocatePlugins (PluginCache pluginCache ) {
99
+ for (Map<String , PluginEntry > currentMap : pluginCache. getAllCategories(). values()) {
100
+ pluginEntryLoop :
101
+ for (PluginEntry currentPluginEntry : currentMap. values()) {
102
+ String className = currentPluginEntry. getClassName();
103
+ RelocateClassContext relocateClassContext = new RelocateClassContext (className, new ShadowStats ());
104
+ for (Relocator currentRelocator : relocators) {
105
+ // If we have a relocator that can relocate our current entry...
106
+ boolean canRelocateClass = currentRelocator. canRelocateClass(relocateClassContext);
107
+ if (canRelocateClass) {
108
+ // Then we perform that relocation and update the plugin entry to reflect the new value.
109
+ String relocatedClassName = currentRelocator. relocateClass(relocateClassContext);
110
+ currentPluginEntry. setClassName(relocatedClassName);
111
+ continue pluginEntryLoop;
112
+ }
113
+ }
114
+ }
115
+ }
116
+ }
117
+ }
0 commit comments