package com.vip.saturn.job.plugin.maven; import java.io.File; import java.io.IOException; import java.lang.reflect.Method; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.maven.artifact.Artifact; import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugin.logging.Log; import org.apache.maven.plugins.annotations.Execute; import org.apache.maven.plugins.annotations.LifecyclePhase; import org.apache.maven.plugins.annotations.Mojo; import org.apache.maven.plugins.annotations.Parameter; import org.apache.maven.plugins.annotations.ResolutionScope; import org.apache.maven.project.MavenProject; import com.vip.saturn.job.plugin.maven.utils.IvyGetArtifact; import com.vip.saturn.job.plugin.maven.utils.MavenProjectUtils; import com.vip.saturn.job.plugin.utils.CommonUtils; import org.apache.maven.shared.utils.io.FileUtils; /** * * @author xiaopeng.he * */ @Mojo(name = "run", requiresDependencyResolution = ResolutionScope.RUNTIME) @Execute(phase = LifecyclePhase.COMPILE) public class SaturnJobRunMojo extends AbstractMojo { @Parameter(property = "namespace") private String namespace; @Parameter(property = "executorName") private String executorName; @SuppressWarnings("unchecked") @Override public void execute() throws MojoExecutionException, MojoFailureException { if (!CommonUtils.initSaturnHome()) throw new MojoExecutionException("The ${user.home}/.saturn/caches is not exists"); Log log = getLog(); log.info("Running saturn job"); final MavenProject project = (MavenProject) getPluginContext().get("project"); // 拷贝应用运行时依赖至target/saturn-run目录 File saturnAppLibDir = new File(project.getBuild().getDirectory() + System.getProperty("file.separator") + "saturn-run"); if(!saturnAppLibDir.exists()) { saturnAppLibDir.mkdirs(); } try { List<String> runtimeArtifacts = project.getRuntimeClasspathElements(); for (String path : runtimeArtifacts) { File tmp = new File(path); copy(tmp, saturnAppLibDir ); } } catch (Exception e) { e.printStackTrace(); throw new MojoExecutionException("getRuntimeClasspathElements error", e); } String saturnVersion = getSaturnVersion(project); MavenProjectUtils mavenProjectUtils = new MavenProjectUtils(project, log); IvyGetArtifact ivyGetArtifact = getIvyGetArtifact(mavenProjectUtils); File saturnExecutorZip = getSaturnExecutorZip(ivyGetArtifact, saturnVersion); File saturnHomeCaches = CommonUtils.getSaturnHomeCaches(); try { CommonUtils.unzip(saturnExecutorZip, saturnHomeCaches); } catch (Exception e) { e.printStackTrace(); throw new MojoExecutionException("unzip saturn-executor.zip failed", e); } File saturnExecutorDir = new File(saturnHomeCaches, "saturn-executor-" + saturnVersion); final URLClassLoader executorClassLoader; try { executorClassLoader = new URLClassLoader(new URL[]{new File(saturnExecutorDir, "saturn-executor.jar").toURL()}, ClassLoader.getSystemClassLoader()); } catch (MalformedURLException e) { throw new MojoExecutionException("get saturn-executor classLoad failed", e); } final List<String> argList = new ArrayList<>(); if(namespace != null) { argList.add("-namespace"); argList.add(namespace); } else { throw new MojoExecutionException("the parameter of namespace is required"); } if(executorName != null) { argList.add("-executorName"); argList.add(executorName); } String saturnLibDir = saturnExecutorDir + System.getProperty("file.separator") + "lib"; argList.add("-saturnLibDir"); argList.add(saturnLibDir); argList.add("-appLibDir"); argList.add(saturnAppLibDir.getAbsolutePath()); Thread containerThread = new Thread(new Runnable() { @Override public void run() { try { Thread.currentThread().setContextClassLoader(executorClassLoader); System.setProperty("saturn.stdout", "true"); Class<?> mainClass = executorClassLoader.loadClass("com.vip.saturn.job.executor.Main"); Method mainMethod = mainClass.getMethod("main", String[].class); mainMethod.invoke(mainClass, new Object[]{argList.toArray(new String[argList.size()])}); } catch (Throwable t) { t.printStackTrace(); } } }); containerThread.start(); try { Thread.currentThread().join(); } catch (InterruptedException e) { e.printStackTrace(); throw new MojoExecutionException("current thread join error", e); } } @SuppressWarnings("unchecked") private String getSaturnVersion(MavenProject project) throws MojoExecutionException { List<Artifact> artifacts = project.getRuntimeArtifacts(); if (artifacts != null && !artifacts.isEmpty()) { for (int i = 0; i < artifacts.size(); i++) { Artifact artifact = artifacts.get(i); if ("saturn-job-api".equals(artifact.getArtifactId())) { return artifact.getBaseVersion(); } } } throw new MojoExecutionException("cannot read the saturn-job-core dependency."); } private IvyGetArtifact getIvyGetArtifact(MavenProjectUtils mavenProjectUtils) throws MojoExecutionException { try { return mavenProjectUtils.getIvyGetArtifact(); } catch (Exception e) { throw new MojoExecutionException("get IvyGetArtifact failed", e); } } private File getSaturnExecutorZip(IvyGetArtifact ivyGetArtifact, String saturnVersion) throws MojoExecutionException { Set<Map<String, Object>> executorArtifacts = new HashSet<Map<String, Object>>(); Map<String, Object> executorZip = new HashMap<String, Object>(); executorZip.put("name", "saturn-executor"); executorZip.put("type", "zip"); executorZip.put("ext", "zip"); executorArtifacts.add(executorZip); Map<String, String> extraAttributes = new HashMap<String, String>(); extraAttributes.put("m:classifier", "zip"); executorZip.put("extraAttributes", extraAttributes); List<URL> executorURLs = null; try { executorURLs = ivyGetArtifact.get("com.vip.saturn", "saturn-executor", saturnVersion, new String[] { "master(*)" }, executorArtifacts); } catch (Exception e) { e.printStackTrace(); throw new MojoExecutionException("download saturn-executor failed", e); } if (executorURLs == null || executorURLs.isEmpty()) { throw new MojoExecutionException("download saturn-executor failed"); } return new File(executorURLs.get(0).getFile()); } private static List<URL> getUrls(File file) throws MalformedURLException { List<URL> urls = new ArrayList<>(); if(file.exists()) { if(file.isDirectory()) { File[] files = file.listFiles(); for(File tmp : files) { urls.addAll(getUrls(tmp)); } } else if(file.isFile()) { urls.add(file.toURI().toURL()); } } return urls; } private void copy(File source, File destinationDir) throws IOException { if(source.isFile()) { FileUtils.copyFileToDirectory(source, destinationDir); } else if(source.isDirectory()) { File newDestinationDir = new File(destinationDir, source.getName()); if(!newDestinationDir.exists()) { newDestinationDir.mkdirs(); } for(File tmp : source.listFiles()) { copy(tmp, newDestinationDir); } } } }