依据pom文件快速获取Jar包源码

一、需求概述

因安全管控,对项目开发过程中引入的jar需要做版本源码扫描,故开发了此工具,实现根据pom文件自动抓取jar源码。

二、实现思路

引入maven-dependency-plugin收集Jar
使用mvn命令下载源码包
集中收集jar和源码包

三、实现过程

1. 通过UI界面提交pom依赖

在这里插入图片描述

2. 将pom依赖填充模板

模板内容为pom.tpl

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.fly</groupId>
	<artifactId>example</artifactId>
	<version>1.0.0</version>
	<name>example</name>
	<url>http://maven.apache.org</url>
	<packaging>pom</packaging>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<java.version>1.8</java.version>
	</properties>

	<!-- 依赖包定义请更新<dependencies></dependencies>内容 -->
	<dependencies>
		 %s
	</dependencies>

	<!-- 阿里云maven仓库 -->
	<repositories>
		<repository>
			<id>public</id>
			<name>aliyun nexus</name>
			<url>https://maven.aliyun.com/repository/public/</url>
			<releases>
				<enabled>true</enabled>
			</releases>
		</repository>
	</repositories>
	<pluginRepositories>
		<pluginRepository>
			<id>public</id>
			<name>aliyun nexus</name>
			<url>https://maven.aliyun.com/repository/public/</url>
			<releases>
				<enabled>true</enabled>
			</releases>
			<snapshots>
				<enabled>false</enabled>
			</snapshots>
		</pluginRepository>
	</pluginRepositories>

	<build>
		<finalName>${project.artifactId}</finalName>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.8.1</version>
				<configuration>
					<source>1.8</source>
					<target>1.8</target>
				</configuration>
			</plugin>

			<!-- 将项目依赖包复制到<outputDirectory>/lib目录下 -->
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-dependency-plugin</artifactId>
				<version>3.1.2</version>
				<executions>
					<execution>
						<id>copy-dependencies</id>
						<phase>package</phase>
						<goals>
							<goal>copy-dependencies</goal>
						</goals>
						<configuration>
							<outputDirectory>${project.build.directory}/lib</outputDirectory>
						</configuration>
					</execution>
				</executions>
			</plugin>
		</plugins>
	</build>
</project>

3. 收集Jar和源码

将模板内容填充参数写入文件后执行mvn clean package -f {pom文件路径},通过maven-dependency-plugin实现了Jar收集到lib目录 ,执行mvn dependency:sources -DdownloadSources=true -f {pom文件路径} 实现jar源码下载,并拷贝到Jar所在lib包。
SimpleSourceUI.java


import java.awt.BorderLayout;
import java.awt.Cursor;
import java.awt.Frame;
import java.awt.HeadlessException;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.InputStream;
import java.net.URL;
import java.nio.charset.StandardCharsets;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;

import com.fly.source.utils.Executor;
import com.fly.source.utils.MvnUtils;

import lombok.extern.slf4j.Slf4j;

/**
 * 
 * 工具UI简化版本
 * 
 * @author 00fly
 * @version [版本号, 2023年3月3日]
 * @see [相关类/方法]
 * @since [产品/模块版本]
 */
@Slf4j
public class SimpleSourceUI extends JFrame
{
    private static final long serialVersionUID = -6346496604061152215L;
    
    JFrame frame = this;
    
    public SimpleSourceUI()
        throws HeadlessException
    {
        initComponent();
        this.setVisible(true);
        this.setResizable(true);
        this.setAlwaysOnTop(true);
        this.setTitle("POM源码工具 V1.0");
        this.setBounds(400, 200, 1200, 550);
        this.setDefaultCloseOperation(EXIT_ON_CLOSE);
        
        try
        {
            // 设定用户界面的外观
            UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
            SwingUtilities.updateComponentTreeUI(this);
        }
        catch (Exception e)
        {
        }
    }
    
