001/* 002 * JDrupes Builder 003 * Copyright (C) 2026 Michael N. Lipp 004 * 005 * This program is free software: you can redistribute it and/or modify 006 * it under the terms of the GNU Affero General Public License as 007 * published by the Free Software Foundation, either version 3 of the 008 * License, or (at your option) any later version. 009 * 010 * This program is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 013 * GNU Affero General Public License for more details. 014 * 015 * You should have received a copy of the GNU Affero General Public License 016 * along with this program. If not, see <https://www.gnu.org/licenses/>. 017 */ 018 019package org.jdrupes.builder.distribution.internal; 020 021import freemarker.template.Configuration; 022import freemarker.template.Template; 023import freemarker.template.TemplateException; 024import freemarker.template.TemplateExceptionHandler; 025import java.io.IOException; 026import java.io.InputStreamReader; 027import java.io.OutputStream; 028import java.io.OutputStreamWriter; 029import java.nio.charset.StandardCharsets; 030import java.util.HashMap; 031import java.util.List; 032import java.util.Locale; 033import java.util.Map; 034import java.util.stream.Collectors; 035import org.jdrupes.builder.api.BuildException; 036 037/// A base class for distribution builders. 038/// 039public class DistributionBuilder { 040 041 /// Initializes a new distribution builder. 042 /// 043 protected DistributionBuilder() { 044 // Make javadoc happy 045 } 046 047 /// Base configuration. 048 /// 049 /// @return the configuration 050 /// 051 protected Configuration baseConfiguration() { 052 var fmConfig = new Configuration(Configuration.VERSION_2_3_34); 053 fmConfig.setDefaultEncoding("utf-8"); 054 fmConfig.setTemplateExceptionHandler( 055 TemplateExceptionHandler.RETHROW_HANDLER); 056 fmConfig.setLogTemplateExceptions(false); 057 return fmConfig; 058 } 059 060 /// Builds the FreeMarker model. 061 /// 062 /// @param config the configuration 063 /// @param distClassPath the dist class path 064 /// @return the map 065 /// 066 protected Map<String, Object> buildModel( 067 ApplicationConfigurationData config, List<String> distClassPath) { 068 var model = new HashMap<String, Object>(); 069 model.put("applicationName", config.executableName()); 070 model.put("mainClassName", config.mainClassName()); 071 model.put("classpath", 072 distClassPath.stream().collect(Collectors.joining(":"))); 073 model.put("optsEnvironmentVar", config.executableName() 074 .toUpperCase(Locale.getDefault()) 075 .replaceAll("[^A-Z0-9_]", "_") + "_OPTS"); 076 // Fixed, unless we make the bin directory name configurable 077 model.put("appHomeRelativePath", ".."); 078 model.put("defaultJvmOpts", config.applicationJvmOpts().stream() 079 .map(s -> "\"" + s + "\"").collect(Collectors.joining(" "))); 080 return model; 081 } 082 083 /// Adds the unix script. 084 /// 085 /// @param out the out 086 /// @param model the model 087 /// @throws IOException Signals that an I/O exception has occurred. 088 /// 089 protected void addUnixScript(OutputStream out, Map<String, Object> model) 090 throws IOException { 091 var fmConfig = baseConfiguration(); 092 fmConfig.setInterpolationSyntax( 093 Configuration.SQUARE_BRACKET_INTERPOLATION_SYNTAX); 094 Template template = new Template("unix", new InputStreamReader( 095 getClass().getResourceAsStream( 096 "/org/jdrupes/builder/java/unixStartScript.ftl"), 097 StandardCharsets.UTF_8), fmConfig); 098 try { 099 var writer = new OutputStreamWriter(out, StandardCharsets.UTF_8); 100 template.process(model, writer); 101 } catch (TemplateException e) { 102 throw new BuildException().cause(e); 103 } 104 } 105 106 /// Adds the windows bat. 107 /// 108 /// @param out the out 109 /// @param model the model 110 /// @throws IOException Signals that an I/O exception has occurred. 111 /// 112 protected void addWindowsBat(OutputStream out, Map<String, Object> model) 113 throws IOException { 114 var fmConfig = baseConfiguration(); 115 Template template = new Template("windows", new InputStreamReader( 116 getClass().getResourceAsStream( 117 "/org/jdrupes/builder/java/windowsStartScript.ftl"), 118 StandardCharsets.UTF_8), fmConfig); 119 try { 120 var writer = new OutputStreamWriter(out, StandardCharsets.UTF_8); 121 template.process(model, writer); 122 } catch (TemplateException e) { 123 throw new BuildException().cause(e); 124 } 125 } 126 127}