maven ramdisk plugin

一直都想让maven的target目录放在内存盘,但把target mklink在mvn clean后又会消失,不够智能

发现了插件 https://plugin.maven.earcam.io/ramdisk/ 但不兼容 win

https://bitbucket.org/earcam/io.earcam.maven.plugin/src/master/

魔改之,只留一个类即可

parent pom.xml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
<?xml version="1.0"?>
<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>io.earcam.maven</groupId>
    <artifactId>io.earcam.maven.plugin</artifactId>
    <version>0.0.4</version>
    <packaging>pom</packaging>

    <modules>
        <module>io.earcam.maven.plugin.ramdisk</module>
    </modules>

    <properties>
        <version.java.platform>8</version.java.platform>
        <version.java>1.${version.java.platform}</version.java>
        <maven.compiler.source>${version.java}</maven.compiler.source>
        <maven.compiler.target>${version.java}</maven.compiler.target>

        <earcam.project.root.artifactId>io.earcam.maven.plugin</earcam.project.root.artifactId>
        <coordinate.username.project>earcam/${earcam.project.root.artifactId}</coordinate.username.project>
        <version.slf4j>1.7.25</version.slf4j>
        <version.utilitarian>1.2.1</version.utilitarian>
        <version.instrumental>0.1.0</version.instrumental>
        <version.unexceptional>1.0.0</version.unexceptional>
        <version.maven>3.5.4</version.maven>

        <version.this.plugin>${project.version}</version.this.plugin>
    </properties>

    <dependencyManagement>
        <dependencies>

            <dependency>
                <groupId>org.apache.maven</groupId>
                <artifactId>maven-plugin-api</artifactId>
                <version>${version.maven}</version>
            </dependency>

        </dependencies>
    </dependencyManagement>

    <build>
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.7.0</version>
                    <configuration>
                        <source>${maven.compiler.source}</source>
                        <target>${maven.compiler.target}</target>
                        <encoding>utf-8</encoding>
                    </configuration>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>
</project>

io.earcam.maven.plugin.ramdisk\pom.xml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
<?xml version="1.0"?>
<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>

	<parent>
		<groupId>io.earcam.maven</groupId>
		<artifactId>io.earcam.maven.plugin</artifactId>
		<version>0.0.4</version>
	</parent>

	<groupId>io.earcam.maven.plugin</groupId>
	<artifactId>io.earcam.maven.plugin.ramdisk</artifactId>
	<packaging>maven-plugin</packaging>

	<properties>
		<earcam.project.name.short>ramdisk</earcam.project.name.short>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.apache.maven</groupId>
			<artifactId>maven-plugin-api</artifactId>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-invoker-plugin</artifactId>
				<version>3.5.1</version>
				<configuration>
					<goals>
						<goal>package</goal>
					</goals>
				</configuration>
			</plugin>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-shade-plugin</artifactId>
				<version>3.4.1</version>
				<executions>
					<execution>
						<id>fat-jar-for-mvn-home-lib-ext</id>
						<phase>package</phase>
						<goals>
							<goal>shade</goal>
						</goals>
						<configuration>
							<shadedClassifierName>uber</shadedClassifierName>
							<shadedArtifactAttached>true</shadedArtifactAttached>
							<artifactSet>
								<includes>
									<include>io.earcam*:*</include>
								</includes>
							</artifactSet>
						</configuration>
					</execution>
				</executions>
			</plugin>
		</plugins>
	</build>
</project>
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
package io.earcam.maven.plugin.ramdisk;

import org.apache.maven.AbstractMavenLifecycleParticipant;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.model.Scm;
import org.apache.maven.project.MavenProject;
import org.codehaus.plexus.component.annotations.Component;

import java.io.IOException;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.List;

import static io.earcam.maven.plugin.ramdisk.RamdiskBuildExtension.NAME;

@Component(role = AbstractMavenLifecycleParticipant.class, hint = NAME, instantiationStrategy = "singleton")
public class RamdiskBuildExtension extends AbstractMavenLifecycleParticipant {

    static final String NAME = "ramdisk";

    Path tmpFsRoot = Paths.get("z:/");

