Java tutorial
/* * 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); } } }