holder, Object resource ) {
96 |
97 | LocalizedResource res = new LocalizedResource( parent );
98 | if ( resource instanceof Closure> ) {
99 | parent.getProject().configure( res, (Closure>)resource );
100 | } else {
101 | res.setLocale( parent.getDefaultResourceLanguage() );
102 | res.setResource( resource );
103 | }
104 |
105 | holder.add( res );
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 | @rem SPDX-License-Identifier: Apache-2.0
17 | @rem
18 |
19 | @if "%DEBUG%"=="" @echo off
20 | @rem ##########################################################################
21 | @rem
22 | @rem Gradle startup script for Windows
23 | @rem
24 | @rem ##########################################################################
25 |
26 | @rem Set local scope for the variables with windows NT shell
27 | if "%OS%"=="Windows_NT" setlocal
28 |
29 | set DIRNAME=%~dp0
30 | if "%DIRNAME%"=="" set DIRNAME=.
31 | @rem This is normally unused
32 | set APP_BASE_NAME=%~n0
33 | set APP_HOME=%DIRNAME%
34 |
35 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
36 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
37 |
38 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
39 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
40 |
41 | @rem Find java.exe
42 | if defined JAVA_HOME goto findJavaFromJavaHome
43 |
44 | set JAVA_EXE=java.exe
45 | %JAVA_EXE% -version >NUL 2>&1
46 | if %ERRORLEVEL% equ 0 goto execute
47 |
48 | echo. 1>&2
49 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
50 | echo. 1>&2
51 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2
52 | echo location of your Java installation. 1>&2
53 |
54 | goto fail
55 |
56 | :findJavaFromJavaHome
57 | set JAVA_HOME=%JAVA_HOME:"=%
58 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
59 |
60 | if exist "%JAVA_EXE%" goto execute
61 |
62 | echo. 1>&2
63 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
64 | echo. 1>&2
65 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2
66 | echo location of your Java installation. 1>&2
67 |
68 | goto fail
69 |
70 | :execute
71 | @rem Setup the command line
72 |
73 |
74 |
75 | @rem Execute Gradle
76 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
77 |
78 | :end
79 | @rem End local scope for the variables with windows NT shell
80 | if %ERRORLEVEL% equ 0 goto mainEnd
81 |
82 | :fail
83 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
84 | rem the _cmd.exe /c_ return code!
85 | set EXIT_CODE=%ERRORLEVEL%
86 | if %EXIT_CODE% equ 0 set EXIT_CODE=1
87 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
88 | exit /b %EXIT_CODE%
89 |
90 | :mainEnd
91 | if "%OS%"=="Windows_NT" endlocal
92 |
93 | :omega
94 |
--------------------------------------------------------------------------------
/src/com/inet/gradle/setup/image/image4j/codec/bmp/BMPImage.java:
--------------------------------------------------------------------------------
1 | /*
2 | * BMPImage.java
3 | *
4 | * Created on February 19, 2007, 8:08 AM
5 | *
6 | * To change this template, choose Tools | Template Manager
7 | * and open the template in the editor.
8 | */
9 |
10 | package com.inet.gradle.setup.image.image4j.codec.bmp;
11 |
12 | /**
13 | * Contains a decoded BMP image, as well as information about the source encoded image.
14 | * @since 0.7
15 | * @author Ian McDonagh
16 | */
17 | public class BMPImage {
18 |
19 | protected InfoHeader infoHeader;
20 | protected java.awt.image.BufferedImage image;
21 |
22 | /**
23 | * Creates a new instance of BMPImage
24 | * @param image the decoded image
25 | * @param infoHeader the InfoHeader structure providing information about the source encoded image
26 | */
27 | public BMPImage(java.awt.image.BufferedImage image, InfoHeader infoHeader) {
28 | this.image = image;
29 | this.infoHeader = infoHeader;
30 | }
31 |
32 | /**
33 | * The InfoHeader structure representing the encoded BMP image.
34 | */
35 | public InfoHeader getInfoHeader() {
36 | return infoHeader;
37 | }
38 |
39 | /**
40 | * Sets the InfoHeader structure used for encoding the BMP image.
41 | */
42 | public void setInfoHeader(InfoHeader infoHeader) {
43 | this.infoHeader = infoHeader;
44 | }
45 |
46 | /**
47 | * The decoded BMP image.
48 | */
49 | public java.awt.image.BufferedImage getImage() {
50 | return image;
51 | }
52 |
53 | /**
54 | * Sets the image to be encoded.
55 | */
56 | public void setImage(java.awt.image.BufferedImage image) {
57 | this.image = image;
58 | }
59 |
60 | /**
61 | * The width of the BMP image in pixels.
62 | * @return the width of the BMP image, or -1 if unknown
63 | * @since 0.7alpha2
64 | */
65 | public int getWidth() {
66 | return infoHeader == null ? -1 : infoHeader.iWidth;
67 | }
68 |
69 | /**
70 | * The height of the BMP image in pixels.
71 | * @return the height of the BMP image, or -1 if unknown.
72 | * @since 0.7alpha2
73 | */
74 | public int getHeight() {
75 | return infoHeader == null ? -1 : infoHeader.iHeight;
76 | }
77 |
78 | /**
79 | * The colour depth of the BMP image (bits per pixel).
80 | * @return the colour depth, or -1 if unknown.
81 | * @since 0.7alpha2
82 | */
83 | public int getColourDepth() {
84 | return infoHeader == null ? -1 : infoHeader.sBitCount;
85 | }
86 |
87 | /**
88 | * The number of possible colours for the BMP image.
89 | * @return the number of colours, or -1 if unknown.
90 | * @since 0.7alpha2
91 | */
92 | public int getColourCount() {
93 | int bpp = infoHeader.sBitCount == 32 ? 24 : infoHeader.sBitCount;
94 | return bpp == -1 ? -1 : (int) (1 << bpp);
95 | }
96 |
97 | /**
98 | * Specifies whether this BMP image is indexed, that is, the encoded bitmap uses a colour table.
99 | * If getColourDepth() returns -1 , the return value has no meaning.
100 | * @return true if indexed, false if not.
101 | * @since 0.7alpha2
102 | */
103 | public boolean isIndexed() {
104 | return infoHeader == null ? false : infoHeader.sBitCount <= 8;
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/src/com/oracle/appbundler/Option.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012, Oracle and/or its affiliates. All rights reserved.
3 | *
4 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 | *
6 | * This code is free software; you can redistribute it and/or modify it
7 | * under the terms of the GNU General Public License version 2 only, as
8 | * published by the Free Software Foundation. Oracle designates this
9 | * particular file as subject to the "Classpath" exception as provided
10 | * by Oracle in the LICENSE file that accompanied this code.
11 | *
12 | * This code is distributed in the hope that it will be useful, but WITHOUT
13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 | * version 2 for more details (a copy is included in the LICENSE file that
16 | * accompanied this code).
17 | *
18 | * You should have received a copy of the GNU General Public License version
19 | * 2 along with this work; if not, write to the Free Software Foundation,
20 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21 | *
22 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
23 | * or visit www.oracle.com if you need additional information or have any
24 | * questions.
25 | */
26 |
27 | package com.oracle.appbundler;
28 |
29 | /**
30 | * Class representing an option that will be passed to the JVM at startup.
31 | * The class can optionally be named, which allows the bundled Java program
32 | * itself to override the option. Changes will take effect upon restart of the
33 | * application.
34 | * Assuming your {@code CFBundleIdentifier} (settable via {@link AppBundlerTask#setIdentifier(String)})
35 | * is {@code com.oracle.appbundler}. Then you can override a named option by calling
36 | *
37 | * import java.util.prefs.Preferences;
38 | * [...]
39 | * Preferences jvmOptions = Preferences.userRoot().node("/com/oracle/appbundler/JVMOptions");
40 | * jvmOptions.put("name", "value");
41 | * jvmOptions.flush();
42 | *
43 | * The corresponding entries will be stored in a file called
44 | * {@code ~/Library/Preferences/com.oracle.appbundler.plist}.
45 | * To manipulate the file without Java's {@link java.util.prefs.Preferences} from the command line,
46 | * you should use the tool
47 | * defaults .
48 | * For example, to add an entry via the command line, use:
49 | *
50 | * defaults write com.oracle.appbundler /com/oracle/appbundler/ -dict-add JVMOptions/ '{"name"="value";}'
51 | *
52 | *
53 | * @author Hendrik Schreiber (preference related code only)
54 | */
55 | public class Option {
56 | private String value = null;
57 | private String name = null;
58 |
59 | public String getValue() {
60 | return value;
61 | }
62 |
63 | public void setValue(String value) {
64 | this.value = value;
65 | }
66 |
67 | public String getName() {
68 | return name;
69 | }
70 |
71 | public void setName(final String name) {
72 | this.name = name;
73 | }
74 |
75 | @Override
76 | public String toString() {
77 | return name == null ? value : name + "=" + value;
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/src/test/java/com/inet/gradle/setup/msi/PlatformDetectionTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2024 i-net software
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.inet.gradle.setup.msi;
17 |
18 | import static org.junit.Assert.assertEquals;
19 | import static org.junit.Assert.assertNotNull;
20 | import static org.junit.Assert.assertTrue;
21 |
22 | import java.io.File;
23 |
24 | import org.gradle.internal.os.OperatingSystem;
25 | import org.junit.Test;
26 |
27 | /**
28 | * Tests for Phase 1: Platform Detection & Path Handling
29 | */
30 | public class PlatformDetectionTest {
31 |
32 | private static final OperatingSystem OS = OperatingSystem.current();
33 |
34 | @Test
35 | public void testPlatformDetection() {
36 | // At least one platform should be detected
37 | assertTrue("Platform should be detected",
38 | OS.isWindows() || OS.isLinux() || OS.isMacOsX());
39 | }
40 |
41 | @Test
42 | public void testFileSeparator() {
43 | String separator = File.separator;
44 | assertNotNull("File separator should not be null", separator);
45 | assertEquals("File separator should be single character", 1, separator.length());
46 |
47 | // Should be either / or \ depending on platform
48 | assertTrue("File separator should be / or \\",
49 | separator.equals("/") || separator.equals("\\"));
50 |
51 | // Unix-like systems should use /
52 | if (OS.isLinux() || OS.isMacOsX()) {
53 | assertEquals("Unix systems should use /", "/", separator);
54 | }
55 | }
56 |
57 | @Test
58 | public void testPathSeparator() {
59 | String pathSeparator = File.pathSeparator;
60 | assertNotNull("Path separator should not be null", pathSeparator);
61 | assertTrue("Path separator should not be empty", pathSeparator.length() > 0);
62 |
63 | // Unix-like systems should use :
64 | if (OS.isLinux() || OS.isMacOsX()) {
65 | assertEquals("Unix systems should use :", ":", pathSeparator);
66 | }
67 | // Windows should use ;
68 | else if (OS.isWindows()) {
69 | assertEquals("Windows should use ;", ";", pathSeparator);
70 | }
71 | }
72 |
73 | @Test
74 | public void testOperatingSystemInstance() {
75 | assertNotNull("OperatingSystem instance should not be null", OS);
76 | }
77 |
78 | @Test
79 | public void testPlatformSpecificChecks() {
80 | // Only one platform should be true at a time
81 | int platformCount = 0;
82 | if (OS.isWindows()) platformCount++;
83 | if (OS.isLinux()) platformCount++;
84 | if (OS.isMacOsX()) platformCount++;
85 |
86 | assertEquals("Exactly one platform should be detected", 1, platformCount);
87 | }
88 | }
89 |
90 |
--------------------------------------------------------------------------------
/src/com/inet/gradle/setup/msi/CommandLine.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 - 2017 i-net software
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.inet.gradle.setup.msi;
17 |
18 | import com.inet.gradle.setup.abstracts.Application;
19 |
20 | /**
21 | * Get the parts of a windows command line.
22 | */
23 | class CommandLine {
24 |
25 | final String relativTarget; // executable inside the installation
26 | final String relativFull; // executable inside the installation
27 | final String target;
28 | final String arguments;
29 | final String full;
30 | final String workDir;
31 |
32 | /**
33 | * Generate the parts of the command line.
34 | * @param starter a command description
35 | * @param javaDir path to java if embedded
36 | */
37 | CommandLine( Application starter, String javaDir ) {
38 | String target = starter.getExecutable();
39 | String arguments = starter.getStartArguments();
40 | String vmArguments = String.join( " ", starter.getJavaVMArguments() ).trim();
41 | String dir;
42 | String workDir = starter.getWorkDir();
43 | if( workDir == null ) {
44 | workDir = "";
45 | } else {
46 | workDir = workDir.replace( '/', '\\' );
47 | if( !workDir.isEmpty() && !workDir.endsWith( "\\" ) ){
48 | workDir += '\\';
49 | }
50 | }
51 | if( target == null || target.isEmpty() ) {
52 | if( javaDir != null ) {
53 | target = "[INSTALLDIR]" + javaDir + "\\bin\\javaw.exe";
54 | } else {
55 | target = "javaw.exe";
56 | }
57 | dir = "";
58 | arguments = vmArguments + " -cp \"[INSTALLDIR]" + workDir + starter.getMainJar() + "\" " + starter.getMainClass() + " " + arguments;
59 | } else {
60 | if( !target.startsWith( "[" ) ) {
61 | dir = "[INSTALLDIR]";
62 | target = workDir + target;
63 | } else {
64 | dir = "";
65 | }
66 | }
67 | this.relativTarget = target;
68 | this.target = dir + target;
69 | this.arguments = arguments;
70 | if( this.target.indexOf( ' ' ) >= 0 || this.target.indexOf( '[' ) >= 0 ) {
71 | this.full = '\"' + this.target + "\" " + arguments;
72 | } else {
73 | this.full = this.target + ' ' + arguments;
74 | }
75 | if( this.relativTarget.indexOf( ' ' ) >= 0 || this.relativTarget.indexOf( '[' ) >= 0 ) {
76 | this.relativFull = '\"' + this.relativTarget + "\" " + arguments;
77 | } else {
78 | this.relativFull = this.relativTarget + ' ' + arguments;
79 | }
80 | this.workDir = workDir;
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/src/com/inet/gradle/setup/image/image4j/io/LittleEndianOutputStream.java:
--------------------------------------------------------------------------------
1 | /*
2 | * LittleEndianOutputStream.java
3 | *
4 | * Created on 07 November 2006, 08:26
5 | *
6 | * To change this template, choose Tools | Template Manager
7 | * and open the template in the editor.
8 | */
9 |
10 | package com.inet.gradle.setup.image.image4j.io;
11 |
12 | import java.io.DataOutputStream;
13 | import java.io.IOException;
14 |
15 | /**
16 | * Writes little-endian data to a target OutputStream by reversing byte ordering.
17 | * @author Ian McDonagh
18 | */
19 | public class LittleEndianOutputStream extends DataOutputStream {
20 |
21 | /**
22 | * Creates a new instance of LittleEndianOutputStream , which will write to the specified target.
23 | * @param out the target OutputStream
24 | */
25 | public LittleEndianOutputStream(java.io.OutputStream out) {
26 | super(out);
27 | }
28 |
29 | /**
30 | * Writes a little-endian short value
31 | * @param value the source value to convert
32 | * @throws java.io.IOException if an error occurs
33 | */
34 | public void writeShortLE(short value) throws IOException {
35 | value = EndianUtils.swapShort(value);
36 | super.writeShort(value);
37 | }
38 |
39 | /**
40 | * Writes a little-endian int value
41 | * @param value the source value to convert
42 | * @throws java.io.IOException if an error occurs
43 | */
44 | public void writeIntLE(int value) throws IOException {
45 | value = EndianUtils.swapInteger(value);
46 | super.writeInt(value);
47 | }
48 |
49 | /**
50 | * Writes a little-endian float value
51 | * @param value the source value to convert
52 | * @throws java.io.IOException if an error occurs
53 | */
54 | public void writeFloatLE(float value) throws IOException {
55 | value = EndianUtils.swapFloat(value);
56 | super.writeFloat(value);
57 | }
58 |
59 | /**
60 | * Writes a little-endian long value
61 | * @param value the source value to convert
62 | * @throws java.io.IOException if an error occurs
63 | */
64 | public void writeLongLE(long value) throws IOException {
65 | value = EndianUtils.swapLong(value);
66 | super.writeLong(value);
67 | }
68 |
69 | /**
70 | * Writes a little-endian double value
71 | * @param value the source value to convert
72 | * @throws java.io.IOException if an error occurs
73 | */
74 | public void writeDoubleLE(double value) throws IOException {
75 | value = EndianUtils.swapDouble(value);
76 | super.writeDouble(value);
77 | }
78 |
79 | /**
80 | * @since 0.6
81 | */
82 | public void writeUnsignedInt(long value) throws IOException {
83 | int i1 = (int)(value >> 24);
84 | int i2 = (int)((value >> 16) & 0xFF);
85 | int i3 = (int)((value >> 8) & 0xFF);
86 | int i4 = (int)(value & 0xFF);
87 |
88 | write(i1);
89 | write(i2);
90 | write(i3);
91 | write(i4);
92 | }
93 |
94 | /**
95 | * @since 0.6
96 | */
97 | public void writeUnsignedIntLE(long value) throws IOException {
98 | int i1 = (int)(value >> 24);
99 | int i2 = (int)((value >> 16) & 0xFF);
100 | int i3 = (int)((value >> 8) & 0xFF);
101 | int i4 = (int)(value & 0xFF);
102 |
103 | write(i4);
104 | write(i3);
105 | write(i2);
106 | write(i1);
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/src/com/inet/gradle/appbundler/AppBundlerGradleTask.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 i-net software
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.inet.gradle.appbundler;
18 |
19 | import java.io.File;
20 |
21 | import org.gradle.api.Action;
22 | import org.gradle.api.GradleException;
23 | import org.gradle.api.tasks.Input;
24 | import org.gradle.api.tasks.Nested;
25 | import org.gradle.api.tasks.Optional;
26 | import org.gradle.api.tasks.TaskAction;
27 |
28 | import com.inet.gradle.setup.abstracts.AbstractTask;
29 |
30 | import groovy.lang.Closure;
31 |
32 | /**
33 | * Task to create a .app archive
34 | * @author gamma
35 | */
36 | public class AppBundlerGradleTask extends AbstractTask {
37 |
38 | private OSXCodeSign codeSign;
39 |
40 | /**
41 | * Construct static as .app
42 | */
43 | public AppBundlerGradleTask() {
44 | super( "app", AppBundler.class );
45 | }
46 |
47 | /**
48 | * Get the app builder
49 | * @return the app builder
50 | */
51 | @Nested
52 | @Optional
53 | public AppBundler getAppBuilder() {
54 | return (AppBundler)super.getAbstractSetupBuilder();
55 | }
56 |
57 | /**
58 | * {@inheritDoc}
59 | */
60 | @Override
61 | public void build() {
62 | new AppBundlerBuilder( this, getAppBuilder(), getFileResolver() ).build();
63 | }
64 |
65 | /**
66 | * The action called from Gradle
67 | * Will not add an artifact since it would be a directory.
68 | */
69 | @TaskAction
70 | public void action() {
71 | build();
72 | File setupFile = getSetupFile();
73 | if( !setupFile.exists() ) {
74 | throw new GradleException( "Setup file was not created: " + setupFile );
75 | }
76 | }
77 |
78 | /**
79 | * Set the needed information for signing the setup.
80 | *
81 | * @param closure the data for signing
82 | */
83 | public void codeSign( Closure closure ) {
84 | codeSign = new OSXCodeSign( this, getFileResolver() );
85 | getProject().configure( codeSign, closure );
86 | }
87 |
88 | /**
89 | * Set the needed information for signing the setup.
90 | *
91 | * @param action the data for signing
92 | */
93 | public void codeSign( Action super OSXCodeSign super AppBundlerGradleTask,? super AppBundler>> action ) {
94 | codeSign = new OSXCodeSign<>( this, getFileResolver() );
95 | action.execute( codeSign );
96 | }
97 |
98 | /**
99 | * Get the SignTool configuration if set
100 | *
101 | * @return the settings or null
102 | */
103 | @Input
104 | @Optional
105 | public OSXCodeSign getCodeSign() {
106 | return codeSign;
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/src/com/inet/gradle/setup/util/GradleUtils.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019 i-net software
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.inet.gradle.setup.util;
17 |
18 | import java.util.List;
19 | import java.util.Objects;
20 | import java.util.Set;
21 |
22 | import org.gradle.api.Project;
23 | import org.gradle.api.Task;
24 | import org.gradle.api.tasks.TaskContainer;
25 |
26 | public abstract class GradleUtils {
27 |
28 | /**
29 | * Checked if the given task will be executed because set in command line or depends on other executed task.
30 | *
31 | * @param task the task to check
32 | * @param project the current project
33 | * @return true, if the task will be executed
34 | */
35 | public static boolean isTaskExecute( Task task, Project project ) {
36 | String name = task.getName();
37 | List startTasks = project.getGradle().getStartParameter().getTaskNames();
38 | TaskContainer tasks = project.getTasks();
39 | for( String startTaskName : startTasks ) {
40 | if( Objects.equals( name, startTaskName ) || startTaskName.endsWith( ":" + name ) ) {
41 | // direct call of the task in the command line
42 | return true;
43 | }
44 | try {
45 | Task startTask = tasks.getByName( startTaskName );
46 | if( isTaskExecute( task, name, startTask, tasks ) ) {
47 | return true;
48 | }
49 | } catch( Throwable th ) {
50 | // can occur if there is a circle in the dependsOn
51 | }
52 | }
53 |
54 | return false;
55 | }
56 |
57 | /**
58 | * Checked if the given task will be executed because set in command line or depends on other executed task.
59 | *
60 | * @param task the task to check
61 | * @param name the name to check
62 | * @param startTask a task that will be executed
63 | * @param tasks all tasks
64 | * @return true, if the task will be executed
65 | */
66 | private static boolean isTaskExecute( Task task, String name, Task startTask, TaskContainer tasks ) {
67 | if( startTask == null ) {
68 | return false;
69 | }
70 | Set dependsOn = startTask.getDependsOn(); // can contain a task name, a task or other objects
71 | for( Object depObject : dependsOn ) {
72 | if( Objects.equals( name, depObject ) ) {
73 | return true;
74 | }
75 | if( Objects.equals( task, depObject ) ) {
76 | return true;
77 | }
78 | Task depTask = null;
79 | if( depObject instanceof String ) {
80 | depTask = tasks.getByName( (String)depObject );
81 | } else if( depObject instanceof Task ) {
82 | depTask = (Task)depObject;
83 | }
84 | if( isTaskExecute( task, name, depTask, tasks ) ) {
85 | return true;
86 | }
87 | }
88 | return false;
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/src/com/inet/gradle/setup/dmg/preferences/Common/Service.m:
--------------------------------------------------------------------------------
1 | //
2 | // Service.m
3 | // LaunchRocket
4 | //
5 | // Created by Josh Butts on 3/26/13.
6 | // Copyright (c) 2013 Josh Butts. All rights reserved.
7 | //
8 |
9 | #import "Service.h"
10 | #import "Variables.h"
11 | #import "NSString+MD5.h"
12 |
13 | @implementation Service
14 |
15 | @synthesize plist;
16 | @synthesize identifier;
17 | @synthesize name;
18 | @synthesize useSudo;
19 | @synthesize runAtBoot;
20 | @synthesize description;
21 | @synthesize version;
22 | @synthesize program;
23 | @synthesize starter;
24 |
25 | - (id) initWithPlistURL:(NSURL *)plistURL
26 | {
27 | if ( self = [super init] ) {
28 |
29 | self.plist = plistURL;
30 |
31 | NSDictionary *plistData = [[NSDictionary alloc] initWithContentsOfURL:self.plist];
32 | self.identifier = [plistData objectForKey:@"Label"];
33 | self.name = [plistData objectForKey:@"Name"];
34 |
35 | NSNumber *shouldUseSudo = [plistData objectForKey:@"RunAsRoot"];
36 | if (shouldUseSudo == nil) {
37 | self.useSudo = NO;
38 | } else {
39 | self.useSudo = [shouldUseSudo boolValue];
40 | }
41 |
42 | NSNumber *shouldRunAtLogin = [plistData objectForKey:@"RunAtBoot"];
43 | if (shouldRunAtLogin == nil) {
44 | self.runAtBoot = NO;
45 | } else {
46 | self.runAtBoot = [shouldRunAtLogin boolValue];
47 | }
48 |
49 | description = [plistData objectForKey:@"Description"];
50 | version = [plistData objectForKey:@"Version"];
51 | program = [plistData objectForKey:@"Program"];
52 | starter = [plistData objectForKey:@"starter"]; // List of starter actions for the pref pane
53 | }
54 |
55 | return self;
56 | }
57 |
58 | - (NSString *)pathForService {
59 |
60 | NSString *plistFile = [NSString stringWithFormat:@"/tmp/%@.plist", self.identifier];
61 | if (self.runAtBoot) {
62 | if (self.useSudo) {
63 | plistFile = [NSString stringWithFormat:@"%@/%@.plist", LAUNCHDAEMONS_PATH, self.identifier];
64 | } else {
65 | plistFile = [NSString stringWithFormat:@"%@%@/%@.plist", NSHomeDirectory(), LAUNCHAGENTS_PATH, self.identifier];
66 | }
67 | plistFile =[NSString stringWithFormat:@"%@/%@.plist", LAUNCHDAEMONS_PATH, self.identifier];
68 | }
69 |
70 | /* DLog(@"Path for service: %@", plistFile); */
71 | return plistFile;
72 | }
73 |
74 | - (NSDictionary *)starterForHash:(const char*)md5 {
75 |
76 | for ( NSDictionary *starter in self->starter ) {
77 | if ( [[Service actionFor:starter] isEqualToMD5CString:md5] ) {
78 | return starter;
79 | }
80 | }
81 | return nil;
82 | }
83 |
84 | /**
85 | Determin the user for the given Starter
86 | */
87 | + (NSString *)userFor:(NSDictionary *)starter {
88 | NSString *user = [starter valueForKey:@"asuser"];
89 | return user != nil ? user : @"root";
90 | }
91 |
92 | /**
93 | Determin the title for the given Starter
94 | */
95 | + (NSString *)titleFor:(NSDictionary *)starter {
96 |
97 | NSString *title = [starter valueForKey:@"title"];
98 | NSString *asRootString = localized(@"runAsRoot");
99 |
100 | if ( [self runAsRoot:starter] ) {
101 | title = [title stringByAppendingString:[NSString stringWithFormat:asRootString, [self userFor:starter]]];
102 | }
103 |
104 | return title;
105 | }
106 |
107 | + (NSString *)actionFor:(NSDictionary *)starter {
108 | return [starter valueForKey:@"action"];
109 | }
110 |
111 | + (BOOL)runAsRoot:(NSDictionary *)starter {
112 | return [[starter valueForKey:@"asroot"] boolValue];
113 | }
114 |
115 | @end
116 |
--------------------------------------------------------------------------------
/src/com/inet/gradle/setup/dmg/template/preinstall.createuser.txt:
--------------------------------------------------------------------------------
1 |
2 | DEAMON_USER="{{daemonUser}}"
3 | HOME_DIRECTORY="{{homeDirectory}}"
4 | SERVICE_DESCRIPTION="{{displayName}}"
5 |
6 | if [ -z "${DEAMON_USER}" ]; then
7 | echo "The User that you want to create has to be set."
8 | exit 1
9 | fi
10 |
11 | if [ -z "${HOME_DIRECTORY}" ]; then
12 | HOME_DIRECTORY="/Users/${DEAMON_USER}"
13 | fi
14 |
15 | # find the next UID and GID that is below 500, so that we can create the service user
16 | # if the user or group already exists, it will use this existing ID and still do the rest. We might have changes to commit.
17 | OLDUID=$(dscl . -read "/Users/${DEAMON_USER}" UniqueID 2> /dev/null | awk '{print $2}')
18 | OLDGID=$(dscl . -read "/Groups/${DEAMON_USER}" PrimaryGroupID 2> /dev/null | awk '{print $2}')
19 |
20 | NEXTUID=$([ -n "$OLDUID" ] && echo "$OLDUID" || dscl . -list /Users UniqueID | awk 'BEGIN{i=0}{if($2>i&&$2<500)i=$2}END{print i+1}')
21 | NEXTGID=$([ -n "$OLDGID" ] && echo "$OLDGID" || dscl . -list /Groups PrimaryGroupID | awk 'BEGIN{i=0}{if($2>i&&$2<500)i=$2}END{print i+1}')
22 |
23 | echo "I am Batman, or: $(whoami)"
24 | echo "Will use '${NEXTUID}' as UserID and '${NEXTGID}' as group ID for User '${DEAMON_USER}'"
25 |
26 | #########################################################################################################
27 | # Create Group
28 | [ -z "$OLDGID" ] && dscl . -create "/Groups/${DEAMON_USER}" PrimaryGroupID "${NEXTGID}" || echo "Group already existed"
29 | # Unusable password for standard user group
30 | [ -z "$OLDGID" ] && dscl . -create "/Groups/${DEAMON_USER}" Password \* || echo "Password for group not set"
31 | #########################################################################################################
32 |
33 | #########################################################################################################
34 | # Create User
35 | [ -z "$OLDUID" ] && dscl . -create "/Users/${DEAMON_USER}" UniqueID "${NEXTUID}" || echo "User already existed"
36 | [ -z "$OLDUID" ] && dscl . -create "/Users/${DEAMON_USER}" PrimaryGroupID "${NEXTGID}" || echo "User already existed, not setting PrimaryGroupID"
37 | dscl . -create "/Users/${DEAMON_USER}" NFSHomeDirectory "${HOME_DIRECTORY}" || echo "NFSHomeDirectory can not be set"
38 |
39 | # Can't login as standard user
40 | dscl . -create "/Users/${DEAMON_USER}" UserShell /usr/bin/false || echo "UserShell can not be set"
41 | dscl . -create "/Users/${DEAMON_USER}" RealName "${SERVICE_DESCRIPTION} Administrator" || echo "RealName can not be set"
42 |
43 | # Revoke Permissions
44 | dscl . -delete "/Users/${DEAMON_USER}" PasswordPolicyOptions || echo "PasswordPolicyOptions can not be removed"
45 | dscl . -delete "/Users/${DEAMON_USER}" AuthenticationAuthority || echo "AuthenticationAuthority can not be removed"
46 |
47 | # Unusable password for standard users
48 | dscl . -create "/Users/${DEAMON_USER}" Password \* || echo "Password can not be set"
49 |
50 | # Add user to group user and staff, but check first! Mojave removed the user group
51 | dseditgroup -o edit -a "${DEAMON_USER}" -t "$(dscl . -read "/Groups/user" RecordName 2> /dev/null | awk '{print $2}')" "$(dscl . -read "/Groups/staff" RecordName 2> /dev/null | awk '{print $2}')" || echo "Default groups could not be added to user"
52 | #########################################################################################################
53 |
54 | # make home directory
55 | [ ! -d "${HOME_DIRECTORY}" ] && mkdir -p "${HOME_DIRECTORY}/Library/Preferences" || echo "HomeDirectory and preferences should already exist"
56 | [ -d "${HOME_DIRECTORY}" ] && chown -R "${DEAMON_USER}:${DEAMON_USER}" "${HOME_DIRECTORY}" || echo "Directory permissions have been set before"
57 |
--------------------------------------------------------------------------------
/src/com/inet/gradle/setup/image/image4j/io/LittleEndianInputStream.java:
--------------------------------------------------------------------------------
1 | /*
2 | * LittleEndianInputStream.java
3 | *
4 | * Created on 07 November 2006, 08:26
5 | *
6 | * To change this template, choose Tools | Template Manager
7 | * and open the template in the editor.
8 | */
9 |
10 | package com.inet.gradle.setup.image.image4j.io;
11 |
12 | import java.io.EOFException;
13 | import java.io.IOException;
14 |
15 | /**
16 | * Reads little-endian data from a source InputStream by reversing byte ordering.
17 | * @author Ian McDonagh
18 | */
19 | public class LittleEndianInputStream extends java.io.DataInputStream {
20 |
21 | /**
22 | * Creates a new instance of LittleEndianInputStream , which will read from the specified source.
23 | * @param in the source InputStream
24 | */
25 | public LittleEndianInputStream(java.io.InputStream in) {
26 | super(in);
27 | }
28 |
29 | /**
30 | * Reads a little-endian short value
31 | * @throws java.io.IOException if an error occurs
32 | * @return short value with reversed byte order
33 | */
34 | public short readShortLE() throws IOException {
35 |
36 | int b1 = read();
37 | int b2 = read();
38 |
39 | if (b1 < 0 || b2 < 0) {
40 | throw new EOFException();
41 | }
42 |
43 | short ret = (short) ((b2 << 8) + (b1 << 0));
44 |
45 | return ret;
46 | }
47 |
48 | /**
49 | * Reads a little-endian int value.
50 | * @throws java.io.IOException if an error occurs
51 | * @return int value with reversed byte order
52 | */
53 | public int readIntLE() throws IOException {
54 | int b1 = read();
55 | int b2 = read();
56 | int b3 = read();
57 | int b4 = read();
58 |
59 | if (b1 < -1 || b2 < -1 || b3 < -1 || b4 < -1) {
60 | throw new EOFException();
61 | }
62 |
63 | int ret = (b4 << 24) + (b3 << 16) + (b2 << 8) + (b1 << 0);
64 |
65 | return ret;
66 | }
67 |
68 | /**
69 | * Reads a little-endian float value.
70 | * @throws java.io.IOException if an error occurs
71 | * @return float value with reversed byte order
72 | */
73 | public float readFloatLE() throws IOException {
74 | int i = readIntLE();
75 |
76 | float ret = Float.intBitsToFloat(i);
77 |
78 | return ret;
79 | }
80 |
81 | /**
82 | * Reads a little-endian long value.
83 | * @throws java.io.IOException if an error occurs
84 | * @return long value with reversed byte order
85 | */
86 | public long readLongLE() throws IOException {
87 |
88 | int i1 = readIntLE();
89 | int i2 = readIntLE();
90 |
91 | long ret = ((long)(i1) << 32) + (i2 & 0xFFFFFFFFL);
92 |
93 | return ret;
94 | }
95 |
96 | /**
97 | * Reads a little-endian double value.
98 | * @throws java.io.IOException if an error occurs
99 | * @return double value with reversed byte order
100 | */
101 | public double readDoubleLE() throws IOException {
102 |
103 | long l = readLongLE();
104 |
105 | double ret = Double.longBitsToDouble(l);
106 |
107 | return ret;
108 | }
109 |
110 | /**
111 | * @since 0.6
112 | */
113 | public long readUnsignedInt() throws IOException {
114 | long i1 = readUnsignedByte();
115 | long i2 = readUnsignedByte();
116 | long i3 = readUnsignedByte();
117 | long i4 = readUnsignedByte();
118 |
119 | long ret = ((i1 << 24) | (i2 << 16) | (i3 << 8) | i4);
120 |
121 | return ret;
122 | }
123 |
124 | /**
125 | * @since 0.6
126 | */
127 | public long readUnsignedIntLE() throws IOException {
128 | long i1 = readUnsignedByte();
129 | long i2 = readUnsignedByte();
130 | long i3 = readUnsignedByte();
131 | long i4 = readUnsignedByte();
132 |
133 | long ret = (i4 << 24) | (i3 << 16) | (i2 << 8) | i1;
134 |
135 | return ret;
136 | }
137 | }
138 |
--------------------------------------------------------------------------------
/src/test/java/com/inet/gradle/setup/msi/Launch4jClassifierTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2024 i-net software
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.inet.gradle.setup.msi;
17 |
18 | import static org.junit.Assert.assertEquals;
19 | import static org.junit.Assert.assertFalse;
20 | import static org.junit.Assert.assertNotNull;
21 | import static org.junit.Assert.assertTrue;
22 |
23 | import java.util.Arrays;
24 | import java.util.HashSet;
25 | import java.util.Set;
26 |
27 | import org.gradle.internal.os.OperatingSystem;
28 | import org.junit.Test;
29 |
30 | /**
31 | * Tests for Phase 3: Launch4j Cross-Platform Workdir Classifier Selection
32 | */
33 | public class Launch4jClassifierTest {
34 |
35 | private static final OperatingSystem OS = OperatingSystem.current();
36 |
37 | // Valid classifiers from Maven Central: https://repo1.maven.org/maven2/net/sf/launch4j/launch4j/3.50/
38 | private static final Set VALID_CLASSIFIERS = new HashSet(Arrays.asList(
39 | "workdir-win32",
40 | "workdir-linux",
41 | "workdir-linux64",
42 | "workdir-mac"
43 | ));
44 |
45 | @Test
46 | public void testClassifierSelection() {
47 | String classifier = getWorkdirClassifier();
48 | assertNotNull("Classifier should not be null", classifier);
49 | assertTrue("Classifier should be valid: " + classifier,
50 | VALID_CLASSIFIERS.contains(classifier));
51 | }
52 |
53 | @Test
54 | public void testWindowsClassifier() {
55 | if (OS.isWindows()) {
56 | String classifier = getWorkdirClassifier();
57 | assertEquals("Windows should use workdir-win32", "workdir-win32", classifier);
58 | }
59 | }
60 |
61 | @Test
62 | public void testLinuxClassifier() {
63 | if (OS.isLinux()) {
64 | String classifier = getWorkdirClassifier();
65 | String arch = System.getProperty("os.arch");
66 |
67 | if (arch != null && (arch.contains("64") || arch.equals("amd64") || arch.equals("x86_64"))) {
68 | assertEquals("64-bit Linux should use workdir-linux64", "workdir-linux64", classifier);
69 | } else {
70 | assertEquals("32-bit Linux should use workdir-linux", "workdir-linux", classifier);
71 | }
72 | }
73 | }
74 |
75 | @Test
76 | public void testMacOsClassifier() {
77 | if (OS.isMacOsX()) {
78 | String classifier = getWorkdirClassifier();
79 | assertEquals("macOS should use workdir-mac", "workdir-mac", classifier);
80 | }
81 | }
82 |
83 | @Test
84 | public void testArchitectureDetection() {
85 | String arch = System.getProperty("os.arch");
86 | assertNotNull("Architecture should be detected", arch);
87 | assertFalse("Architecture should not be empty", arch.isEmpty());
88 | }
89 |
90 | /**
91 | * Simulates the getWorkdirClassifier() logic from Launch4jCreator
92 | */
93 | private String getWorkdirClassifier() {
94 | if (OS.isWindows()) {
95 | return "workdir-win32";
96 | } else if (OS.isLinux()) {
97 | String arch = System.getProperty("os.arch");
98 | if (arch != null && (arch.contains("64") || arch.equals("amd64") || arch.equals("x86_64"))) {
99 | return "workdir-linux64";
100 | }
101 | return "workdir-linux";
102 | } else if (OS.isMacOsX()) {
103 | return "workdir-mac";
104 | }
105 | return "workdir-win32"; // Fallback
106 | }
107 | }
108 |
109 |
--------------------------------------------------------------------------------
/testBuilds/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | repositories {
3 | mavenLocal()
4 | mavenCentral()
5 | // For snapshots, add Sonatype snapshot repository
6 | maven {
7 | url uri('https://oss.sonatype.org/content/repositories/snapshots/')
8 | }
9 | }
10 | dependencies {
11 | apply from: "${buildscript.sourceFile.parentFile.parentFile}/scripts/VersionNumber.gradle"
12 | apply from: "${buildscript.sourceFile.parentFile.parentFile}/scripts/SetupBuilderVersion.gradle"
13 | classpath 'de.inetsoftware:SetupBuilder:' + setupBuilderVersion()
14 | }
15 | }
16 |
17 | repositories {
18 | mavenLocal()
19 | mavenCentral()
20 | }
21 |
22 | apply plugin: 'de.inetsoftware.setupbuilder'
23 |
24 | apply plugin: 'java'
25 |
26 | sourceSets {
27 | main {
28 | java {
29 | srcDirs 'src'
30 | }
31 | }
32 | }
33 |
34 | setupBuilder {
35 |
36 | application = "Setup Builder Test"
37 | description = 'Build a test Programm.'
38 | icons = "test-icon.icns"
39 | vendor = 'Sample Company Inc.'
40 |
41 | licenseFile "license_en.txt"
42 | licenseFile {
43 | locale = "de"
44 | resource = "license_de.txt"
45 | }
46 |
47 | from jar.outputs
48 |
49 | bundleJre = 1.8
50 | java.sourceCompatibility = 1.8
51 | java.targetCompatibility = 1.8
52 | mainClass = 'com.inet.testapplication.TestLauncher'
53 | mainJar = 'testBuilds.jar'
54 |
55 | runBeforeUninstall {
56 | mainClass = 'com.inet.testapplication.TestLauncher'
57 | }
58 | runAfter {
59 | mainClass = 'com.inet.testapplication.TestLauncher'
60 | mainJar = 'testBuilds.jar'
61 | }
62 | service {
63 | displayName = "i-net TestLaunch Server"
64 | id = "testservice"
65 | }
66 | version = "3.0"
67 | minimumUpdateVersion "2.5"
68 | }
69 |
70 | configure( [ deb, rpm ] ) {
71 | doFirst {
72 | setupBuilder {
73 | defaultResourceLanguage "de"
74 | longDescription "longDesc_de.txt"
75 | longDescription {
76 | locale = "en"
77 | resource = "longDesc_en.txt"
78 | }
79 | }
80 | }
81 | }
82 |
83 | deb {
84 | checkPackage = false
85 | }
86 |
87 | dmg {
88 | preferencesLink {
89 | title = "Testing Link"
90 | action = "echo Hello World"
91 | }
92 | preferencesLink {
93 | title = "Second Testing Link"
94 | action = "echo Another World, hello"
95 | }
96 |
97 | daemonUser = "testingUser"
98 | }
99 |
100 | msi{
101 | languages = ["en-us"]
102 | //external file("fragmentDlg.wxs")
103 | //wxsTemplate = "template.wxs"
104 | multiInstanceCount = 10
105 | }
106 |
107 | dmg.dependsOn jar
108 | deb.dependsOn jar
109 | rpm.dependsOn jar
110 | msi.dependsOn jar
111 |
112 | // If the 'dmg' task is to be build, make sure that the pref pane exists as well
113 | import org.apache.tools.ant.taskdefs.condition.Os
114 | task preparePrefPane(type: GradleBuild) {
115 |
116 | buildDir = '../../SetupBuilderOSXPrefPane'
117 | tasks = ['clean', 'uploadArchives']
118 |
119 | processResources.dependsOn 'preparePrefPane'
120 |
121 | onlyIf {
122 | file('../../SetupBuilderOSXPrefPane/build.gradle').exists() && Os.isFamily(Os.FAMILY_MAC)
123 | }
124 | }
125 |
126 | /** buildFile does not exits anymore
127 | // run the following task as a dependency to the "check"-task.
128 | task runAppBundlerTest(type: GradleBuild) {
129 |
130 | buildFile = './appBundler.gradle'
131 | tasks = ['clean', 'bundleApp']
132 |
133 | processResources.dependsOn 'runAppBundlerTest'
134 |
135 | onlyIf {
136 | file(buildFile).exists() && Os.isFamily(Os.FAMILY_MAC)
137 | }
138 | }
139 |
140 | // run the following task as a dependency to the "check"-task.
141 | task runJNLPBundlerTest(type: GradleBuild) {
142 |
143 | buildFile = './jnlpBundler.gradle'
144 | tasks = ['clean', 'bundleApp']
145 |
146 | processResources.dependsOn 'runJNLPBundlerTest'
147 |
148 | onlyIf {
149 | file(buildFile).exists() && Os.isFamily(Os.FAMILY_MAC)
150 | }
151 | }
152 | */
153 |
--------------------------------------------------------------------------------
/src/com/inet/gradle/setup/image/image4j/codec/ico/IconEntry.java:
--------------------------------------------------------------------------------
1 | package com.inet.gradle.setup.image.image4j.codec.ico;
2 |
3 | import java.io.IOException;
4 |
5 | import com.inet.gradle.setup.image.image4j.io.LittleEndianInputStream;
6 |
7 | /**
8 | * Represents an IconEntry structure, which contains information about an ICO image.
9 | * @author Ian McDonagh
10 | */
11 | public class IconEntry {
12 | /**
13 | * The width of the icon image in pixels.
14 | * 0 specifies a width of 256 pixels.
15 | */
16 | public int bWidth;
17 | /**
18 | * The height of the icon image in pixels.
19 | * 0 specifies a height of 256 pixels.
20 | */
21 | public int bHeight;
22 | /**
23 | * The number of colours, calculated from {@link #sBitCount sBitCount}.
24 | * 0 specifies a colour count of >= 256.
25 | */
26 | public int bColorCount;
27 | /**
28 | * Unused. Should always be 0 .
29 | */
30 | public byte bReserved;
31 | /**
32 | * Number of planes, which should always be 1 .
33 | */
34 | public short sPlanes;
35 | /**
36 | * Colour depth in bits per pixel.
37 | */
38 | public short sBitCount;
39 | /**
40 | * Size of ICO data, which should be the size of (InfoHeader + AND bitmap + XOR bitmap).
41 | */
42 | public int iSizeInBytes;
43 | /**
44 | * Position in file where the InfoHeader starts.
45 | */
46 | public int iFileOffset;
47 |
48 | /**
49 | * Creates an IconEntry structure from the source input
50 | * @param in the source input
51 | * @throws java.io.IOException if an error occurs
52 | */
53 | public IconEntry(LittleEndianInputStream in) throws IOException {
54 | //Width 1 byte Cursor Width (16, 32, 64, 0 = 256)
55 | bWidth = in.readUnsignedByte();
56 | //Height 1 byte Cursor Height (16, 32, 64, 0 = 256 , most commonly = Width)
57 | bHeight = in.readUnsignedByte();
58 | //ColorCount 1 byte Number of Colors (2,16, 0=256)
59 | bColorCount = in.readUnsignedByte();
60 | //Reserved 1 byte =0
61 | bReserved = in.readByte();
62 | //Planes 2 byte =1
63 | sPlanes = in.readShortLE();
64 | //BitCount 2 byte bits per pixel (1, 4, 8)
65 | sBitCount = in.readShortLE();
66 | //SizeInBytes 4 byte Size of (InfoHeader + ANDbitmap + XORbitmap)
67 | iSizeInBytes = in.readIntLE();
68 | //FileOffset 4 byte FilePos, where InfoHeader starts
69 | iFileOffset = in.readIntLE();
70 | }
71 |
72 | /**
73 | * Creates and IconEntry structure with default values.
74 | */
75 | public IconEntry() {
76 | bWidth = 0;
77 | bHeight = 0;
78 | bColorCount = 0;
79 | sPlanes = 1;
80 | bReserved = 0;
81 | sBitCount = 0;
82 | iSizeInBytes = 0;
83 | iFileOffset = 0;
84 | }
85 |
86 | /**
87 | * A string representation of this IconEntry structure.
88 | */
89 | public String toString() {
90 | StringBuffer sb = new StringBuffer();
91 | sb.append("width=");
92 | sb.append(bWidth);
93 | sb.append(",height=");
94 | sb.append(bHeight);
95 | sb.append(",bitCount=");
96 | sb.append(sBitCount);
97 | sb.append(",colorCount="+bColorCount);
98 | return sb.toString();
99 | }
100 |
101 | /**
102 | * Writes the IconEntry structure to output
103 | * @param out the output
104 | * @throws java.io.IOException if an error occurs
105 | */
106 | public void write(com.inet.gradle.setup.image.image4j.io.LittleEndianOutputStream out) throws IOException {
107 | //Width 1 byte Cursor Width (16, 32 or 64)
108 | out.writeByte(bWidth);
109 | //Height 1 byte Cursor Height (16, 32 or 64 , most commonly = Width)
110 | out.writeByte(bHeight);
111 | //ColorCount 1 byte Number of Colors (2,16, 0=256)
112 | out.writeByte(bColorCount);
113 | //Reserved 1 byte =0
114 | out.writeByte(bReserved);
115 | //Planes 2 byte =1
116 | out.writeShortLE(sPlanes);
117 | //BitCount 2 byte bits per pixel (1, 4, 8)
118 | out.writeShortLE(sBitCount);
119 | //SizeInBytes 4 byte Size of (InfoHeader + ANDbitmap + XORbitmap)
120 | out.writeIntLE(iSizeInBytes);
121 | //FileOffset 4 byte FilePos, where InfoHeader starts
122 | out.writeIntLE(iFileOffset);
123 | }
124 | }
--------------------------------------------------------------------------------
/src/com/inet/gradle/setup/dmg/preferences/SetupBuilderOSXPrefPane/SetupBuilderOSXPrefPane.m:
--------------------------------------------------------------------------------
1 | //
2 | // SetupBuilderOSXPrefPane.m
3 | // SetupBuilderOSXPrefPane
4 | //
5 | // Created by Gerry Weißbach on 23/07/2015.
6 | // Copyright (c) 2015 i-net software. All rights reserved.
7 | //
8 |
9 | #import "SetupBuilderOSXPrefPane.h"
10 |
11 | #import "ServiceController.h"
12 | #import "Service.h"
13 | #import "Process.h"
14 |
15 | @implementation SetupBuilderOSXPrefPane
16 |
17 | // Constructor
18 | - (id)initWithBundle:(NSBundle *)bundle
19 | {
20 | if ( ( self = [super initWithBundle:bundle] ) != nil ) {
21 | self->bundle = bundle;
22 | self->helperPath = [bundle pathForAuxiliaryExecutable:HELPER_BINARY];
23 | DLog(@"Using helper: `%@`", helperPath);
24 | }
25 | return self;
26 | }
27 |
28 | - (void)mainViewDidLoad
29 | {
30 | NSURL *plist = [[NSBundle bundleForClass:[self class]] URLForResource:@"service" withExtension:@"plist"];
31 | service = [[Service alloc] initWithPlistURL:plist];
32 |
33 | // Setup SFAuthorizationView
34 | AuthorizationItem items = {kAuthorizationRightExecute, 0, NULL, 0};
35 | AuthorizationRights rights = {1, &items};
36 | [authView setAuthorizationRights:&rights];
37 | authView.delegate = self;
38 | [authView updateStatus:nil];
39 | }
40 |
41 | - (void)didUnselect {
42 | }
43 |
44 | // Called when the preference pane is shown
45 | - (void)didSelect {
46 | [serviceController setService:service];
47 | [serviceController setProcess: [[Process alloc] initWithAuthProvider: self]];
48 | [serviceController pollStatus];
49 | [self updateUI];
50 | }
51 |
52 | - (void)updateUI {
53 | DLog( @"Updating UI: %hhd", [self isUnlocked] );
54 | [serviceController setEnabled: [self isUnlocked]];
55 | }
56 |
57 | //
58 | // SFAuthorization delegates
59 | //
60 |
61 | - (void)authorizationViewDidAuthorize:(SFAuthorizationView *)view {
62 | // Enable Service Button
63 | [self updateUI];
64 | }
65 |
66 | - (void)authorizationViewDidDeauthorize:(SFAuthorizationView *)view {
67 | // Disable Service Button
68 | [self updateUI];
69 | }
70 |
71 | - (void)authorizationViewCreatedAuthorization:(SFAuthorizationView *)view {
72 | [self updateUI];
73 | }
74 |
75 | //
76 | // AuthorizationProvider protocol
77 | //
78 |
79 | - (BOOL)isUnlocked {
80 | return [authView authorizationState] == SFAuthorizationViewUnlockedState;
81 | }
82 |
83 | - (int)runAsRoot:(NSString*)program args:(NSArray*)args {
84 | size_t numArgs = args.count;
85 | char **cArgs = alloca(sizeof(char*) * (1 + numArgs));
86 | for (int i=0; i timestamps = Arrays.asList( //
35 | "http://time.certum.pl", //
36 | //"http://timestamp.verisign.com/scripts/timstamp.dll", // no connect possible
37 | "http://timestamp.globalsign.com/scripts/timestamp.dll", //
38 | "http://tsa.starfieldtech.com", //
39 | "http://timestamp.comodoca.com/authenticode" // certificate is expired
40 | );
41 |
42 | /**
43 | * Get a certificate file.
44 | *
45 | * @return a file or null
46 | */
47 | public Object getCertificate() {
48 | return certificate;
49 | }
50 |
51 | /**
52 | * Set a certificate file. This is used for the /f option of signtool.
53 | *
54 | * @param certificate the file
55 | */
56 | public void setCertificate( Object certificate ) {
57 | this.certificate = certificate;
58 | }
59 |
60 | /**
61 | * Get the password for a certificate file.
62 | *
63 | * @return the password
64 | */
65 | public String getPassword() {
66 | return password;
67 | }
68 |
69 | /**
70 | * Set the password for a certificate file. This is used for the /p option of signtool.
71 | *
72 | * @param password the password
73 | */
74 | public void setPassword( String password ) {
75 | this.password = password;
76 | }
77 |
78 | /**
79 | * Get a SHA1 thumbprint of the signing cert.
80 | *
81 | * @return the thumbprint
82 | */
83 | public String getSha1() {
84 | return sha1;
85 | }
86 |
87 | /**
88 | * Set the SHA1 thumbprint of the signing cert. This is used for the /sha1 option of signtool.
89 | *
90 | * @param sha1 the thumbprint
91 | */
92 | public void setSha1( String sha1 ) {
93 | this.sha1 = sha1;
94 | }
95 |
96 | /**
97 | * Get a list of timestamp servers.
98 | *
99 | * @return the list or null
100 | */
101 | public List getTimestamp() {
102 | return timestamps;
103 | }
104 |
105 | /**
106 | * Set a list of timestamp servers. By default there is already a list of popular timestamp servers. With null you
107 | * can disable the timestamp signing. If one server is failing then the next server is try.
108 | *
109 | * @param timestamps new timestamp servers.
110 | */
111 | public void setTimestamp( List timestamps ) {
112 | this.timestamps = timestamps;
113 | }
114 |
115 | /**
116 | * Set a single timestamp server. With null you can disable the timestamp signing.
117 | *
118 | * @param timestamp a single timestamp server
119 | */
120 | public void setTimestamp( String timestamp ) {
121 | this.timestamps = timestamp == null ? null : Arrays.asList( timestamp );
122 | }
123 | }
124 |
--------------------------------------------------------------------------------
/src/com/inet/gradle/setup/msi/Launch4jManifest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 - 20016 i-net software
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.inet.gradle.setup.msi;
17 |
18 | import java.io.File;
19 | import java.io.IOException;
20 |
21 | import org.w3c.dom.Element;
22 |
23 | import com.inet.gradle.setup.SetupBuilder;
24 | import com.inet.gradle.setup.util.XmlFileBuilder;
25 |
26 | /**
27 | * Create an XML configuration file for lauch4j.
28 | *
29 | * @author Volker
30 | */
31 | class Launch4jManifest extends XmlFileBuilder {
32 |
33 | private Launch4j launch;
34 |
35 | /**
36 | * Create a instance.
37 | *
38 | * @param launch the launch description
39 | * @param task current task
40 | * @param setup the SetupBuilder
41 | * @throws Exception if any error occur
42 | */
43 | Launch4jManifest( Launch4j launch, Msi task, SetupBuilder setup ) throws Exception {
44 | super( task, setup, File.createTempFile( "launch4j", ".manifest", task.getTemporaryDir() ), task.getTemporaryDir(), null );
45 | this.launch = launch;
46 | }
47 |
48 | /**
49 | * Create the XML file.
50 | *
51 | * @throws IOException if an error occurs on reading the image files
52 | */
53 | void build() throws IOException {
54 | Element assembly = getOrCreateChild( doc, "assembly" );
55 | assembly.setAttributeNS( "http://www.w3.org/2000/xmlns/", "xmlns", "urn:schemas-microsoft-com:asm.v1" );
56 | addAttributeIfNotExists( assembly, "manifestVersion", "1.0" );
57 |
58 | Element identity = getOrCreateChild( assembly, "assemblyIdentity" );
59 | addAttributeIfNotExists( identity, "version", Launch4jConfig.normalizeVersionNumber( task.getVersion() ) );
60 | addAttributeIfNotExists( identity, "processorArchitecture", "X86" );
61 | addAttributeIfNotExists( identity, "name", launch.getDisplayName() );
62 | addAttributeIfNotExists( identity, "type", "win32" );
63 |
64 | Element compatibility = getOrCreateChild( assembly, "compatibility" );
65 | compatibility.setAttributeNS( "http://www.w3.org/2000/xmlns/", "xmlns", "urn:schemas-microsoft-com:compatibility.v1" );
66 |
67 | Element application = getOrCreateChild( compatibility, "application" );
68 | getOrCreateChildById( application, "supportedOS", "{e2011457-1546-43c5-a5fe-008deee3d3f0}" ); // support for Vista
69 | getOrCreateChildById( application, "supportedOS", "{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" ); // support for Windows 7
70 | getOrCreateChildById( application, "supportedOS", "{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}" ); // support for Windows 8
71 | getOrCreateChildById( application, "supportedOS", "{1f676c76-80e1-4239-95bb-83d0f6d0da78}" ); // support for Windows 8.1
72 | getOrCreateChildById( application, "supportedOS", "{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" ); // support for Windows 10
73 |
74 | getOrCreateChild( assembly, "description" ).setTextContent( launch.getDescription() );
75 |
76 | Element trustInfo = getOrCreateChild( assembly, "trustInfo" );
77 | trustInfo.setAttributeNS( "http://www.w3.org/2000/xmlns/", "xmlns", "urn:schemas-microsoft-com:asm.v2" );
78 |
79 | String level = launch.getRequestedExecutionLevel();
80 | if ( level != null && !level.isEmpty() ) {
81 | Element security = getOrCreateChild( trustInfo, "security" );
82 | Element requestedPrivileges = getOrCreateChild( security, "requestedPrivileges" );
83 | Element requestedExecutionLevel = getOrCreateChildByKeyValue( requestedPrivileges, "requestedExecutionLevel", "level", level );
84 | addAttributeIfNotExists( requestedExecutionLevel, "uiAccess", "false" );
85 | }
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/src/com/inet/gradle/setup/abstracts/DocumentType.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 i-net software
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.inet.gradle.setup.abstracts;
17 |
18 | import java.util.ArrayList;
19 | import java.util.List;
20 |
21 | /**
22 | * This class contains content for registering file extensions.
23 | *
24 | * @author Volker
25 | */
26 | public class DocumentType {
27 |
28 | private final AbstractSetupBuilder setup;
29 |
30 | private List extensions;
31 |
32 | private String name;
33 |
34 | private String mimetype;
35 |
36 | private String role = "Viewer";
37 |
38 | private Object icons;
39 |
40 | DocumentType( AbstractSetupBuilder setup ) {
41 | this.setup = setup;
42 | }
43 |
44 | /**
45 | * Add one file extensions.
46 | *
47 | * @param extension the extension
48 | */
49 | public void fileExtension( String extension ) {
50 | if( extension.startsWith( "*." ) ) {
51 | extension = extension.substring( 2 );
52 | }
53 | if( extensions == null ) {
54 | extensions = new ArrayList<>();
55 | }
56 | extensions.add( extension );
57 | }
58 |
59 | /**
60 | * Add multiple file extensions.
61 | *
62 | * @param extensions the extensions
63 | */
64 | public void fileExtension( List extensions ) {
65 | for( String extension : extensions ) {
66 | fileExtension( extension );
67 | }
68 | }
69 |
70 | /**
71 | * Add one file extensions.
72 | *
73 | * @param extension the extension
74 | */
75 | public void setFileExtension( String extension ) {
76 | extensions = null;
77 | fileExtension( extension );
78 | }
79 |
80 | public List getFileExtension() {
81 | return extensions;
82 | }
83 |
84 | /**
85 | * Set multiple file extensions.
86 | *
87 | * @param extensions the extensions
88 | */
89 | public void setFileExtension( List extensions ) {
90 | this.extensions = extensions;
91 | }
92 |
93 | public String getName() {
94 | if( name != null && !name.isEmpty() ) {
95 | return name;
96 | }
97 | return setup.getProject().getName() + " file";
98 | }
99 |
100 | public void setName( String name ) {
101 | this.name = name;
102 | }
103 |
104 | /**
105 | * Returns the mime type for the document type. If none mime type was specified it will return 'application/<the first extension>'.
106 | * @return the mime type for the document type
107 | */
108 | public String getMimetype() {
109 | if( mimetype != null && mimetype.trim().length() > 0) {
110 | return mimetype;
111 | } else {
112 | List ext = getFileExtension();
113 | return "application/" + ext.get( 0 );
114 | }
115 | }
116 |
117 | /**
118 | * Sets the mime type of the document type
119 | * @param mimetype the mime type
120 | */
121 | public void setMimetype( String mimetype ) {
122 | this.mimetype = mimetype;
123 | }
124 |
125 | public String getRole() {
126 | return role;
127 | }
128 |
129 | /**
130 | * Set the role for OSX.
131 | *
132 | * @param role the role
133 | */
134 | public void setRole( String role ) {
135 | this.role = role;
136 | }
137 |
138 | public Object getIcons() {
139 | if( icons != null ) {
140 | return icons;
141 | }
142 | return setup.getIcons();
143 | }
144 |
145 | public void setIcons( Object icons ) {
146 | this.icons = icons;
147 | }
148 |
149 | }
150 |
--------------------------------------------------------------------------------
/src/com/inet/gradle/setup/unix/deb/Deb.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 i-net software
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.inet.gradle.setup.unix.deb;
17 |
18 | import org.gradle.api.tasks.Input;
19 | import org.gradle.api.tasks.Optional;
20 |
21 | import com.inet.gradle.setup.unix.Unix;
22 |
23 | /**
24 | * The deb Gradle task. It build a deb package for Debian / Ubuntu.
25 | *
26 | * @author Stefan Heidrich
27 | */
28 | public class Deb extends Unix {
29 |
30 | private String priority;
31 |
32 | private String installSize;
33 |
34 | private String recommends;
35 |
36 | private boolean checkPackage = false;
37 |
38 | private String lintianOptions = "";
39 |
40 | private String maintainerEmail;
41 |
42 | private String changes;
43 |
44 | private String compression;
45 |
46 | public Deb() {
47 | super( "deb" );
48 | }
49 |
50 | /**
51 | * {@inheritDoc}
52 | */
53 | @Override
54 | public void build() {
55 | new DebBuilder( this, getSetupBuilder(), getFileResolver() ).build();
56 | }
57 |
58 | @Input
59 | @Optional
60 | public String getPriority() {
61 | return priority;
62 | }
63 |
64 | public void setPriority( String priority ) {
65 | this.priority = priority;
66 | }
67 |
68 | @Input
69 | @Optional
70 | public String getInstallSize() {
71 | return installSize;
72 | }
73 |
74 | public void setInstallSize( String installSize ) {
75 | this.installSize = installSize;
76 | }
77 |
78 | @Input
79 | @Optional
80 | @Override
81 | public String getRecommends() {
82 | return recommends;
83 | }
84 |
85 | @Override
86 | public void setRecommends( String recommends ) {
87 | this.recommends = recommends;
88 | }
89 |
90 | public boolean shouldCheckPackage() {
91 | return checkPackage;
92 | }
93 |
94 | public void setCheckPackage( boolean checkPackage ) {
95 | this.checkPackage = checkPackage;
96 | }
97 |
98 | /**
99 | * Return the options used for the 'lintian' process.
100 | * They will only have impact when checkPackages is enabled.
101 | * @return the lintianOptions
102 | */
103 | @Input
104 | public String getLintianOptions() {
105 | return lintianOptions;
106 | }
107 |
108 | /**
109 | * Set the options used for the 'linting' process.
110 | * They will only have impact when checkPackages is enabled.
111 | * @param lintianOptions the lintianOptions to set
112 | */
113 | public void setLintianOptions( String lintianOptions ) {
114 | this.lintianOptions = lintianOptions;
115 | }
116 |
117 | @Input
118 | @Optional
119 | public String getMaintainerEmail() {
120 | return maintainerEmail;
121 | }
122 |
123 | public void setMaintainerEmail( String maintainerEmail ) {
124 | this.maintainerEmail = maintainerEmail;
125 | }
126 |
127 | @Input
128 | @Optional
129 | public String getChanges() {
130 | return changes;
131 | }
132 |
133 | public void setChanges( String changes ) {
134 | this.changes = changes;
135 | }
136 |
137 | @Input
138 | @Optional
139 | public String getCompression() {
140 | return compression;
141 | }
142 |
143 | public void setCompression( String compression ) {
144 | this.compression = compression;
145 | }
146 |
147 | @Input
148 | @Override
149 | public String getArchitecture() {
150 | String architecture = super.getArchitecture();
151 | if( architecture == null || architecture.length() == 0 ) {
152 | architecture = "all";
153 | }
154 | return architecture;
155 | }
156 | }
157 |
--------------------------------------------------------------------------------
/src/com/inet/gradle/setup/abstracts/AbstractSetupTask.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 - 2016 i-net software
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.inet.gradle.setup.abstracts;
17 |
18 | import java.util.ArrayList;
19 |
20 | import com.inet.gradle.setup.SetupBuilder;
21 | import org.gradle.api.tasks.Input;
22 | import org.gradle.api.tasks.Internal;
23 |
24 | /**
25 | * Base task for all setup builder tasks.
26 | *
27 | * @author Volker Berlin
28 | */
29 | public abstract class AbstractSetupTask extends AbstractTask {
30 |
31 | private ArrayList postinst = new ArrayList();
32 |
33 | private ArrayList preinst = new ArrayList();
34 |
35 | private ArrayList postrm = new ArrayList();
36 |
37 | private ArrayList prerm = new ArrayList();
38 |
39 | /**
40 | * Constructor with indication to artifact result Runs with the default SetupBuilder for dmg, msi ...
41 | *
42 | * @param extension of the setup
43 | */
44 | public AbstractSetupTask( String extension ) {
45 | super( extension, SetupBuilder.class );
46 | }
47 |
48 | /**
49 | * Get the setup builder extension.
50 | *
51 | * @return the instance of the SetupBuilder
52 | */
53 | @Internal
54 | public SetupBuilder getSetupBuilder() {
55 | return (SetupBuilder)super.getAbstractSetupBuilder();
56 | }
57 |
58 | /**
59 | * Returns the preinst that should be used in the 'preinst' config file.
60 | *
61 | * @return the preinst specified in the gradle script
62 | */
63 | @Input
64 | public ArrayList getPreinst() {
65 | return preinst;
66 | }
67 |
68 | /**
69 | * Adds the content for the 'preinst' config file. On Windows this can be vbscript or jscript that should be executed.
70 | *
71 | * @param preinst the content for the entry
72 | */
73 | public void setPreinst( String preinst ) {
74 | this.preinst.add( preinst );
75 | }
76 |
77 | /**
78 | * Returns the postinst that should be used in the 'postinst' config file.
79 | *
80 | * @return the postinst specified in the gradle script
81 | */
82 | @Input
83 | public ArrayList getPostinst() {
84 | return postinst;
85 | }
86 |
87 | /**
88 | * Adds the content for the 'postinst' config file. On Windows this can be vbscript or jscript that should be executed.
89 | *
90 | * @param postinst the value for the entry
91 | */
92 | public void setPostinst( String postinst ) {
93 | this.postinst.add( postinst );
94 | }
95 |
96 | /**
97 | * Returns the prerm that should be used in the 'prerm' config file.
98 | *
99 | * @return the prerm specified in the gradle script
100 | */
101 | @Input
102 | public ArrayList getPrerm() {
103 | return prerm;
104 | }
105 |
106 | /**
107 | * Adds the content for the 'prerm' config file. On Windows this can be vbscript or jscript that should be executed.
108 | *
109 | * @param prerm the value for the entry
110 | */
111 | public void setPrerm( String prerm ) {
112 | this.prerm.add( prerm );
113 | }
114 |
115 | /**
116 | * Returns the postrm that should be used in the 'postrm' config file.
117 | *
118 | * @return the postrm specified in the gradle script
119 | */
120 | @Input
121 | public ArrayList getPostrm() {
122 | return postrm;
123 | }
124 |
125 | /**
126 | * Adds the content for the 'postrm' config file. On Windows this can be vbscript or jscript that should be executed.
127 | *
128 | * @param postrm the value for the entry
129 | */
130 | public void setPostrm( String postrm ) {
131 | this.postrm.add( postrm );
132 | }
133 | }
134 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # SetupBuilder Changelog
2 |
3 | ## 8.4.23 (Unreleased)
4 |
5 | ### Changed
6 | * **Version Management**: Simplified version management - version now read from `gradle.properties` instead of hardcoded `buildVersion` variable
7 | * Version format: `..` or `..-SNAPSHOT`
8 | * Version compatibility with Gradle version is automatically validated and adjusted if needed
9 | * **Build Process**: Removed conditional JPP (Java Preprocessor) execution - now always processes source files for Gradle version compatibility
10 | * Source files are always preprocessed to `buildDir/preparedSrc-${gradleVersion}`
11 | * Ensures consistent build behavior across all Gradle versions
12 | * **Publishing**: Replaced local `../repo` publishing with `mavenLocal()` for local development
13 | * Use `./gradlew publishToMavenLocal` for local development
14 | * Snapshots are published to Sonatype snapshot repository
15 | * Releases are published to Maven Central via Sonatype
16 | * **CI/CD**: Migrated from Travis CI to GitHub Actions
17 | * CI workflow tests with multiple Gradle versions (7.6, 8.4, 8.14.2, 9.2.1) across multiple platforms (Ubuntu, Windows, macOS)
18 | * Release workflow automatically publishes to Sonatype and Gradle Plugin Portal
19 |
20 | ### Added
21 | * **Sonatype Publishing**: Added full Sonatype/Maven Central publishing support
22 | * Snapshots automatically published to `https://oss.sonatype.org/content/repositories/snapshots/`
23 | * Releases go through staging → close → release process
24 | * Signing support for both snapshots and releases
25 | * **Configuration Files**:
26 | * Created `gradle.properties` for centralized version management
27 | * Added GitHub Actions workflows (`.github/workflows/ci.yml` and `release.yml`)
28 | * **Documentation**: Added "Using Snapshots" section to README.md
29 | * Instructions for adding Sonatype snapshot repository
30 | * Instructions for using `mavenLocal()` for local development
31 |
32 | ### Fixed
33 | * Fixed Gradle 8.4 compatibility issues with `CopyProcessingSpec` interface methods
34 | * `getDirMode()`, `setDirMode()`, `getFileMode()`, `setFileMode()` methods properly handled
35 | * Fixed syntax error in `nexusPublishing` configuration block
36 | * Updated test builds to use `mavenLocal()` and Sonatype snapshot repository instead of `../../repo`
37 |
38 | ## 8.4.22 (v22)
39 |
40 | ### Changed
41 | * Gradle 9 now requires Java 17
42 | * Adaptations for Gradle 9 compatibility
43 | * Current version of `com.gradle.plugin-publish` plugin only compatible with Gradle >= 7.6
44 | * Removed support for older Gradle versions
45 | * Made Gradle script fit for Gradle 9
46 | * Replaced missing `VersionNumber` with own implementation
47 | * Updated `com.gradle.plugin-publish` plugin
48 |
49 | ### Fixed
50 | * `java.net.URL` is not allowed as `@Input` anymore (#132)
51 | * With Gradle 9 only the file name `build.gradle` is supported
52 | * Replaced internal API `ConfigureUtil` with public API
53 | * Removed reference to internal class `ProjectInternal`
54 | * Made compatible with Gradle 8.12/8.13 through a more generic solution (#132)
55 | * Fixed `gradlePlugin` settings
56 | * Added hack for Eclipse `.classpath` file
57 |
58 | ## 8.4.21 (v21)
59 |
60 | ### Changed
61 | * Build for Gradle version 8.4 because there are API changes since Gradle 8.0 (#125)
62 | * Build also version 8.0 of SetupBuilder (#125)
63 |
64 | ### Added
65 | * Added getter and setter methods for compression to use for Debian package
66 | * Default compression is now xzip on newer Debian systems
67 | * Can change compression for older systems (e.g., `compression="gzip"`)
68 |
69 | ### Fixed
70 | * Debian package: skip Recommends when empty (#128)
71 | * MSI installer: Does not use HKLM registry keys for installer with perUser scope (#127)
72 | * RTF file must not be quoted
73 |
74 | ## 8.4.20 (v20)
75 |
76 | ### Changed
77 | * Updated plugin dependencies
78 | * Library updates
79 |
80 | ## 8.4.18 (v18)
81 |
82 | ### Changed
83 | * Updates for Gradle 7
84 |
85 | ## 8.4.17 (v17)
86 |
87 | ### Changed
88 | * Library updates
89 |
90 | ## 8.4.16 (v16)
91 |
92 | ### Changed
93 | * Library updates
94 |
95 | ## 8.4.15 (v15)
96 |
97 | ### Changed
98 | * Library updates
99 |
100 | ## 8.4.13 (v13)
101 |
102 | ### Changed
103 | * Library updates
104 |
105 | ## 8.4.12 (v12)
106 |
107 | ### Changed
108 | * Library updates
109 |
110 | ## 8.4.11 (v11)
111 |
112 | ### Changed
113 | * Initial version tracking
114 |
115 | ---
116 |
117 | **Note:** Version history prior to v11 may not be fully documented. This changelog tracks significant changes from version 8.4.11 onwards.
118 |
119 |
--------------------------------------------------------------------------------
/src/com/oracle/appbundler/TypeDeclaration.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015, Quality First Software GmbH and/or its affiliates. All rights reserved.
3 | *
4 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 | *
6 | * This code is free software; you can redistribute it and/or modify it
7 | * under the terms of the GNU General Public License version 2 only, as
8 | * published by the Free Software Foundation. Oracle designates this
9 | * particular file as subject to the "Classpath" exception as provided
10 | * by Oracle in the LICENSE file that accompanied this code.
11 | *
12 | * This code is distributed in the hope that it will be useful, but WITHOUT
13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 | * version 2 for more details (a copy is included in the LICENSE file that
16 | * accompanied this code).
17 | *
18 | * You should have received a copy of the GNU General Public License version
19 | * 2 along with this work; if not, write to the Free Software Foundation,
20 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21 | *
22 | */
23 |
24 | package com.oracle.appbundler;
25 |
26 | import static com.oracle.appbundler.BundleDocument.getListFromCommaSeparatedString;
27 |
28 | import java.io.File;
29 | import java.util.Arrays;
30 | import java.util.List;
31 |
32 | /**
33 | * Class representing an UTExportedTypeDeclaration or UTImportedTypeDeclaration in Info.plist
34 | */
35 | public class TypeDeclaration implements IconContainer {
36 |
37 | private boolean imported = false;
38 | private String identifier = null;
39 | private String referenceUrl = null;
40 | private String description = null;
41 | private String icon = null;
42 | private List conformsTo = null;
43 | private List osTypes = null;
44 | private List mimeTypes = null;
45 | private List extensions = null;
46 |
47 | public TypeDeclaration() {
48 | this.conformsTo = Arrays.asList(new String[]{"public.data"});
49 | }
50 |
51 | public boolean isImported() {
52 | return imported;
53 | }
54 |
55 | public void setImported(boolean imported) {
56 | this.imported = imported;
57 | }
58 |
59 | public String getIdentifier() {
60 | return identifier;
61 | }
62 |
63 | public void setIdentifier(String identifier) {
64 | this.identifier = identifier;
65 | }
66 |
67 | public String getReferenceUrl() {
68 | return referenceUrl;
69 | }
70 |
71 | public void setReferenceUrl(String referenceUrl) {
72 | this.referenceUrl = referenceUrl;
73 | }
74 |
75 | public String getDescription() {
76 | return description;
77 | }
78 |
79 | public void setDescription(String description) {
80 | this.description = description;
81 | }
82 |
83 | public String getIcon() {
84 | return icon;
85 | }
86 |
87 | public void setIcon(String icon) {
88 | this.icon = icon;
89 | }
90 |
91 | public File getIconFile() {
92 | if (icon == null) { return null; }
93 |
94 | File ifile = new File (icon);
95 |
96 | if (! ifile.exists ( ) || ifile.isDirectory ( )) { return null; }
97 |
98 | return ifile;
99 | }
100 |
101 | public boolean hasIcon() {
102 | return icon != null;
103 | }
104 |
105 | public List getConformsTo() {
106 | return conformsTo;
107 | }
108 |
109 | public void setConformsTo(String conformsToAsString) {
110 | this.conformsTo = getListFromCommaSeparatedString(conformsToAsString, "Conforms To");
111 | }
112 |
113 | public List getOsTypes() {
114 | return osTypes;
115 | }
116 |
117 | public void setOsTypes(String osTypesAsString) {
118 | this.osTypes = getListFromCommaSeparatedString(osTypesAsString, "OS Types");
119 | }
120 |
121 | public List getMimeTypes() {
122 | return mimeTypes;
123 | }
124 |
125 | public void setMimeTypes(String mimeTypesAsString) {
126 | this.mimeTypes = getListFromCommaSeparatedString(mimeTypesAsString, "Mime Types", true);
127 | }
128 |
129 | public List getExtensions() {
130 | return extensions;
131 | }
132 |
133 | public void setExtensions(String extensionsAsString) {
134 | this.extensions = getListFromCommaSeparatedString(extensionsAsString, "Extensions", true);
135 | }
136 |
137 | @Override
138 | public String toString() {
139 | return "" + imported;
140 | }
141 | }
142 |
--------------------------------------------------------------------------------
/src/com/inet/gradle/setup/msi/MsiLanguages.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 i-net software
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.inet.gradle.setup.msi;
17 |
18 | /**
19 | * A mapping between Windows cultures and languages IDs
20 | *
21 | * @author Volker Berlin
22 | */
23 | enum MsiLanguages {
24 | // Available Language Packs for Windows: https://technet.microsoft.com/en-us/library/hh825678.aspx
25 | // from WixUIExtension supported languages: https://github.com/wixtoolset/wix3/tree/develop/src/ext/UIExtension/wixlib
26 |
27 | en_us( 1033 ), // this should be the default, that it is on position 0
28 |
29 | ar_sa( 1025 ), //
30 | bg_bg( 1026 ), //
31 | ca_es( 1027 ), //
32 | zh_tw( 1028 ), //
33 | cs_cz( 1029 ), //
34 | da_dk( 1030 ), //
35 | de_de( 1031 ), //
36 | el_gr( 1032 ), //
37 | fi_fi( 1035 ), //
38 | fr_fr( 1036 ), //
39 | he_IL( 1037 ), //
40 | hu_hu( 1038 ), //
41 | it_it( 1040 ), //
42 | ja_jp( 1041 ), //
43 | ko_kr( 1042 ), //
44 | nl_nl( 1043 ), //
45 | nb_no( 1044 ), //
46 | pl_pl( 1045 ), //
47 | pt_br( 1046 ), //
48 | ro_ro( 1048 ), //
49 | ru_ru( 1049 ), //
50 | hr_hr( 1050 ), //
51 | sk_sk( 1051 ), //
52 | sv_se( 1053 ), //
53 | th_th( 1054 ), //
54 | tr_tr( 1055 ), //
55 | uk_ua( 1058 ), //
56 | sl_si( 1060 ), //
57 | et_ee( 1061 ), //
58 | lv_lv( 1062 ), //
59 | lt_lt( 1063 ), //
60 | // hi_in( 1081 ), // error LGHT0311 : A string was provided with characters that are not available in the specified database code page '1252'. Either change these characters to ones that exist in the database's code page, or update the database's code page by modifying one of the following attributes: Product/@Codepage, Module/@Codepage, Patch/@Codepage, PatchCreation/@Codepage, or WixLocalization/@Codepage.
61 | // kk_kz( 1087 ), // error LGHT0311 : A string was provided with characters that are not available in the specified database code page '1252'. Either change these characters to ones that exist in the database's code page, or update the database's code page by modifying one of the following attributes: Product/@Codepage, Module/@Codepage, Patch/@Codepage, PatchCreation/@Codepage, or WixLocalization/@Codepage.
62 | zh_cn( 2052 ), //
63 | pt_pt( 2070 ), //
64 | sr_latn_cs( 2074 ), //
65 | zh_hk( 3076 ), //
66 | es_es( 3082 ), //
67 | ;
68 |
69 | private final String culture;
70 |
71 | private final int langID;
72 |
73 | /**
74 | * Create a instance of the enum.
75 | * @param langID the numeric language ID.
76 | */
77 | private MsiLanguages( int langID ) {
78 | this.culture = name().replace( '_', '-' );
79 | this.langID = langID;
80 | }
81 |
82 | /**
83 | * The culture like en-us.
84 | * @return the culture
85 | */
86 | String getCulture() {
87 | return culture;
88 | }
89 |
90 | /**
91 | * The numeric language ID.
92 | * @return the id
93 | */
94 | String getLangID() {
95 | return Integer.toString( langID );
96 | }
97 |
98 | public static MsiLanguages getMsiLanguage( String input ) {
99 |
100 | String key = input.replace( '-', '_' ).toLowerCase();
101 | MsiLanguages value = null;
102 | try {
103 | value = MsiLanguages.valueOf( key );
104 | } catch( IllegalArgumentException ex ) {
105 | // The complete name was not found.
106 | // now we check if this is only a language without a country
107 | for( MsiLanguages msiLanguage : MsiLanguages.values() ) {
108 | if( msiLanguage.toString().startsWith( key ) ) {
109 | value = msiLanguage;
110 | break;
111 | }
112 | }
113 | if( value == null ) {
114 | throw ex; // not supported language
115 | }
116 | }
117 | return value;
118 | }
119 | }
120 |
--------------------------------------------------------------------------------