1 package org.apache.maven.plugin.surefire.booterclient;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import org.apache.maven.plugin.surefire.booterclient.lazytestprovider.OutputStreamFlushableCommandline;
23 import org.apache.maven.plugin.surefire.booterclient.output.InPluginProcessDumpSingleton;
24 import org.apache.maven.plugin.surefire.log.api.ConsoleLogger;
25 import org.apache.maven.surefire.booter.AbstractPathConfiguration;
26 import org.apache.maven.surefire.booter.Classpath;
27 import org.apache.maven.surefire.booter.ModularClasspath;
28 import org.apache.maven.surefire.booter.ModularClasspathConfiguration;
29 import org.apache.maven.surefire.booter.StartupConfiguration;
30 import org.apache.maven.surefire.booter.SurefireBooterForkException;
31
32 import javax.annotation.Nonnegative;
33 import javax.annotation.Nonnull;
34 import javax.annotation.Nullable;
35 import java.io.File;
36 import java.io.FileWriter;
37 import java.io.IOException;
38 import java.util.Collection;
39 import java.util.Iterator;
40 import java.util.List;
41 import java.util.Map;
42 import java.util.Properties;
43
44 import static java.io.File.createTempFile;
45 import static java.io.File.pathSeparatorChar;
46 import static org.apache.maven.plugin.surefire.SurefireHelper.escapeToPlatformPath;
47 import static org.apache.maven.shared.utils.StringUtils.replace;
48 import static org.apache.maven.surefire.util.internal.StringUtils.NL;
49
50
51
52
53
54 public class ModularClasspathForkConfiguration
55 extends DefaultForkConfiguration
56 {
57 @SuppressWarnings( "checkstyle:parameternumber" )
58 public ModularClasspathForkConfiguration( @Nonnull Classpath bootClasspath,
59 @Nonnull File tempDirectory,
60 @Nullable String debugLine,
61 @Nonnull File workingDirectory,
62 @Nonnull Properties modelProperties,
63 @Nullable String argLine,
64 @Nonnull Map<String, String> environmentVariables,
65 @Nonnull String[] excludedEnvironmentVariables,
66 boolean debug,
67 @Nonnegative int forkCount,
68 boolean reuseForks,
69 @Nonnull Platform pluginPlatform,
70 @Nonnull ConsoleLogger log )
71 {
72 super( bootClasspath, tempDirectory, debugLine, workingDirectory, modelProperties, argLine,
73 environmentVariables, excludedEnvironmentVariables, debug, forkCount, reuseForks, pluginPlatform, log );
74 }
75
76 @Override
77 protected void resolveClasspath( @Nonnull OutputStreamFlushableCommandline cli, @Nonnull String startClass,
78 @Nonnull StartupConfiguration config, @Nonnull File dumpLogDirectory )
79 throws SurefireBooterForkException
80 {
81 try
82 {
83 AbstractPathConfiguration pathConfig = config.getClasspathConfiguration();
84
85 ModularClasspathConfiguration modularClasspathConfiguration =
86 pathConfig.toRealPath( ModularClasspathConfiguration.class );
87
88 ModularClasspath modularClasspath = modularClasspathConfiguration.getModularClasspath();
89
90 String moduleName = modularClasspath.getModuleNameFromDescriptor();
91 List<String> modulePath = modularClasspath.getModulePath();
92 Collection<String> packages = modularClasspath.getPackages();
93 File patchFile = modularClasspath.getPatchFile();
94 List<String> classpath = toCompleteClasspath( config );
95
96 File argsFile = createArgsFile( moduleName, modulePath, classpath, packages, patchFile, startClass );
97
98 cli.createArg().setValue( "@" + escapeToPlatformPath( argsFile.getAbsolutePath() ) );
99 }
100 catch ( IOException e )
101 {
102 String error = "Error creating args file";
103 InPluginProcessDumpSingleton.getSingleton()
104 .dumpException( e, error, dumpLogDirectory );
105 throw new SurefireBooterForkException( error, e );
106 }
107 }
108
109 @Nonnull
110 File createArgsFile( @Nonnull String moduleName, @Nonnull List<String> modulePath,
111 @Nonnull List<String> classPath, @Nonnull Collection<String> packages,
112 @Nonnull File patchFile, @Nonnull String startClassName )
113 throws IOException
114 {
115 File surefireArgs = createTempFile( "surefireargs", "", getTempDirectory() );
116 if ( isDebug() )
117 {
118 getLogger().debug( "Path to args file: " + surefireArgs.getCanonicalPath() );
119 }
120 else
121 {
122 surefireArgs.deleteOnExit();
123 }
124
125 try ( FileWriter io = new FileWriter( surefireArgs ) )
126 {
127 StringBuilder args = new StringBuilder( 64 * 1024 );
128 if ( !modulePath.isEmpty() )
129 {
130
131 args.append( "--module-path" )
132 .append( NL )
133 .append( '"' );
134
135 for ( Iterator<String> it = modulePath.iterator(); it.hasNext(); )
136 {
137 args.append( replace( it.next(), "\\", "\\\\" ) );
138 if ( it.hasNext() )
139 {
140 args.append( pathSeparatorChar );
141 }
142 }
143
144 args.append( '"' )
145 .append( NL );
146 }
147
148 if ( !classPath.isEmpty() )
149 {
150 args.append( "--class-path" )
151 .append( NL )
152 .append( '"' );
153
154 for ( Iterator<String> it = classPath.iterator(); it.hasNext(); )
155 {
156 args.append( replace( it.next(), "\\", "\\\\" ) );
157 if ( it.hasNext() )
158 {
159 args.append( pathSeparatorChar );
160 }
161 }
162
163 args.append( '"' )
164 .append( NL );
165 }
166
167 args.append( "--patch-module" )
168 .append( NL )
169 .append( moduleName )
170 .append( '=' )
171 .append( '"' )
172 .append( replace( patchFile.getPath(), "\\", "\\\\" ) )
173 .append( '"' )
174 .append( NL );
175
176 for ( String pkg : packages )
177 {
178 args.append( "--add-exports" )
179 .append( NL )
180 .append( moduleName )
181 .append( '/' )
182 .append( pkg )
183 .append( '=' )
184 .append( "ALL-UNNAMED" )
185 .append( NL );
186 }
187
188 args.append( "--add-modules" )
189 .append( NL )
190 .append( moduleName )
191 .append( NL );
192
193 args.append( "--add-reads" )
194 .append( NL )
195 .append( moduleName )
196 .append( '=' )
197 .append( "ALL-UNNAMED" )
198 .append( NL );
199
200 args.append( startClassName );
201
202 String argsFileContent = args.toString();
203
204 if ( isDebug() )
205 {
206 getLogger().debug( "args file content:" + NL + argsFileContent );
207 }
208
209 io.write( argsFileContent );
210
211 return surefireArgs;
212 }
213 }
214 }