【问题标题】:Replace class files before maven assembly在 maven 程序集之前替换类文件
【发布时间】:2013-01-27 15:35:12
【问题描述】:

我面临一个非常独特的情况,需要一些建议: 我正在开发一个项目,该项目依赖于我同一家公司的另一个项目,现在我需要对依赖项进行一些修改。 我遇到的问题是依赖项的源代码已经丢失,所以我唯一拥有的是存储库中的 Maven 依赖项,以及相应的 jar 文件。 最重要的是,Jar 文件中的一些类是使用 JiBX 解析器创建的,映射了一些我没有的 XSD 文件,并且生成的类是合成的,我发现没有反编译器能够正确处理它们。

唯一的好处是我需要更改的类可以正确反编译,所以选择了以下内容:

  • 我反编译了整个 jar 文件并最终得到了一些类( JiBx 那些)具有空的或错误实现的方法。
  • 我注释掉了错误方法的主体以获得存根对象,将所需的更改应用于正确的类并重新编译。
  • 我将旧的 Jar 文件打开,然后手动将旧类替换为新类。

生成的 Jar 按预期工作。

现在我的问题是:我可以使用 Maven 完成所有这些吗?

这个想法是将 JiBX 类文件作为资源,并将存根等效项作为源文件,然后让 maven:

  • 照常编译一切,把所有编译好的类文件 进入目标文件夹
  • 从目标文件夹中删除存根类文件并用旧的预编译类文件替换它们
  • 打包jar。

您会推荐哪种方法?

更新

我给出了一些关于依赖项目结构的更多细节:

所有类都在同一个包中:

my.project.domain.JiBX__c_GeneratedObfuscatedClass1.java
my.project.domain.JiBX__c_GeneratedObfuscatedClass2.java
my.project.domain.JiBX__c_GeneratedObfuscatedClass3.java
my.project.domain.CustomizableClass1.java
my.project.domain.CustomizableClass2.java
my.project.domain.CustomizableClass3.java

JiBX 类未作为依赖项正确导入,如果我尝试将任何 CustmizableClasses 放入项目源中并让 JiBX 类成为依赖项,编译器会报告缺少方法。

我也尝试按照建议使用 Shade Plugin,但由于我需要将 JiBX 类包含到我的源路径中,我最终不得不将来自 jar 依赖项和编译的 CustomizableClasses 的 JiBX 类包含到包中,但跳过 jar 中的 CustomizableClasses dep 并编译 JiBX 类。

我看起来它可以工作,但我承认我仍然没有找到这样做的方法。 任何线索都将受到欢迎。

更新 2(解决方案)

我在这里解释了我最终是如何按照建议使用阴影插件来管理这个的,以防万一其他人也需要这样做:

我终于在同一个包中创建了一个反编译类的项目,并将不想被反编译的方法注释掉。

在 pom.xml 中我添加了以下内容:

<build>
<plugins>
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-shade-plugin</artifactId>
        <version>2.0</version>
        <executions>
            <execution>
                <phase>package</phase>
                <goals>
                    <goal>shade</goal>
                </goals>
                <configuration>
                    <artifactSet>
                        <includes>
                            <include>${project.groupId}:${project.artifactId}</include>
                            <include>TheDamnedProject:WithoutSources</include>
                        </includes>
                    </artifactSet>
                    <filters>
                        <filter>
                            <artifact>TheDamnedProject:WithoutSources</artifact>
                            <includes>
                                <!-- These classes will be taken directly from dependency JAR -->
                                <include>my/package/ClassWhichCouldNotBeDecompiled1.class</include>
                                <include>my/package/ClassWhichCouldNotBeDecompiled2.class</include>
                                <include>my/package/ClassWhichCouldNotBeDecompiled3.class</include>
                                <include>my/package/ClassWhichCouldNotBeDecompiled4.class</include>
                            </includes>
                        </filter>
                        <filter>
                            <artifact>${project.groupId}:${project.artifactId}</artifact>
                            <excludes>
                                <!-- These classes will be overridden by the ones inside the JAR -->
                                <exclude>my/package/ClassWhichCouldNotBeDecompiled1.class</exclude>
                                <exclude>my/package/ClassWhichCouldNotBeDecompiled2.class</exclude>
                                <exclude>my/package/ClassWhichCouldNotBeDecompiled3.class</exclude>
                                <exclude>my/package/ClassWhichCouldNotBeDecompiled4.class</exclude>
                            </excludes>
                        </filter>
                    </filters>
                </configuration>
            </execution>
        </executions>
    </plugin>