    /**
     * 组件初始化
     * 
     * @see [类、类#方法、类#成员]
     */
    private void initComponent()
    {
        // 加载图标
        URL imgURL = getClass().getResource("/img/icon.gif");
        if (imgURL != null)
        {
            setIconImage(getToolkit().createImage(imgURL));
        }
        
        JTextArea textArea = new JTextArea();
        textArea.setToolTipText("请输入dependencies节点内容, 例如:<dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.15.0</version></dependency>");
        textArea.setText("<!-- 请替换下面内容 -->\n<dependency>\n  <groupId>commons-io</groupId>\n  <artifactId>commons-io</artifactId>\n  <version>2.15.0</version>\n</dependency>");
        
        // JTextArea不自带滚动条,因此就需要把文本区放到一个滚动窗格中
        JScrollPane scroll = new JScrollPane(textArea);
        scroll.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
        scroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
        
        JButton button = new JButton(" 获 取 源 码 包 ");
        this.add(scroll, BorderLayout.CENTER);
        this.add(button, BorderLayout.SOUTH);
        button.addMouseListener(new MouseAdapter()
        {
            @Override
            public void mouseClicked(MouseEvent event)
            {
                try
                {
                    setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
                    String dependencies = textArea.getText();
                    if (StringUtils.isBlank(dependencies))
                    {
                        throw new Exception("dependencies节点内容不合法,请修改");
                    }
                    try (InputStream is = QuickSourceUI.class.getResourceAsStream("/pom.tpl"))
                    {
                        String pomTemplate = IOUtils.toString(is, StandardCharsets.UTF_8);
                        String pom = String.format(pomTemplate, dependencies);
                        File dest = new File("upload/pom.xml");
                        FileUtils.writeStringToFile(dest, pom, StandardCharsets.UTF_8, false);
                        
                        // 运行package命令,通过pom文件中的插件maven-dependency-plugin收集jar到lib
                        String pomPath = dest.getCanonicalPath();
                        log.info("pom.xml 文件路径:{}", pomPath);
                        Executor.execute("mvn clean package -f " + pomPath).forEach(log::info);
                        // 收集sources
                        MvnUtils.copyResource(pomPath);
                        setExtendedState(Frame.ICONIFIED);
                    }
                }
                catch (Exception e)
                {
                    JOptionPane.showMessageDialog(frame, e.getMessage(), "系統异常", JOptionPane.ERROR_MESSAGE);
                }
                finally
                {
                    setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
                }
            }
        });
    }
    
    public static void main(String[] args)
    {
        SwingUtilities.invokeLater(() -> new SimpleSourceUI());
    }
}

4、运行结果

在这里插入图片描述

5、针对完整的有依赖关系的pom文件

可直接选择pom文件
在这里插入图片描述
核心代码如下:

QuickSourceUI.java


import java.awt.Dimension;
import java.awt.Frame;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.nio.charset.StandardCharsets;

import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.filechooser.FileFilter;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.time.DateFormatUtils;

import com.fly.source.utils.Executor;
import com.fly.source.utils.MvnUtils;

import lombok.extern.slf4j.Slf4j;

/*****
 * 界面操作展示类
 */
@Slf4j
public class QuickSourceUI extends JFrame
{
    private static final long serialVersionUID = -9154321945329564644L;
    
    // 界面组件
    JPanel panel = new JPanel();
    
    JTextArea textArea = new JTextArea();
    
    JTextField fileText = new JTextField(null, 40);
    
    JButton fileDirBrowse = new JButton("请选择");
    
    JButton runButton = new JButton(" 获 取 源 码 包 ");
    
    // 构造函数
    public QuickSourceUI()
    {
        // 加载图标
        URL imgURL = getClass().getResource("/img/icon.gif");
        if (imgURL != null)
        {
            setIconImage(getToolkit().createImage(imgURL));
        }
        setTitle("POM源码工具 V1.0");
        setSize(1000, 800);
        Dimension screenSize = getToolkit().getScreenSize();
        Dimension frameSize = this.getSize();
        frameSize.height = Math.min(screenSize.height, frameSize.height);
        frameSize.width = Math.min(screenSize.width, frameSize.width);
        setLocation((screenSize.width - frameSize.width) / 2, (screenSize.height - frameSize.height) / 2);
        addMenu();
        addButton();
        copyPomFromJar();
        try
        {
            UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
            SwingUtilities.updateComponentTreeUI(this);
        }
        catch (Exception e)
        {
        }
        setResizable(false);
        setVisible(true);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        fileText.setFocusable(false);
    }
    
    /**
     * jar 拷贝样例pom
     * 
     * @throws IOException
     * 
     */
    private void copyPomFromJar()
    {
        URL url = QuickSourceUI.class.getProtectionDomain().getCodeSource().getLocation();
        if (url.getPath().endsWith(".jar"))
        {
            try (InputStream is = QuickSourceUI.class.getResourceAsStream("/pom.xml"))
            {
                File file = new File(DateFormatUtils.format(System.currentTimeMillis(), "yyyyMMdd-HHmmss") + "-pom.xml");
                FileUtils.copyInputStreamToFile(is, file);
                file.deleteOnExit();
            }
            catch (IOException e)
            {
                log.error(e.getMessage(), e);
            }
        }
    }
    
