/* * Copyright (c) 2010-2012 Research In Motion Limited. All rights reserved. * * This program and the accompanying materials are made available * under the terms of the Eclipse Public License, Version 1.0, * which accompanies this distribution and is available at * * http://www.eclipse.org/legal/epl-v10.html * */ package net.rim.ejde.internal.builders; import java.io.BufferedWriter; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.Writer; import java.util.ArrayList; import java.util.Calendar; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.MissingResourceException; import java.util.ResourceBundle; import java.util.Vector; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import net.rim.ejde.internal.core.ContextManager; import net.rim.ejde.internal.core.IConstants; import net.rim.ejde.internal.model.BlackBerryProject; import net.rim.ejde.internal.model.BlackBerryProperties; import net.rim.ejde.internal.model.BlackBerrySDKInstall; import net.rim.ejde.internal.util.PackagingUtils; import net.rim.ejde.internal.util.ProjectUtils; import net.rim.ejde.internal.util.ProjectUtils.RRHFile; import net.rim.ejde.internal.util.VMUtils; import net.rim.ide.core.VMConst; import net.rim.sdk.rc.ConvertUtil; import net.rim.sdk.resourceutil.ResourceCollection; import net.rim.sdk.resourceutil.ResourceCollectionFactory; import net.rim.sdk.resourceutil.ResourceElement; import net.rim.sdk.resourceutil.ResourceLocale; import net.rim.sdk.resourceutil.ResourceParseException; import net.rim.sdk.resourceutil.ResourceUtil; import org.apache.commons.lang.StringUtils; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; import org.eclipse.core.runtime.CoreException; import org.eclipse.jdt.launching.IVMInstall; import org.osgi.framework.Version; import org.w3c.dom.Document; import org.xml.sax.SAXException; /** * A simple tool to generate an ALX file based on the current project. * * This class was ripped out entirely from the JDE. * * @see net.rim.sdk.alxbuilder.AlxBuilder */ public final class ALXBuilder { private static final boolean DEBUG = false; // contants ---------------------------------------------------------------- private static final String PROPERTIES = "net.rim.sdk.alxbuilder.alxbuilder"; private static final String CLA_FILENAME = "CommandLineArg.filename"; // -filename private static final String CLA_APPLICATIONID = "CommandLineArg.appid"; // -applicationId private static final String CLA_NAME = "CommandLineArg.name"; // -name private static final String CLA_DESC = "CommandLineArg.description"; // -description private static final String CLA_VERSION = "CommandLineArg.version"; // -version private static final String CLA_VENDOR = "CommandLineArg.vendor"; // -vendor private static final String CLA_COPYRIGHT = "CommandLineArg.copyright"; // -copyright private static final String CLA_LANG = "CommandLineArg.lang"; // -lang - key value pairs -> id=id;name=<name>;desc=<desc> // there can be 0..N of this switch private static final String CLA_FILESET = "CommandLineArg.fileset"; // -vendor -fileset -> key value pairs: // dir=<dir>;files=<file1>?<file2>?...etc private static final String ALX_VERSION = "Version"; private static final String ALX_TAG_LOADER = "Tag.Loader"; private static final String ALX_TAG_LOADER_ATTR_VERSION = "Tag.Loader.Version"; private static final String ALX_TAG_APP = "Tag.Application"; private static final String ALX_TAG_APP_ATTR_ID = "Tag.Application.Id"; private static final String ALX_TAG_VERSION = "Tag.Version"; private static final String ALX_TAG_VENDOR = "Tag.Vendor"; private static final String ALX_TAG_COPYRIGHT = "Tag.Copyright"; private static final String ALX_TAG_LANG = "Tag.Language"; // language private static final String ALX_TAG_LANG_ATTR_ID = "Tag.Language.LangId"; // langid private static final String ALX_TAG_DESCRIPTION = "Tag.Description"; // description private static final String ALX_TAG_NAME = "Tag.Name"; // name private static final String ALX_TAG_FILESET = "Tag.FileSet"; // fileset private static final String ALX_TAG_FILESET_ATTRIBUTE = "Tag.FileSet.Attribute"; // Java private static final String ALX_TAG_FILESET_DIRECTORY = "Tag.FileSet.Directory"; // directory private static final String ALX_TAG_FILESET_FILES = "Tag.FileSet.Files"; // files private static final String ALX_TAG_ALX_IMPORT = "Tag.AlxImport"; // alx imports private static final String ALX_TAG_ALX_IMPORT_ATTR_ID = "Tag.AlxImport.Id"; // alx imports private static final String ALX_FILENAME_EXTENSION = "Filename.Extension"; // .alx private static final String ALX_COD_FILE_EXTENSION = "Filename.Cod.Extension"; // .cod private static final String VMVERSION = "1.0"; // debug only private static final String XML_DECLARATION = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>"; // required by xml parser private static final String BLACKBERRY_VERSION = " _blackberryVersion"; // statics ----------------------------------------------------------------- private static AlxProperties _props = new AlxProperties( PROPERTIES ); // inner classes ----------------------------------------------------------- /** * The Class Alx. */ public static final class Alx { private String _applicationId; private String _name; private String _desc; private String _version; private String _vendor; private String _copyright; private Vector< Language > _languages; // vector of Language objects private List< FileSet > _filesetList; private Vector< Alx > _dependencies; // further AlxElement items describing the dependencies of this module private Vector< AlxImport > _alxImports; // further AlxElement items describing required alx files /** * The core element of the ALX builder * <p> * This element contains all the information necessary to completely generate an ALX file * * @param appid * The id attribute specifies a unique identifier for the application. You should use an ID that includes your * company domain, in reverse, to ensure uniqueness (for example, net.rim.samples.contacts). * @param name * The name element provides a descriptive name for the application, which appears in the Application Loader. * It does not appear on the handheld. * @param desc * The description element provides a brief description of the application, which appears in the Application * Loader. It does not appear on the handheld. * @param version * The version element provides the version number of the application. This version number appears in the * Application Loader. * @param vendor * The vendor element provides the name of the company that created the application. The vendor name appears in * the Application Loader. * @param copyright * The copyright element provides copyright information, which appears in the Application Loader. * @param languages * a vector of Language objects describing application information. May be null * @param filesetList * a list of FileSet objects describing the location and file names of the CODs to load * @param dependencies * a vector of AlxElement objects describing further dependencies for this component. May be null. */ public Alx( String appid, String name, String desc, String version, String vendor, String copyright, Vector< Language > languages, List< FileSet > filesetList, Vector< Alx > dependencies, Vector< AlxImport > alxImports ) { _applicationId = appid == null ? "" : appid; _name = name == null ? "" : Alx.encodeSpecialChars( name ); _desc = desc == null ? "" : Alx.encodeSpecialChars( desc ); _version = version == null ? "" : Alx.encodeSpecialChars( version ); _vendor = vendor == null ? "" : Alx.encodeSpecialChars( vendor ); _copyright = copyright == null ? "" : Alx.encodeSpecialChars( copyright ); _languages = languages; _filesetList = filesetList; _dependencies = dependencies; _alxImports = alxImports; if( _dependencies == null ) { _dependencies = new Vector< Alx >( 0 ); // 0 length vector so the toElement routine doesn't need null checking } if( _languages == null ) { _languages = new Vector< Language >( 0 ); // 0 length vector so the toElement routine doesn't need null checking } if( _filesetList == null ) { throw new IllegalArgumentException(); } if( _alxImports == null ) { _alxImports = new Vector< AlxImport >( 0 ); } } /* package */Element toElement( AlxProperties props ) { Element e = new Element( props.getStringProperty( ALX_TAG_APP ) ); e.attribute( props.getStringProperty( ALX_TAG_APP_ATTR_ID ), _applicationId ); // the name ALXBuilder.debug( "adding name tag" ); Element name = new Element( props.getStringProperty( ALX_TAG_NAME ), _name ); e.add( name ); // description Element desc = new Element( props.getStringProperty( ALX_TAG_DESCRIPTION ), _desc ); e.add( desc ); // version Element ver = new Element( props.getStringProperty( ALX_TAG_VERSION ), _version ); e.add( ver ); // vendor Element vendor = new Element( props.getStringProperty( ALX_TAG_VENDOR ), _vendor ); e.add( vendor ); // copyright Element copyright = new Element( props.getStringProperty( ALX_TAG_COPYRIGHT ), _copyright ); e.add( copyright ); // langs try { for( int i = 0; i < _languages.size(); ++i ) { e.add( _languages.elementAt( i ).toElement( props ) ); } } catch( ClassCastException ex ) { System.err.println( "AlxBuilder: languages vector contains non Language class instance!!: " + ex ); return null; } // fileset for( FileSet fileSet : _filesetList ) { e.add( fileSet.toElement( props ) ); } // dependencies try { for( int i = 0; i < _dependencies.size(); ++i ) { e.add( _dependencies.elementAt( i ).toElement( props ) ); } } catch( ClassCastException ex ) { System.err.println( "AlxBuilder: dependencies vector contains non AlxElement class instance!!: " + ex ); return null; } // alx imports try { for( int i = 0; i < _alxImports.size(); ++i ) { e.add( _alxImports.elementAt( i ).toElement( props ) ); } } catch( ClassCastException ex ) { System.err.println( "AlxBuilder: alx imports vector contains non AlxElement class instance!!: " + ex ); return null; } ALXBuilder.debug( "element built" ); return e; } private static String encodeSpecialChars( String unencodedString ) { if( unencodedString == null ) { return null; } int length = unencodedString.length(); StringBuffer buffer = new StringBuffer( length ); for( int i = 0; i < length; ++i ) { char ch = unencodedString.charAt( i ); switch( ch ) { case '&': buffer.append( "&" ); break; case '\'': buffer.append( "'" ); break; case '"': buffer.append( """ ); break; case '<': buffer.append( "<" ); break; case '>': buffer.append( ">" ); break; default: if( ch > 127 ) { buffer.append( "&#" ); buffer.append( (int) ch ); buffer.append( ';' ); } else { buffer.append( ch ); } break; } } return buffer.toString(); } } /** * The Class Language. */ public static final class Language { private String _langid; private String _countrycode; private String _name; private String _description; /** * A language object for defining app name and description parameters in different languages * * @param languageId * iso3 representation of the language * @param countrycode * iso2 representation of the country, may be null * @param name * the name of the application in the apppropriate language * @param description * a description of the application in the appropriate language */ public Language( String languageId, String countrycode, String name, String description ) { _langid = languageId; _countrycode = countrycode; _name = name; _description = description; } /* pacakge */Element toElement( AlxProperties props ) { Element lang = new Element( props.getStringProperty( ALX_TAG_LANG ) ); String key = _langid + ( ( _countrycode != null ) && !_countrycode.equals( "" ) ? "_" + _countrycode : "" ); key = key.toLowerCase(); // always look for lower case string ALXBuilder.debug( "looking for windows language id for: " + key ); String windowsLangId = props.getStringProperty( key ); lang.attribute( props.getStringProperty( ALX_TAG_LANG_ATTR_ID ), windowsLangId ); Element name = new Element( props.getStringProperty( ALX_TAG_NAME ), _name ); Element description = new Element( props.getStringProperty( ALX_TAG_DESCRIPTION ), _description ); lang.add( name ); lang.add( description ); return lang; } } /** * The Class FileSet. */ public static final class FileSet { private String _directory; private Vector< String > _files; private String _vmVersion; private String _blackberryVersion; /** * the set of files that comprise the component * * @param dir * the directory from which the desktop loader will install the cods - (suggestion: the location of the main * JDP file) * @param files * a vector of strings containing the filenames * @param vmVersion * the minimum version of the java VM with which the cod files are compatible (currently 1.0) * @param bbVersion * the BlackBerry version the code file was compiled against */ public FileSet( String dir, Vector< String > files, String vmVersion, String bbVersion ) { _directory = dir; _files = files; _vmVersion = vmVersion; _blackberryVersion = bbVersion; } /* package */Element toElement( AlxProperties props ) { Element fileset = new Element( props.getProperty( ALX_TAG_FILESET ) ); fileset.attribute( props.getProperty( ALX_TAG_FILESET_ATTRIBUTE ), _vmVersion ); fileset.attribute( BLACKBERRY_VERSION, _blackberryVersion ); Element dir = new Element( props.getProperty( ALX_TAG_FILESET_DIRECTORY ), _directory ); String codExtension = props.getProperty( ALX_COD_FILE_EXTENSION ); StringBuffer sb = new StringBuffer(); for( int i = 0; i < _files.size(); ++i ) { String f = _files.elementAt( i ); if( !f.endsWith( codExtension ) ) { f = f + codExtension; // add the .cod extension if not present } sb.append( f ); sb.append( '\n' ); } Element files = new Element( props.getProperty( ALX_TAG_FILESET_FILES ), sb.toString() ); fileset.add( dir ); fileset.add( files ); return fileset; } } /** * The Class AlxImport. */ public static final class AlxImport { private String _filename; public AlxImport( String filename ) { _filename = filename; } Element toElement( AlxProperties props ) { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); FileInputStream in = null; Element alxImport = new Element( props.getStringProperty( ALX_TAG_ALX_IMPORT ) ); try { DocumentBuilder builder = factory.newDocumentBuilder(); // parse the required alx file for the application tag ALXBuilder.debug( "looking for external alx file: " + _filename ); // prepend the character-set spec to contents of alx file- required by parser in = new FileInputStream( new File( _filename ) ); byte[] declare = XML_DECLARATION.getBytes(); byte[] bs = new byte[ declare.length + in.available() ]; for( int i = 0; i < declare.length; ++i ) { bs[ i ] = declare[ i ]; } in.read( bs, declare.length, in.available() ); ByteArrayInputStream bin = new ByteArrayInputStream( bs ); Document document = builder.parse( bin ); org.w3c.dom.NodeList list = document.getElementsByTagName( props.getStringProperty( ALX_TAG_APP ) ); // use the first application tag found if( list.getLength() > 0 ) { org.w3c.dom.Node applicationNode = list.item( 0 ); org.w3c.dom.NamedNodeMap attributes = applicationNode.getAttributes(); org.w3c.dom.Node idNode = attributes.getNamedItem( props.getStringProperty( ALX_TAG_APP_ATTR_ID ) ); alxImport.attribute( props.getProperty( ALX_TAG_ALX_IMPORT_ATTR_ID ), idNode.getNodeValue() ); } } catch( SAXException sxe ) { System.err.println( "AlxBuilder: error parsing required alx file: " + sxe ); } catch( ParserConfigurationException pce ) { System.err.println( "AlxBuilder: alx file parser can't be build: " + pce ); } catch( IOException ioe ) { System.err.println( "AlxBuilder: i/o error parsing required alx file: " + ioe ); } finally { try { if( in != null ) { in.close(); } } catch( IOException e ) { // TODO Auto-generated catch block e.printStackTrace(); } } return alxImport; } } /** * from John Dahm's IDEProperties.java class in net.rim.ide (//depot/main/Lynx/ide) */ private static final class AlxProperties { private ResourceBundle _resources; public AlxProperties( String resourceName ) { _resources = ResourceBundle.getBundle( resourceName ); } String getStringProperty( String name ) { try { return _resources.getString( name ); } catch( MissingResourceException e ) { return null; } } String getProperty( String key ) { try { return _resources.getString( key ); } catch( MissingResourceException e ) { return null; } } } private static class Element { private String _key; private String _value; private Vector< Element > _elements = new Vector< Element >(); private StringBuffer _attributes = new StringBuffer(); public Element( String key ) { this( key, null ); } public Element( String key, String value ) { _key = key; _value = value; } public void add( Element e ) { _elements.addElement( e ); } /** * add an attribute to this element * * @param key * the attribute name * @param value * the value for this attribute */ public void attribute( String key, String value ) { _attributes.append( key ); _attributes.append( '=' ); _attributes.append( '"' ); _attributes.append( value ); _attributes.append( '"' ); } public void write( Writer out, String indent ) throws IOException { out.write( indent ); out.write( '<' ); out.write( _key ); out.write( ' ' ); out.write( _attributes.toString() ); if( ( _value != null ) || ( _elements.size() > 0 ) ) { String newindent = indent + "\t"; // add a tab out.write( ">\n" ); if( _value != null ) { out.write( newindent ); out.write( _value ); } for( int i = 0; i < _elements.size(); ++i ) { _elements.elementAt( i ).write( out, newindent ); } out.write( '\n' ); out.write( indent ); out.write( "</" ); out.write( _key ); out.write( ">\n" ); } else { out.write( "/>\n" ); } } } // methods ----------------------------------------------------------------- private ALXBuilder() { // empty private constructor - can't be instantiated } /** * Write out the ALX file. ALX files are used by the desktop tools to load applications onto devices * * @param filename * the name of alx file * @param AlxElement * the object comprising the ALX file */ public static boolean write( String fileName, Alx alx ) { if( ( fileName == null ) || ( alx == null ) ) { return false; } try { ALXBuilder.debug( "FileName: " + fileName ); // FileWriter fw = new FileWriter(fileName + _props.getStringProperty(ALX_FILENAME_EXTENSION)); FileOutputStream fos = new FileOutputStream( fileName + _props.getStringProperty( ALX_FILENAME_EXTENSION ) ); Writer fw = new BufferedWriter( new OutputStreamWriter( fos, "ISO8859_1" ) ); ALXBuilder.debug( "adding application tag" ); Element loader = new Element( _props.getStringProperty( ALX_TAG_LOADER ) ); loader.attribute( _props.getStringProperty( ALX_TAG_LOADER_ATTR_VERSION ), _props.getStringProperty( ALX_VERSION ) ); loader.add( alx.toElement( _props ) ); loader.write( fw, "" ); fw.close(); } catch( IOException ex ) { System.err.println( "AlxBuilder.write() failed:" + ex ); return false; } return true; } /** * Generates the alx based on the old method from RIA. * * @see net.rim.ide.Project.generateAlx() * * @param inherited * the inherited * @param bbProject * the java proj * * * @return the aLX builder. alx * * @throws CoreException * the core exception * @throws ResourceParseException * the resource parse exception * @throws FileNotFoundException * the file not found exception */ public static ALXBuilder.Alx generateAlx( HashMap inherited, BlackBerryProject bbProject ) throws CoreException, ResourceParseException, FileNotFoundException { return generateAlx( inherited, bbProject, true ); } private static ALXBuilder.Alx generateAlx( HashMap inherited, BlackBerryProject bbProject, boolean checkDependency ) throws CoreException, ResourceParseException, FileNotFoundException { if( inherited == null ) { inherited = new HashMap(); // used to pass values to projects this depends on } BlackBerryProperties properties = ContextManager.PLUGIN.getBBProperties( bbProject.getProject().getName(), false ); String outputName = properties._packaging.getOutputFileName(); int end = outputName.lastIndexOf( '.' ) == -1 ? outputName.length() : outputName.lastIndexOf( '.' ); String outputNamenoext = outputName.substring( 0, end ); // access the resource tools and generate AlxBuilder.Language instances for each langauge supported (we're // looking for the resources for Title and Description, if provided // Add the output file name to the list of files required for this app HashMap< String, Object > requiredFilesList = new HashMap< String, Object >(); // use a hashmap to eliminate duplicates requiredFilesList.put( outputName, null ); // Languages - generate an AlxBuilder.Lanuage instance for each language supported by the app Vector< Language > languages = new Vector< Language >(); // a vector to hold the Lanuage instances // If title resource not active, it is possibly a library,skip the languages step String titleResourceBundleClassName = properties._resources.getTitleResourceBundleClassName(); String titleResourceBundleKey = properties._resources.getTitleResourceBundleKey(); String rootTitle = IConstants.EMPTY_STRING, rootDescription = IConstants.EMPTY_STRING; if( properties._resources.hasTitleResource() && !StringUtils.isEmpty( titleResourceBundleClassName ) && !StringUtils.isEmpty( titleResourceBundleKey ) ) { ResourceCollection resources; Map< String, RRHFile > resourceMap = ProjectUtils.getProjectResources( bbProject ); IFile resourceFile = resourceMap.get( properties._resources.getTitleResourceBundleClassName() ).getFile(); if( resourceFile != null && resourceFile.exists() ) { resources = ResourceCollectionFactory.newResourceCollection( resourceFile.getLocation().toOSString() ); ResourceLocale[] resourceLocales = resources.getLocales(); String titlevalue = null, descvalue = null; for( ResourceLocale resourceLocale : resourceLocales ) { ResourceElement titleElement = resourceLocale.getResourceElement( properties._resources .getTitleResourceBundleKey() ); if( titleElement != null ) { titlevalue = ResourceUtil.unicodeToEscaped( titleElement.getValueAsString() ); } ResourceElement descrElement = resourceLocale.getResourceElement( properties._resources.getDescriptionId() ); if( descrElement != null ) { descvalue = ResourceUtil.unicodeToEscaped( descrElement.getValueAsString() ); } if( ( ( titlevalue == null ) && ( descvalue == null ) ) || ( ( titlevalue == null ) && ( descvalue.length() == 0 ) ) || ( ( titlevalue.length() == 0 ) && ( descvalue == null ) ) || ( ( titlevalue.length() == 0 ) && ( descvalue.length() == 0 ) ) ) { continue; } // don't generate a language element for the root if( resourceLocale.getLocaleName().equals( IConstants.EMPTY_STRING ) ) { // we need to remember the root title and the description values rootTitle = titlevalue; rootDescription = descvalue; continue; } Locale locale = ConvertUtil.localeValueOf( resourceLocale.getLocaleName() ); languages.addElement( new ALXBuilder.Language( locale.getISO3Language(), locale.getCountry(), titlevalue, descvalue ) ); } } } String copyright = "Copyright (c) " + Integer.toString( Calendar.getInstance().get( Calendar.YEAR ) ) + " " + properties._general.getVendor(); // TODO: what directory for the FileSet? currently using the vendor name as the subdir, with '_' substituted for ' ' /* * String dir = vendor.replace(' ', '_'); //String any trailing dots (windows strips them in path names for some reason) * dir = dir.endsWith(".") ? dir.substring(0, dir.length() - 1) : dir; */ String vmversion = VMConst.DebugAPIVersionMajor + "." + VMConst.DebugAPIVersionMinor; // Generate all the dependency ALX objects Vector< Alx > dependencies = new Vector< Alx >(); if( checkDependency ) { for( BlackBerryProject dependantProj : ProjectUtils.getAllReferencedProjects( bbProject ) ) { // we do not need to recursively check the dependent project dependencies.addElement( ALXBuilder.generateAlx( inherited, dependantProj, false ) ); } } // a vector to hold the alxImport instances Vector< AlxImport > alxImports = new Vector< AlxImport >(); // create a new alxImport for each filename IFile alxFile; for( String alxFileName : properties._packaging.getAlxFiles() ) { alxFile = bbProject.getProject().getFile( alxFileName ); if( alxFile.exists() ) { alxImports.addElement( new ALXBuilder.AlxImport( alxFile.getLocation().toOSString() ) ); } } List< IVMInstall > vmList = VMUtils.getInstalledBBVMs(); List< ALXBuilder.FileSet > fileSetList = new ArrayList< FileSet >(); BlackBerrySDKInstall bbVM; String currentVersionString; Version bbVersionLeftBound, bbVersionRightBound; String compatiableVersion; Collections.sort( vmList, new VMUtils.VMGeneralComparator() ); int indexOfNextValidVM = nextValidBBVM( null, vmList, bbProject ); while( indexOfNextValidVM >= 0 ) { bbVM = (BlackBerrySDKInstall) vmList.get( indexOfNextValidVM ); currentVersionString = bbVM.getVMVersion(); indexOfNextValidVM = nextValidBBVM( bbVM, vmList, bbProject ); if( indexOfNextValidVM > 0 ) { bbVersionLeftBound = new Version( currentVersionString ); bbVersionRightBound = new Version( bbVersionLeftBound.getMajor(), bbVersionLeftBound.getMinor(), bbVersionLeftBound.getMicro() + 1 ); compatiableVersion = "[" + currentVersionString + "," + bbVersionRightBound + ")"; } else { compatiableVersion = "[" + currentVersionString + ")"; } if( currentVersionString.equalsIgnoreCase( IConstants.HEADVER_VM_VERSION ) ) { currentVersionString = IConstants.HEADVER_VM_OUTPUTFOLDER; } fileSetList.add( new ALXBuilder.FileSet( currentVersionString, new Vector< String >( requiredFilesList.keySet() ), vmversion, compatiableVersion ) ); } if( properties._resources.hasTitleResource() && !StringUtils.isEmpty( titleResourceBundleClassName ) && !StringUtils.isEmpty( titleResourceBundleKey ) ) { // if resource is used, we use the root title and description return new ALXBuilder.Alx( outputNamenoext, rootTitle, rootDescription, properties._general.getVersion(), properties._general.getVendor(), copyright, languages, fileSetList, dependencies, alxImports ); } else { return new ALXBuilder.Alx( outputNamenoext, properties._general.getTitle(), properties._general.getDescription(), properties._general.getVersion(), properties._general.getVendor(), copyright, languages, fileSetList, dependencies, alxImports ); } } private static int nextValidBBVM( BlackBerrySDKInstall currentVM, List< IVMInstall > vmList, BlackBerryProject bbProject ) { BlackBerrySDKInstall bbVM; Version currentVersion, version; if( currentVM == null ) { currentVersion = Version.emptyVersion; } else { currentVersion = new Version( currentVM.getVMVersion() ); } for( int i = 0; i < vmList.size(); i++ ) { bbVM = (BlackBerrySDKInstall) vmList.get( i ); version = new Version( bbVM.getVMVersion() ); if( version.compareTo( currentVersion ) > 0 && hasPackaged( bbVM, bbProject ) ) { return i; } } return -1; } private static boolean hasPackaged( BlackBerrySDKInstall bbVM, BlackBerryProject bbProject ) { String outputFolderPath = PackagingUtils.getRelativeStandardOutputFolder( bbProject, bbVM ); IFolder outputFolder = bbProject.getProject().getFolder( outputFolderPath ); IFile codFile = outputFolder.getFile( bbProject.getProperties()._packaging.getOutputFileName() + IConstants.COD_FILE_EXTENSION_WITH_DOT ); if( codFile.exists() || codFile.getLocation().toFile().exists() ) { return true; } return false; } private static void debug( String msg ) { if( DEBUG ) { System.out.println( "[ALXBuilder] " + msg ); } } }