/*
* Copyright 2008,2009 Alin Dreghiciu.
* Copyright 2008,2009 Toni Menzel
*
* 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 org.ops4j.pax.exam.container.def.internal;
import java.io.File;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.ops4j.pax.exam.Customizer;
import org.ops4j.pax.exam.Option;
import static org.ops4j.pax.exam.OptionUtils.*;
import org.ops4j.pax.exam.container.def.options.AutoWrapOption;
import org.ops4j.pax.exam.container.def.options.CleanCachesOption;
import org.ops4j.pax.exam.container.def.options.ExcludeDefaultRepositoriesOption;
import org.ops4j.pax.exam.container.def.options.LocalRepositoryOption;
import org.ops4j.pax.exam.container.def.options.ProfileOption;
import org.ops4j.pax.exam.container.def.options.RawPaxRunnerOptionOption;
import org.ops4j.pax.exam.container.def.options.RepositoryOptionImpl;
import org.ops4j.pax.exam.container.def.options.VMOption;
import org.ops4j.pax.exam.container.def.options.WorkingDirectoryOption;
import org.ops4j.pax.exam.options.BootClasspathLibraryOption;
import org.ops4j.pax.exam.options.BootDelegationOption;
import org.ops4j.pax.exam.options.BundleStartLevelOption;
import org.ops4j.pax.exam.options.CustomFrameworkOption;
import org.ops4j.pax.exam.options.DebugClassLoadingOption;
import org.ops4j.pax.exam.options.FrameworkOption;
import org.ops4j.pax.exam.options.FrameworkStartLevelOption;
import org.ops4j.pax.exam.options.MavenPluginGeneratedConfigOption;
import org.ops4j.pax.exam.options.ProvisionOption;
import org.ops4j.pax.exam.options.SystemPackageOption;
import org.ops4j.pax.exam.options.SystemPropertyOption;
/**
* Utility methods for converting configuration options to Pax Runner arguments.
*
* @author Alin Dreghiciu (adreghiciu@gmail.com)
* @author Toni Menzel (toni@okidokiteam.com)
* @since 0.3.0 December 10, 2008
*/
class ArgumentsBuilder
{
/**
* Controls if one of the options set a Args Option manually.
* Otherwise, defaultArguments will include a --noArgs flag to prevent
* unintentional runner.args files being picked up by paxrunner.
*/
private boolean argsSetManually = false;
/**
* Pax Runner compatible arguments parsed from input.
*/
private final String[] m_parsedArgs;
/**
* There's a default location (users home) as well as an option for this.
* Effective working folder is of great importance not only to the pax runner instance.
*
* To make things simple, we store this property redundantly here.
* It is readable by a getter.
*/
private File m_workingFolder;
private Customizer[] m_customizers;
/**
* Converts configuration options to Pax Runner arguments.
*
* @param options array of configuration options
*/
ArgumentsBuilder( final Option... options )
{
final List<String> arguments = new ArrayList<String>();
m_customizers = filter( Customizer.class, options );
add( arguments, extractArguments( filter( MavenPluginGeneratedConfigOption.class, options ) ) );
add( arguments, extractArguments( filter( FrameworkOption.class, options ) ) );
add( arguments, extractArguments( filter( ProfileOption.class, options ) ) );
add( arguments, extractArguments( filter( BootDelegationOption.class, options ) ) );
add( arguments, extractArguments( filter( SystemPackageOption.class, options ) ) );
add( arguments, extractArguments( filter( ProvisionOption.class, options ) ) );
add( arguments,
extractArguments(
filter( RepositoryOptionImpl.class, options ),
filter( ExcludeDefaultRepositoriesOption.class, options )
)
);
add( arguments, extractArguments( filter( AutoWrapOption.class, options ) ) );
add( arguments, extractArguments( filter( CleanCachesOption.class, options ) ) );
add( arguments, extractArguments( filter( LocalRepositoryOption.class, options ) ) );
add( arguments, extractArguments( filter( FrameworkStartLevelOption.class, options ) ) );
add( arguments, extractArguments( filter( BundleStartLevelOption.class, options ) ) );
add( arguments, extractArguments( filter( WorkingDirectoryOption.class, options ) ) );
add( arguments, extractArguments( filter( RawPaxRunnerOptionOption.class, options ) ) );
add( arguments,
extractArguments(
filter( SystemPropertyOption.class, options ),
filter( VMOption.class, options )
)
);
add( arguments, extractArguments( filter( BootClasspathLibraryOption.class, options ) ) );
add( arguments, extractArguments( filter( DebugClassLoadingOption.class, options ) ) );
add( arguments, defaultArguments() );
m_parsedArgs = arguments.toArray( new String[arguments.size()] );
}
/**
* @return Pax Runner arguments
*/
public String[] getArguments()
{
return m_parsedArgs;
}
/**
* Adds a collection of arguments to a list of arguments by skipping null arguments.
*
* @param arguments list to which the arguments should be added
* @param argumentsToAdd arguments to be added (can be null or empty)
*/
private void add( final List<String> arguments,
final Collection<String> argumentsToAdd )
{
if( argumentsToAdd != null && argumentsToAdd.size() > 0 )
{
arguments.addAll( argumentsToAdd );
}
}
/**
* Adds an argumentto a list of arguments by skipping null or empty arguments.
*
* @param arguments list to which the arguments should be added
* @param argument argument to be added (can be null or empty)
*/
private void add( final List<String> arguments,
final String argument )
{
if( argument != null && argument.trim().length() > 0 )
{
arguments.add( argument );
}
}
/**
* Returns a collection of default Pax Runner arguments.
*
* @return collection of default arguments
*/
private Collection<String> defaultArguments()
{
final List<String> arguments = new ArrayList<String>();
arguments.add( "--noConsole" );
arguments.add( "--noDownloadFeedback" );
if( !argsSetManually )
{
arguments.add( "--noArgs" );
}
String folder = System.getProperty( "java.io.tmpdir" )
+ "/paxexam_runner_"
+ System.getProperty( "user.name" );
arguments.add( "--workingDirectory=" + createWorkingDirectory( folder ).getAbsolutePath() );
return arguments;
}
/**
* Converts framework options into corresponding arguments (--platform, --version).
*
* @param frameworks framework options
*
* @return converted Pax Runner collection of arguments
*
* @throws IllegalArgumentException - If there are more then one framework options
*/
private Collection<String> extractArguments( final FrameworkOption[] frameworks )
{
final List<String> arguments = new ArrayList<String>();
if( frameworks.length > 1 )
{
throw new IllegalArgumentException( "Configuration cannot contain more then one platform" );
}
if( frameworks.length > 0 )
{
if( frameworks[ 0 ] instanceof CustomFrameworkOption )
{
String basePlatform = ( (CustomFrameworkOption) frameworks[ 0 ] ).getBasePlatform();
if( basePlatform != null && basePlatform.trim().length() > 0 )
{
arguments.add( "--platform=" + basePlatform );
}
arguments.add( "--definitionURL=" + ( (CustomFrameworkOption) frameworks[ 0 ] ).getDefinitionURL() );
}
else
{
arguments.add( "--platform=" + frameworks[ 0 ].getName() );
final String version = frameworks[ 0 ].getVersion();
if( version != null && version.trim().length() > 0 )
{
arguments.add( "--version=" + version );
}
}
}
return arguments;
}
/**
* @return all arguments that have been recognized by OptionResolvers as PaxRunner arguments
*/
private Collection<String> extractArguments(
MavenPluginGeneratedConfigOption[] mavenPluginGeneratedConfigOption )
{
final List<String> arguments = new ArrayList<String>();
for( MavenPluginGeneratedConfigOption arg : mavenPluginGeneratedConfigOption )
{
URL url = arg.getURL();
arguments.add( "--args=" + url.toExternalForm() );
}
argsSetManually = true;
return arguments;
}
/**
* Converts provision options into corresponding arguments (provision urls).
*
* @param bundles provision options
*
* @return converted Pax Runner collection of arguments
*/
private Collection<String> extractArguments( final ProvisionOption[] bundles )
{
final List<String> arguments = new ArrayList<String>();
for( ProvisionOption bundle : bundles )
{
arguments.add( bundle.getURL() );
}
return arguments;
}
/**
* Converts profile options into corresponding arguments (--profiles).
*
* @param profiles profile options
*
* @return converted Pax Runner collection of arguments
*/
private static String extractArguments( final ProfileOption[] profiles )
{
final StringBuilder argument = new StringBuilder();
if( profiles != null && profiles.length > 0 )
{
for( ProfileOption profile : profiles )
{
if( profile != null && profile.getProfile() != null && profile.getProfile().length() > 0 )
{
if( argument.length() == 0 )
{
argument.append( "--profiles=" );
}
else
{
argument.append( "," );
}
argument.append( profile.getProfile() );
}
}
}
return argument.toString();
}
/**
* Converts boot delegation packages options into corresponding arguments (--bootDelegation).
*
* @param packages boot delegation package options
*
* @return converted Pax Runner collection of arguments
*/
private static String extractArguments( final BootDelegationOption[] packages )
{
final StringBuilder argument = new StringBuilder();
if( packages != null && packages.length > 0 )
{
for( BootDelegationOption pkg : packages )
{
if( pkg != null && pkg.getPackage() != null && pkg.getPackage().length() > 0 )
{
if( argument.length() == 0 )
{
argument.append( "--bootDelegation=" );
}
else
{
argument.append( "," );
}
argument.append( pkg.getPackage() );
}
}
}
return argument.toString();
}
/**
* Converts system package options into corresponding arguments (--systemPackages).
*
* @param packages system package options
*
* @return converted Pax Runner collection of arguments
*/
private String extractArguments( final SystemPackageOption[] packages )
{
final StringBuilder argument = new StringBuilder();
if( packages != null && packages.length > 0 )
{
for( SystemPackageOption pkg : packages )
{
if( pkg != null && pkg.getPackage() != null && pkg.getPackage().length() > 0 )
{
if( argument.length() == 0 )
{
argument.append( "--systemPackages=" );
}
else
{
argument.append( "," );
}
argument.append( pkg.getPackage() );
}
}
}
return argument.toString();
}
/**
* Converts system properties and vm options into corresponding arguments (--vmOptions).
*
* @param systemProperties system property options
* @param vmOptions virtual machine options
*
* @return converted Pax Runner argument
*/
private String extractArguments( final SystemPropertyOption[] systemProperties,
final VMOption[] vmOptions )
{
final StringBuilder argument = new StringBuilder();
if( systemProperties != null && systemProperties.length > 0 )
{
for( SystemPropertyOption property : systemProperties )
{
if( property != null && property.getKey() != null && property.getKey().trim().length() > 0 )
{
if( argument.length() > 0 )
{
argument.append( " " );
}
argument.append( "-D" ).append( property.getKey() ).append( "=" ).append( property.getValue() );
}
}
}
if( vmOptions != null && vmOptions.length > 0 )
{
for( VMOption vmOption : vmOptions )
{
if( vmOption != null && vmOption.getOption() != null && vmOption.getOption().trim().length() > 0 )
{
if( argument.length() > 0 )
{
argument.append( " " );
}
argument.append( vmOption.getOption() );
}
}
}
if( argument.length() > 0 )
{
argument.insert( 0, "--vmOptions=" );
}
return argument.toString();
}
/**
* Converts repository options into corresponding arguments (--repositories).
*
* @param repositoriesOptions repository options to be converted
* @param excludeDefaultRepositoriesOptions
* if array not empty the default list of maven repos should be excluded
*
* @return converted Pax Runner argument
*/
private String extractArguments( RepositoryOptionImpl[] repositoriesOptions,
ExcludeDefaultRepositoriesOption[] excludeDefaultRepositoriesOptions )
{
final StringBuilder argument = new StringBuilder();
final boolean excludeDefaultRepositories = excludeDefaultRepositoriesOptions.length > 0;
if( repositoriesOptions.length > 0 || excludeDefaultRepositories )
{
argument.append( "--repositories=" );
if( !excludeDefaultRepositories )
{
argument.append( "+" );
}
for( int i = 0; i < repositoriesOptions.length; i++ )
{
argument.append( repositoriesOptions[ i ].getRepository() );
if( i + 1 < repositoriesOptions.length )
{
argument.append( "," );
}
}
}
return argument.toString();
}
private String extractArguments( AutoWrapOption[] autoWrapOptions )
{
if( autoWrapOptions.length > 0 )
{
return "--autoWrap";
}
else
{
return null;
}
}
private String extractArguments( CleanCachesOption[] cleanCachesOption )
{
if( cleanCachesOption.length > 0 )
{
return "--clean";
}
else
{
return null;
}
}
private String extractArguments( LocalRepositoryOption[] localRepositoryOptions )
{
if( localRepositoryOptions != null && localRepositoryOptions.length > 0 )
{
LocalRepositoryOption local = localRepositoryOptions[ 0 ];
return "--localRepository=" + local.getLocalRepositoryPath();
}
return null;
}
private List<String> extractArguments( RawPaxRunnerOptionOption[] paxrunnerOptions )
{
List<String> args = new ArrayList<String>();
final boolean excludeDefaultRepositories = paxrunnerOptions.length > 0;
if( paxrunnerOptions.length > 0 || excludeDefaultRepositories )
{
for( int i = 0; i < paxrunnerOptions.length; i++ )
{
args.add( paxrunnerOptions[ i ].getOption().trim() );
}
}
return args;
}
private String extractArguments( WorkingDirectoryOption[] workingDirectoryOptions )
{
if( workingDirectoryOptions.length > 0 )
{
return "--workingDirectory=" + createWorkingDirectory( workingDirectoryOptions[ 0 ].getWorkingDirectory()
).getAbsolutePath();
}
return null;
}
/**
* Converts framework start level option into coresponding argument (--startLevel).
*
* @param startLevels framework start levels options
*
* @return converted Pax Runner collection of arguments
*
* @throws IllegalArgumentException - If there is more then one framework start level option
*/
private Collection<String> extractArguments( final FrameworkStartLevelOption[] startLevels )
{
final List<String> arguments = new ArrayList<String>();
if( startLevels.length > 1 )
{
throw new IllegalArgumentException( "Configuration cannot contain more then one framework start level" );
}
if( startLevels.length > 0 )
{
arguments.add( "--startLevel=" + startLevels[ 0 ].getStartLevel() );
}
return arguments;
}
/**
* Converts initial bundle start level option into coresponding argument (--bundleStartLevel).
*
* @param startLevels initial bundle start levels options
*
* @return converted Pax Runner collection of arguments
*
* @throws IllegalArgumentException - If there is more then one initial bundle start level option
*/
private Collection<String> extractArguments( final BundleStartLevelOption[] startLevels )
{
final List<String> arguments = new ArrayList<String>();
if( startLevels.length > 1 )
{
throw new IllegalArgumentException( "Configuration cannot contain more then one bundle start level" );
}
if( startLevels.length > 0 )
{
arguments.add( "--bundleStartLevel=" + startLevels[ 0 ].getStartLevel() );
}
return arguments;
}
/**
* Converts boot classpath library options into corresponding arguments (--bcp/a, --bcp/p).
*
* @param libraries boot classpath libraries
*
* @return converted Pax Runner collection of arguments
*/
private Collection<String> extractArguments( final BootClasspathLibraryOption[] libraries )
{
final List<String> arguments = new ArrayList<String>();
for( BootClasspathLibraryOption library : libraries )
{
if( library.isBeforeFramework() )
{
arguments.add( "--bcp/p=" + library.getLibraryUrl().getURL() );
}
else
{
arguments.add( "--bcp/a=" + library.getLibraryUrl().getURL() );
}
}
return arguments;
}
/**
* Converts debug class loading option into corresponding argument (--debugClassLoading).
*
* @param debugClassLoadingOptions debug class loading options
*
* @return converted Pax Runner argument
*/
private String extractArguments( final DebugClassLoadingOption[] debugClassLoadingOptions )
{
if( debugClassLoadingOptions.length > 0 )
{
return "--debugClassLoading";
}
else
{
return null;
}
}
/**
* Creates by default a working directory as ${java.io.tmpdir}/paxexam_runner_${user.name}.
* Unless manualWorkingDirectory is set.
*
* @param workingDirectoryOption
*
* @return created working directory
*/
private File createWorkingDirectory( String workingDirectoryOption )
{
final File workDir = new File( workingDirectoryOption );
// create if not existent:
if( !workDir.exists() )
{
workDir.mkdirs();
}
if( m_workingFolder == null )
{
m_workingFolder = workDir;
}
return workDir;
}
public File getWorkingFolder()
{
return m_workingFolder;
}
public Customizer[] getCustomizers()
{
return m_customizers;
}
}