</plugins>

谢谢!

卡尔斯

【问题讨论】:

  • 您需要动态发生吗?部署更改后的 JAR 并仅将其作为依赖项引用会有不利影响吗?
  • 我可以手动执行此操作,但这是我第二次需要在短时间内修改此内容,我无法保证下一个开发人员了解发生了什么,所以我更喜欢制作这个尽可能自动化

标签: class maven jar resources package


【解决方案1】:

我会这样做:

  • 为这个 Jar 文件创建一个新的 Maven 项目,打包类型为 jar
  • 包含原始 Jar 文件作为依赖项
  • 在src文件夹中添加一个反编译的.java文件

这应该让您可以编译 .java 文件,因为 jar 文件中的其他类可用。

您现在有两个 Jar 文件:一个是原始文件,另一个应该只包含一个重新编译和更改的类。

将两者都添加到您的应用程序类路径可能有效,但取决于类路径上的顺序。

如果你想最终得到一个 jar 文件,我建议查看 Maven Shade 插件 (http://maven.apache.org/plugins/maven-shade-plugin/),它允许你创建一个包含内容的新 Jar 文件来自多个来源。它将允许您过滤进入新 Jar 文件的内容。

Maven Shade 插件允许您指定包含每个工件的哪些类。它为此使用通配符和包含/排除标签,如下所述:http://maven.apache.org/plugins/maven-shade-plugin/examples/includes-excludes.html

创建该 Jar 文件后,我将使用 Maven Release 插件发布它,然后将该工件包含在下游。这将允许您仅在真正需要时更新已修补的 Jar,它可能不必在每个构建中。但这取决于您的使用模式。

对于新 Jar 文件的版本号,我建议使用原始版本的变体。使用相同的groupIdartifactId,然后修改版本号。如果原始文件有1.0.2,则您的新修补文件应以1.0.2-1 发布,以表明它基于1.0.2 源。如果您需要进行其他更改,请将其发布为1.0.2-2,依此类推。这将使您可以轻松了解您的补丁所基于的版本,并且不断增加的补丁编号将为您提供区分版本的方法。

【讨论】:

  • 哇,反应好快!听起来像是一个选项,但我尝试了类似的方法:创建了一个仅包含 JiBX 类的更薄的 jar,并将其设置为包含要修改的类的项目的依赖项。不知何故,它没有在 JiBX 类中找到一些方法......
  • 您确定所有依赖项都在您创建的 Jar 文件中吗? Shade 插件将允许您指定要从原始 Jar 重用的类,然后添加您自己的类。我建议使用原始版本的修改版本号发布生成的 Jar(请参阅答案,我添加了一些细节)。
  • nwinkler 方法应该有效。也许您的过程中出了点问题。也许对较薄 jar 的版本或内容有些混淆..
  • 我又试了一次,但我仍然看不到使用 Shade 插件执行此操作的方法:我需要包含存根类,否则编译器会报告 JiBX 类中缺少方法(我再次尝试导入薄罐和完整的旧罐)。问题是存根对象与要修改的类在同一个包中,所以我发现没有办法告诉 Shade 插件如何只包含包中的一些类。还有什么线索吗?
  • 您在 Shade 插件上看到此页面了吗? maven.apache.org/plugins/maven-shade-plugin/examples/… 它展示了如何使用通配符(**)过滤每个包中的类。您应该能够将范围缩小到各个类。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-07
  • 2011-01-07
  • 2016-07-09
  • 2012-12-30
相关资源
最近更新 更多