1 /*
  2  * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
  3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  * This code is free software; you can redistribute it and/or modify it
  6  * under the terms of the GNU General Public License version 2 only, as
  7  * published by the Free Software Foundation.
  8  *
  9  * This code is distributed in the hope that it will be useful, but WITHOUT
 10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 12  * version 2 for more details (a copy is included in the LICENSE file that
 13  * accompanied this code).
 14  *
 15  * You should have received a copy of the GNU General Public License version
 16  * 2 along with this work; if not, write to the Free Software Foundation,
 17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 18  *
 19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 20  * or visit www.oracle.com if you need additional information or have any
 21  * questions.
 22  */
 23 
 24 package org.openjdk.skara.gradle.images;
 25 
 26 import org.gradle.api.*;
 27 import org.gradle.api.file.Directory;
 28 import org.gradle.api.tasks.bundling.*;
 29 import org.gradle.api.artifacts.UnknownConfigurationException;
 30 
 31 import java.util.ArrayList;
 32 import java.util.HashSet;
 33 import java.io.File;
 34 
 35 public class ImagesPlugin implements Plugin<Project> {
 36     private static String getOS() {
 37         var p = System.getProperty("os.name").toLowerCase();
 38         if (p.startsWith("win")) {
 39             return "windows";
 40         }
 41         if (p.startsWith("mac")) {
 42             return "macos";
 43         }
 44         if (p.startsWith("linux")) {
 45             return "linux";
 46         }
 47         if (p.startsWith("sunos")) {
 48             return "solaris";
 49         }
 50 
 51         throw new RuntimeException("Unknown operating system: " + System.getProperty("os.name"));
 52     }
 53 
 54     private static String getCPU() {
 55         var p = System.getProperty("os.arch").toLowerCase();
 56         if (p.startsWith("amd64") || p.startsWith("x86_64") || p.startsWith("x64")) {
 57             return "x64";
 58         }
 59         if (p.startsWith("x86") || p.startsWith("i386")) {
 60             return "x86";
 61         }
 62         if (p.startsWith("sparc")) {
 63             return "sparc";
 64         }
 65         if (p.startsWith("ppc")) {
 66             return "ppc";
 67         }
 68         if (p.startsWith("arm")) {
 69             return "arm";
 70         }
 71         if (p.startsWith("aarch64")) {
 72             return "aarch64";
 73         }
 74 
 75         throw new RuntimeException("Unknown CPU: " + System.getProperty("os.arch"));
 76     }
 77 
 78     @Override
 79     public void apply(Project project) {
 80         NamedDomainObjectContainer<ImageEnvironment> imageEnvironmentContainer =
 81             project.container(ImageEnvironment.class, new NamedDomainObjectFactory<ImageEnvironment>() {
 82                 public ImageEnvironment create(String name) {
 83                     return new ImageEnvironment(name, project.getObjects());
 84                 }
 85             });
 86         project.getExtensions().add("images", imageEnvironmentContainer);
 87 
 88         var projectPath = project.getPath();
 89         var taskNames = new ArrayList<String>();
 90         var rootDir = project.getRootDir().toPath().toAbsolutePath();
 91         var buildDir = project.getBuildDir().toPath().toAbsolutePath();
 92 
 93         imageEnvironmentContainer.all(new Action<ImageEnvironment>() {
 94             public void execute(ImageEnvironment env) {
 95                 var parts = env.getName().split("_");;
 96                 var isLocal = parts.length == 1 && parts[0].equals("local");
 97                 var os = isLocal ? getOS() : parts[0];
 98                 var cpu = isLocal ? getCPU() : parts[1];
 99                 var osAndCpuPascalCased =
100                     os.substring(0, 1).toUpperCase() + os.substring(1) +
101                     cpu.substring(0, 1).toUpperCase() + cpu.substring(1);
102                 var subName = isLocal ? "Local" : osAndCpuPascalCased;
103 
104                 var downloadTaskName = "download" + subName + "JDK";
105                 if (!isLocal) {
106                     project.getTasks().register(downloadTaskName, DownloadJDKTask.class, (task) -> {
107                         task.getUrl().set(env.getUrl());
108                         task.getSha256().set(env.getSha256());
109                         task.getToDir().set(rootDir.resolve(".jdk"));
110                     });
111                 }
112 
113                 var linkTaskName = "link" + subName;
114                 project.getTasks().register(linkTaskName, LinkTask.class, (task) -> {
115                     for (var jarTask : project.getTasksByName("jar", true)) {
116                         if (jarTask instanceof Jar) {
117                             task.getModulePath().add(((Jar) jarTask).getArchiveFile());
118                         }
119                     }
120 
121                     try {
122                         var runtimeClasspath = project.getConfigurations().getByName("runtimeClasspath");
123                         task.getRuntimeModules().addAll(runtimeClasspath.getElements());
124                         task.dependsOn(runtimeClasspath);
125                     } catch (UnknownConfigurationException e) {
126                         // ignored
127                     }
128 
129                     if (!isLocal) {
130                         task.dependsOn(projectPath + ":" + downloadTaskName);
131                         task.getUrl().set(env.getUrl());
132                     } else {
133                         task.getUrl().set("local");
134                     }
135                     task.getToDir().set(buildDir.resolve("images"));
136                     task.getOS().set(os);
137                     task.getCPU().set(cpu);
138                     task.getLaunchers().set(env.getLaunchers());
139                     task.getModules().set(env.getModules());
140                 });
141 
142                 var launchersTaskName = "launchers" + subName;
143                 project.getTasks().register(launchersTaskName, LaunchersTask.class, (task) -> {
144                     task.getLaunchers().set(env.getLaunchers());
145                     task.getOptions().set(env.getOptions());
146                     task.getToDir().set(buildDir.resolve("launchers"));
147                     task.getOS().set(os);
148                     task.getCPU().set(cpu);
149                 });
150 
151                 var zipTaskName = "bundleZip" + subName;
152                 project.getTasks().register(zipTaskName, Zip.class, (task) -> {
153                     task.dependsOn(projectPath + ":" + linkTaskName);
154                     task.dependsOn(projectPath + ":" + launchersTaskName);
155 
156                     task.setPreserveFileTimestamps(false);
157                     task.setReproducibleFileOrder(true);
158                     task.getArchiveBaseName().set(project.getName());
159                     task.getArchiveClassifier().set(os + "-" + cpu);
160                     task.getArchiveExtension().set("zip");
161 
162                     if (env.getMan().isPresent()) {
163                         var root = project.getRootProject().getRootDir().toPath().toAbsolutePath();
164                         task.from(root.resolve(env.getMan().get()).toString(), (s) -> {
165                             s.into("bin/man");
166                         });
167                     }
168 
169                     var subdir = os + "-" + cpu;
170                     task.from(buildDir.resolve("images").resolve(subdir), (s) -> {
171                         s.into("image");
172                     });
173                     task.from(buildDir.resolve("launchers").resolve(subdir), (s) -> {
174                         s.into("bin");
175                     });
176                 });
177 
178                 var gzipTaskName = "bundleTarGz" + subName;
179                 project.getTasks().register(gzipTaskName, Tar.class, (task) -> {
180                     task.dependsOn(projectPath + ":" + linkTaskName);
181                     task.dependsOn(projectPath + ":" + launchersTaskName);
182 
183                     task.setPreserveFileTimestamps(false);
184                     task.setReproducibleFileOrder(true);
185                     task.getArchiveBaseName().set(project.getName());
186                     task.getArchiveClassifier().set(os + "-" + cpu);
187                     task.getArchiveExtension().set("tar.gz");
188                     task.setCompression(Compression.GZIP);
189 
190                     if (env.getMan().isPresent()) {
191                         var root = project.getRootProject().getRootDir().toPath().toAbsolutePath();
192                         task.from(root.resolve(env.getMan().get()).toString(), (s) -> {
193                             s.into("bin/man");
194                         });
195                     }
196 
197                     var subdir = os + "-" + cpu;
198                     task.from(buildDir.resolve("images").resolve(subdir), (s) -> {
199                         s.into("image");
200                     });
201                     task.from(buildDir.resolve("launchers").resolve(subdir), (s) -> {
202                         s.into("bin");
203                     });
204                 });
205 
206                 var imageTaskName = "image" + subName;
207                 project.getTasks().register(imageTaskName, DefaultTask.class, (task) -> {
208                     for (var bundle : env.getBundles().get()) {
209                         if (bundle.equals("zip")) {
210                             task.dependsOn(projectPath + ":" + zipTaskName);
211                         } else if (bundle.equals("tar.gz")) {
212                             task.dependsOn(projectPath + ":" + gzipTaskName);
213                         }
214                     }
215                 });
216 
217                 taskNames.add(imageTaskName);
218             }
219         });
220 
221         project.getTasks().register("images", DefaultTask.class, (task) -> {
222             for (var name : taskNames) {
223                 task.dependsOn(projectPath + ":" + name);
224             }
225         });
226     }
227 }