    // Menu set
    private void addMenu()
    {
        JMenuBar mb = new JMenuBar();
        // 一级菜单
        JMenu conf = new JMenu(" 系 统 ");
        // 子菜单
        JMenuItem exit = new JMenuItem("退出");
        exit.addActionListener(event -> System.exit(0));
        conf.add(exit);
        mb.add(conf);
        JMenu help = new JMenu(" 帮 助 ");
        JMenuItem about = new JMenuItem("关于工具");
        about.addActionListener((ActionEvent event) -> JOptionPane.showMessageDialog(null, "POM源码工具 V1.0,00fly 于2024年11月。\n", "关于本工具", JOptionPane.INFORMATION_MESSAGE));
        help.add(about);
        mb.add(help);
        setJMenuBar(mb);
    }
    
    // JButton set
    private void addButton()
    {
        panel.setLayout(null);
        getContentPane().add(panel);
        
        JLabel textLabel = new JLabel("pom文件内容");
        textLabel.setBounds(20, 10, 120, 18);
        panel.add(textLabel);
        
        JLabel fileLabel = new JLabel("POM文件");
        fileLabel.setBounds(30, 700, 240, 18);
        panel.add(fileLabel);
        
        textArea.setEditable(false);
        
        JScrollPane scroll = new JScrollPane(textArea);
        scroll.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
        scroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
        scroll.setBounds(20, 30, 950, 650);
        panel.add(scroll);
        
        fileText.setBounds(100, 700, 560, 24);
        fileText.setText(new File(" ").getAbsolutePath().trim());
        panel.add(fileText);
        fileDirBrowse.setBounds(680, 700, 80, 25);
        fileDirBrowse.addActionListener(event -> {
            String path = fileText.getText();
            File xmlfile = new File(path);
            if (new File(fileText.getText()).exists())
            {
                xmlfile = new File(path).getParentFile();
            }
            JFileChooser fc = new JFileChooser(xmlfile);
            fc.setFileSelectionMode(JFileChooser.FILES_ONLY);
            fc.setDialogTitle("pom.xml文件选择");
            if (fc.showOpenDialog(null) == JFileChooser.CANCEL_OPTION)
            {
                return;
            }
            fc.setFileFilter(new FileFilter()
            {
                @Override
                public boolean accept(File file)
                {
                    return file.getName().toLowerCase().endsWith(".xml");
                }
                
                @Override
                public String getDescription()
                {
                    return "";
                }
            });
            File f = fc.getSelectedFile();
            if (f != null && f.isFile())
            {
                fileText.setText(f.getAbsolutePath());
                try
                {
                    textArea.setText(FileUtils.readFileToString(f, StandardCharsets.UTF_8));
                    runButton.setEnabled(true);
                }
                catch (IOException e)
                {
                }
            }
        });
        panel.add(fileDirBrowse);
        
        runButton.addMouseListener(new MouseAdapter()
        {
            @Override
            public void mouseClicked(MouseEvent e)
            {
                if (!runButton.isEnabled())
                {
                    return;
                }
                new Thread(() -> {
                    try
                    {
                        runButton.setText(" 处 理 中 ......");
                        runButton.setEnabled(false);
                        
                        // 业务处理
                        String pomPath = fileText.getText();
                        if (!new File(pomPath).exists())
                        {
                            throw new Exception(pomPath + "文件不存在");
                        }
                        
                        // 移动pom文件
                        File dest = new File("upload/pom.xml");
                        FileUtils.copyFile(new File(pomPath), dest);
                        
                        // 运行package命令,通过pom文件中的插件maven-dependency-plugin收集jar到lib
                        pomPath = dest.getCanonicalPath();
                        log.info("pom.xml 文件路径:{}", pomPath);
                        Executor.execute("mvn clean package -f " + pomPath).forEach(log::info);
                        // 收集sources
                        MvnUtils.copyResource(pomPath);
                        setExtendedState(Frame.ICONIFIED);
                        
                        runButton.setText(" 获 取 源 码 包 ");
                        runButton.setEnabled(true);
                    }
                    catch (Exception e1)
                    {
                        JOptionPane.showMessageDialog(null, "失败原因: " + e1.getMessage(), "业务处理失败", JOptionPane.ERROR_MESSAGE);
                    }
                }).start();
            }
        });
        runButton.setBounds(780, 695, 160, 30);
        runButton.setEnabled(false);
        panel.add(runButton);
    }
    
    // Run
    public static void main(String[] args)
    {
        SwingUtilities.invokeLater(() -> new QuickSourceUI());
    }
}

四、源码放送

可执行Jar下载: quick-source-get-0.0.1.jar (6.3M)

swing版:https://gitee.com/00fly/effict-side/tree/master/quick-source-get

springboot版:https://gitee.com/00fly/effict-side/tree/master/quick-source-get-boot


有任何问题和建议,都可以向我提问讨论,大家一起进步,谢谢!

-over-

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值