/*
* Copyright 2015 -2016 i-net software
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.inet.gradle.setup.msi;
import groovy.lang.Closure;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import org.gradle.api.internal.file.CopyActionProcessingStreamAction;
import org.gradle.api.internal.project.ProjectInternal;
import org.gradle.util.ConfigureUtil;
import com.inet.gradle.setup.abstracts.AbstractSetupTask;
import com.inet.gradle.setup.abstracts.DesktopStarter;
/**
* The msi Gradle task. It build a msi setup for Windows.
*
* @author Volker Berlin
*/
public class Msi extends AbstractSetupTask {
private String arch;
private boolean only32bit;
private Object bannerBmp, dialogBmp, wxsTemplate, multiInstanceScript;
private List<String> languages;
private SignTool signTool;
private double minOS;
private List<DesktopStarter> launch4j = new ArrayList<>();
private int multiInstanceCount = 1;
private InstallScope installScope;
private List<String> preGUI = new ArrayList<String>();
/**
* Create a new instance.
*/
public Msi() {
super( "msi" );
}
/**
* {@inheritDoc}
*/
@Override
public void build() {
ProjectInternal project = (ProjectInternal)getProject();
new MsiBuilder( this, getSetupBuilder(), project.getFileResolver() ).build();
}
/**
* {@inheritDoc}
*/
@Override
protected void processFiles( CopyActionProcessingStreamAction action ) {
super.processFiles( action );
}
/**
* If this installer should run only on windows 32 bit versions.
*
* @return true, if only 32 bit
*/
boolean isOnly32Bit() {
return only32bit;
}
/**
* Get the architecture of the installer.
* @return the architecture
*/
public String getArch() {
if( arch != null ) {
return arch;
}
return "x64";
}
/**
* Set the architecture of the setup. The default is x64. Possible values are:
* <ul>
* <li>x86
* <li>x64
* <li>ia64
* <li>x86-only - does not run on a 64 bit system
* </ul>
*
* @param arch the architecture
*/
public void setArch( String arch ) {
if( "x86-only".equals( arch ) ) {
this.arch = "x86";
this.only32bit = true;
} else {
this.arch = arch;
this.only32bit = false;
}
}
/**
* if the setup is a 64 bit setup.
*
* @return true, if 64 bit.
*/
boolean is64Bit() {
switch( getArch() ) {
case "x64":
case "ia64":
return true;
default:
return false;
}
}
/**
* Get the file of the banner or null
* @return the file
*/
public File getBannerBmp() {
if( bannerBmp != null ) {
return getProject().file( bannerBmp );
}
return null;
}
/**
* Set a file with a banner BMP. The typical size is 493 x 58
*
* @param bannerBmp the file
*/
public void setBannerBmp( Object bannerBmp ) {
this.bannerBmp = bannerBmp;
}
/**
* Get the banner BMP.
*
* @return the BMP
*/
public File getDialogBmp() {
if( dialogBmp != null ) {
return getProject().file( dialogBmp );
}
return null;
}
/**
* Set a file with the dialog BMP. The typical size is 493 x 312
*
* @param dialogBmp the file
*/
public void setDialogBmp( Object dialogBmp ) {
this.dialogBmp = dialogBmp;
}
/**
* Set the needed information for signing the setup.
*
* @param closue the data for signing
*/
public void signTool( Closure<SignTool> closue ) {
signTool = ConfigureUtil.configure( closue, new SignTool() );
}
/**
* Get the SignTool configuration if set
*
* @return the settings or null
*/
public SignTool getSignTool() {
return signTool;
}
/**
* Get a URL to a *.wxs file for the WIX Toolset
*
* @return the template
* @throws MalformedURLException if any error occur
*/
public URL getWxsTemplate() throws MalformedURLException {
if( wxsTemplate != null ) {
return getProject().file( wxsTemplate ).toURI().toURL();
}
return getClass().getResource( "template.wxs" );
}
/**
* Set an optional *.wxs file as template for building the final file with the settings of the gradle task. This
* template give you the option to set things that are not available via the gradle task.
*
* @param wxsTemplate the file location
*/
public void setWxsTemplate( Object wxsTemplate ) {
this.wxsTemplate = wxsTemplate;
}
/**
* Get the languages that the setup should be support. The list must at minimum one element.
* @return a list of languages
*/
public List<MsiLanguages> getLanguages() {
ArrayList<MsiLanguages> result = new ArrayList<>();
if( languages == null ) {
Collections.addAll( result, MsiLanguages.values() );
return result;
}
for( String lang : languages ) {
String key = lang.replace( '-', '_' ).toLowerCase();
MsiLanguages value = null;
try {
value = MsiLanguages.valueOf( key );
} catch( IllegalArgumentException ex ) {
// The completely name was not found.
// now we check if this is only a language without a country
for( MsiLanguages msiLanguage : MsiLanguages.values() ) {
if( msiLanguage.toString().startsWith( key ) ) {
value = msiLanguage;
break;
}
}
if( value == null ) {
throw ex; // not supported language
}
}
result.add( value );
}
if( result.isEmpty() ) {
result.add( MsiLanguages.en_us );
}
return result;
}
/**
* Set a list of languages for the setup GUI. For example "en-us". By default all available languages will be added to the setup. This can need some time on creation.
* @param languages the languages
*/
public void setLanguages( Object languages ) {
List<String> list;
if( languages == null ) {
list = null;
} else if( languages instanceof Iterable ) {
list = new ArrayList<>();
for( Object str : (Iterable<?>)languages ) {
list.add( str.toString() );
}
} else {
list = Arrays.asList( languages.toString() );
}
this.languages = list;
}
/**
* Get the minimum OS version.
*
* @return the version
*/
public double getMinOS() {
return minOS;
}
/**
* Set the minimum OS version.
* <ul>
* <li>10.0 - Windows 10
* <li>10.0 - Windows Server 2016
* <li> 6.3 - Windows 8.1
* <li> 6.3 - Windows Server 2012 R2
* <li> 6.2 - Windows 8
* <li> 6.2 - Windows Server 2012
* <li> 6.1 - Windows 7
* <li> 6.1 - Windows Server 2008 R2
* <li> 6.0 - Windows Server 2008
* <li> 6.0 - Windows Vista
* <li> 5.2 - Windows Server 2003 R2
* <li> 5.2 - Windows Server 2003
* <li> 5.2 - Windows XP 64-Bit Edition
* <li> 5.1 - Windows XP
* <li> 5.0 - Windows 2000
* </ul>
*
* @param minVersion the version
*/
public void setMinOS( double minVersion ) {
this.minOS = minVersion;
}
/**
* Register a lauch4j configuration.
*
* @param closue the closure of the launch4j definition
*/
public void launch4j( Closure<DesktopStarter> closue ) {
DesktopStarter service = ConfigureUtil.configure( closue, new DesktopStarter( getSetupBuilder() ) );
launch4j.add( service );
}
/**
* Returns the registered services.
*
* @return the registered services
*/
public List<DesktopStarter> getLaunch4js() {
return launch4j;
}
/**
* Get the count of possible multiple instances.
*
* @return instance count
*/
public int getMultiInstanceCount() {
return multiInstanceCount;
}
/**
* Set the count of possible multiple instances. The default is 1. A value lesser or equals 1 result in a single
* instance setup.
*
* @param instanceCount the current instance count
*/
public void setMultiInstanceCount( int instanceCount ) {
this.multiInstanceCount = instanceCount;
}
/**
* Get the URL to a vbscript that set the instance name.
*
* @return the URL
* @throws MalformedURLException if any error occur
*/
public URL getMultiInstanceScript() throws MalformedURLException {
if( multiInstanceScript != null ) {
return getProject().file( multiInstanceScript ).toURI().toURL();
}
return getClass().getResource( "MultiInstance.vbs" );
}
/**
* Set a vbscript that can change the product name, instance id and other things on a multi instance installation.
*
* @param multiInstanceScript the script
*/
public void setMultiInstanceScript( Object multiInstanceScript ) {
this.multiInstanceScript = multiInstanceScript;
}
/**
* Possible values for install scope
*/
public static enum InstallScope {
perUser, perMachine
}
/**
* Get the install scope. Never null.
*
* @return the scope
*/
public InstallScope getInstallScope() {
if( installScope != null ) {
return installScope;
}
return InstallScope.perMachine;
}
/**
* Set the install scope. Possible values are perUser and perMachine. If not set then it is perMachine.
* A perUser installer has no elevated rights and can not installed to program files.
*
* @param installScope the new scope
*/
public void setInstallScope( InstallScope installScope ) {
this.installScope = installScope;
}
/**
* Returns the preGUI scripts.
*
* @return the scripts
*/
public List<String> getPreGUI() {
return preGUI;
}
/**
* Set a vbscript or jscript that should be executed before the GUI is displayed. This can be used for setting
* a default install directory. This action has no elevated rights.
*
* @param script list or single script
*/
@SuppressWarnings( "unchecked" )
public void setPreGUI( Object script ) {
preGUI.clear();
preGUI( script );
}
/**
* Add a vbscript or jscript that should be executed before the GUI is displayed. This can be used for setting
* a default install directory. This action has no elevated rights.
*
* @param script the content for the entry
*/
public void preGUI( Object script ) {
if( script == null ) {
// nothing
} else if( script instanceof Collection ) {
preGUI.addAll( (Collection)script );
} else {
preGUI.add( script.toString() );
}
}
}