    @Override
    public void afterProjectsRead(MavenSession session) {

        List<MavenProject> modules = session.getAllProjects();

        modules.forEach(this::createTmpFsBuildDir);
    }

    private void createTmpFsBuildDir(MavenProject project) {

        if (null != project.getPackaging() && project.getPackaging().equals("pom")) {
            return;
        }

        try {
            createTmpFsBuildDir(project, tmpFsRoot);
        } catch (Throwable e) {
            throw new RuntimeException(e);
        }
    }

    static boolean isJunction(Path p) {
        boolean isJunction = false;
        try {
            isJunction = (p.compareTo(p.toRealPath()) != 0);
        } catch (IOException e) {

        }
        return isJunction;
    }

    static void createTmpFsBuildDir(MavenProject project, Path tmpFs) throws IOException {

        Path link = Paths.get(project.getBuild().getDirectory());
        Path linkTarget = tmpFs.resolve(relativePathFor(project));
        if (!linkTarget.toFile().exists()) {
            Files.createDirectories(linkTarget);
        }
        if (!link.toFile().exists()) {
            Runtime runtime = Runtime.getRuntime();
            runtime.exec(new String[]{"cmd", "/c", "mklink", "/j", link.toString(), linkTarget.toString()});
        } else {
            boolean junction = isJunction(link);
            if (!junction) {
                delete(link);
            }
            Runtime runtime = Runtime.getRuntime();
            runtime.exec(new String[]{"cmd", "/c", "mklink", "/j", link.toString(), linkTarget.toString()});
        }

    }

    static Path relativePathFor(MavenProject project) {
        Path linkTarget = Paths.get("maven", project.getGroupId(), project.getArtifactId(), project.getVersion());
        return appendScmTag(project, linkTarget);
    }

    private static Path appendScmTag(MavenProject project, Path linkTarget) {
        Scm scm = project.getScm();
        if (scm != null) {
            String tag = scm.getTag();
            if (tag != null && !tag.isEmpty()) {
                linkTarget = linkTarget.resolve(tag);
            }
        }
        return linkTarget;
    }

    @Override
    public void afterSessionEnd(MavenSession session) {
        session.getAllProjects().forEach(this::createTmpFsBuildDir);
    }


    public static void delete(Path path, LinkOption... options) throws IOException {
        recurse(path, new DeleteVisitor(path, options));
    }

    private static void recurse(Path source, AbstractVisitor visitor) throws IOException {
        boolean noFollow = Arrays.asList(visitor.options).contains(LinkOption.NOFOLLOW_LINKS);
        EnumSet<FileVisitOption> options = noFollow ? EnumSet.noneOf(FileVisitOption.class) : EnumSet.of(FileVisitOption.FOLLOW_LINKS);
        Files.walkFileTree(source, options, Integer.MAX_VALUE, visitor);
    }

    private static final class DeleteVisitor extends AbstractVisitor {
        public DeleteVisitor(Path source, CopyOption... options) {
            super(source, source, options);
        }

        public FileVisitResult postVisitDirectory(Path directory) throws IOException {
            Files.delete(directory);
            return FileVisitResult.CONTINUE;
        }

        public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
            Files.delete(file);
            return FileVisitResult.CONTINUE;
        }
    }

    abstract static class AbstractVisitor extends SimpleFileVisitor<Path> {
        final Path sink;

        final Path source;

        final CopyOption[] options;

        Path sinkSub;

        public AbstractVisitor(Path source, Path sink, CopyOption... options) {
            this.source = source;
            this.sink = sink;
            this.options = options;
        }

        public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
            this.sinkSub = this.sink.resolve(this.source.relativize(dir));
            this.sinkSub.toFile().mkdirs();
            return FileVisitResult.CONTINUE;
        }

        public FileVisitResult postVisitDirectory(Path directory, IOException thrown) throws IOException {
            super.postVisitDirectory(directory, thrown);
            return this.postVisitDirectory(directory);
        }

        protected abstract FileVisitResult postVisitDirectory(Path var1) throws IOException;

        public abstract FileVisitResult visitFile(Path var1, BasicFileAttributes var2) throws IOException;
    }
}