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.util; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.regex.Pattern; import net.rim.ejde.internal.core.ContextManager; import net.rim.ejde.internal.core.IConstants; import net.rim.ejde.internal.model.BlackBerrySDKInstall; import net.rim.ejde.internal.model.BlackBerryVMInstallType; import net.rim.ejde.internal.model.preferences.WarningsPreferences; import net.rim.ejde.internal.signing.BBSigningKeys; import net.rim.ejde.internal.sourcelookup.RIMClasspathProvider; import net.rim.ide.RIA; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.internal.launching.LaunchingMessages; import org.eclipse.jdt.launching.AbstractVMInstall; import org.eclipse.jdt.launching.IVMInstall; import org.eclipse.jdt.launching.IVMInstallType; import org.eclipse.jdt.launching.JavaRuntime; import org.eclipse.jdt.launching.VMStandin; import org.eclipse.jdt.launching.environments.ExecutionEnvironmentDescription; import org.osgi.framework.Version; /** * The Class VMUtils. * * @author cmalinescu, jheifetz, rgunartanam */ public class VMUtils { static private final Logger _log = Logger.getLogger(VMUtils.class); private static Map<String, BBSigningKeys> _signKeysCache = new HashMap<String, BBSigningKeys>(); /** * Gets the sign keys cache. * * @return the sign keys cache */ public static Map<String, BBSigningKeys> getSignKeysCache() { return _signKeysCache; } /** * Adds the sign keys to cache. * * @param vm * the vm * * @return the bB signing keys */ public static BBSigningKeys addSignKeysToCache(IVMInstall vm) { if (vm == null) { // This could happen in import failed due to a bug _log.error("No BlackBerry VM found and Signing Keys cache cannot be populated."); return null; } String vmName = vm.getName(); if (!_signKeysCache.containsKey(vmName)) { RIA ria = ContextManager.PLUGIN.getRIA(vm.getInstallLocation().getPath()); BBSigningKeys signingKeys = new BBSigningKeys(ria); _signKeysCache.put(vmName, signingKeys); _log.debug("SigningKey cache is populated for vm: " + vmName); return signingKeys; } return _signKeysCache.get(vmName); } /** * Removes the sign keys from cache. * * @param vm * the vm */ public static void removeSignKeysFromCache(IVMInstall vm) { if (vm == null) { // This could happen in import failed due to a bug _log.error("No BlackBerry VM found and Signing Keys cache cannot be populated."); return; } if (_signKeysCache.containsKey(vm.getName())) { _signKeysCache.remove(vm.getName()); _log.debug("SigningKey object for " + vm.getName() + " is removed from the cache."); } } /** * Convert key to preference label. * * @param keyId * the key id * @param vmName * the vm name * * @return the string */ public static String convertKeyToPreferenceLabel(Integer keyId, String vmName) { String id = null; if ((vmName != null)) { BBSigningKeys keyCache = VMUtils.getSignKeysCache().get(vmName); return VMUtils.convertKeyToPreferenceLabel(keyId, keyCache); } return id; } /** * Convert key to preference label. * * @param keyId * the key id * @param keyCache * the key cache * * @return the string */ public static String convertKeyToPreferenceLabel(Integer keyId, BBSigningKeys keyCache) { String id = null; if ((keyId != null) && (keyCache != null)) { id = ((keyCache.getKeyName(keyId) != null) ? keyCache.getKeyName(keyId).trim() : "") + " (0x" //$NON-NLS-1$//$NON-NLS-2$ + Integer.toHexString(keyId.intValue()) + ")";//$NON-NLS-1$ } return id; } /** * Convert preference label to key. * * @param preferenceLabel * the preference label * * @return the integer */ public static Integer convertPreferenceLabelToKey(String preferenceLabel) { int begin = preferenceLabel.indexOf("(0x"); int end = preferenceLabel.indexOf(')'); return Integer.valueOf(Integer.parseInt(preferenceLabel.substring(begin + 3, end), 16)); } /** * Convert code sign error msg to preference label. * * @param msg * the msg * * @return the string */ public static String convertCodeSignErrorMsgToPreferenceLabel(String msg) { int indexA = msg.indexOf(":"); String keyLabel = msg.substring(indexA + 1); int indexB = keyLabel.indexOf(":"); return keyLabel.substring(0, indexB).trim(); } /** * Gets the hidden classes filtered by preferences. * * @param vmName * the vm name * * @return the hidden classes filtered by preferences */ public static List<String> getHiddenClassesFilteredByPreferences(String vmName) { List<String> hiddenClasses = new ArrayList<String>(); if ((_signKeysCache != null) && (vmName != null) && _signKeysCache.containsKey(vmName)) { BBSigningKeys keyCache = _signKeysCache.get(vmName); // These must be generated through addition, as keyCache.getProtectedClasses() contains classes // not associated with any of the desired keys. for (int key : keyCache.getKeys()) { Integer iKey = Integer.valueOf(key); if (!WarningsPreferences.getWarnStatus(VMUtils.convertKeyToPreferenceLabel(iKey, vmName))) { hiddenClasses.addAll(keyCache.getClassesByKey(iKey)); } } } return hiddenClasses; } /** * This method returns the list of BlackBerry specific VMs (JREs). * * @return bbVMlist List<IVMInstall> */ public static List<IVMInstall> getInstalledBBVMs() { final IVMInstallType bbVMType = JavaRuntime.getVMInstallType(BlackBerryVMInstallType.VM_ID); if (bbVMType != null) { return Arrays.asList(bbVMType.getVMInstalls()); } return new ArrayList<IVMInstall>(); } /** * Gets all the installed VMs. * * @return the installed VMs */ public static IVMInstall[] getInstalledVMs() { List<IVMInstall> vms = new ArrayList<IVMInstall>(); for (IVMInstallType vmType : JavaRuntime.getVMInstallTypes()) { for (IVMInstall vm : vmType.getVMInstalls()) { vms.add(vm); } } return vms.toArray(new IVMInstall[vms.size()]); } /** * Gets the Installed BlackBerry specific VMs (JRE) with the matching ID. * * @param name * the name * * @return the bBVM */ public static IVMInstall getBBVM(String vmID) { final IVMInstallType bbVMType = JavaRuntime.getVMInstallType(BlackBerryVMInstallType.VM_ID); if (bbVMType != null) { return bbVMType.findVMInstall(vmID); } return null; } /** * This method returns the HashMap of BlackBerry specific VMs (JREs) Java doc locations with VMs names as a key. * * @return bbVMMap Map< String, String > */ public static ArrayList<Map.Entry<String, String>> getJREDocsLocation() { Map<String, String> bbVMMap = new HashMap<String, String>(); for (IVMInstall vm : VMUtils.getInstalledBBVMs()) { bbVMMap.put(vm.getName(), vm.getJavadocLocation().toString()); } ArrayList<Map.Entry<String, String>> bbVMList = new ArrayList<Map.Entry<String, String>>( bbVMMap.entrySet()); Collections.sort(bbVMList, new VMMapEntryComparator()); return bbVMList; } /** * This method returns the default BlackBerry specific VM (JRE) based on following logic: When user already selected a * BlackBerry VM as a default installed VM then this method will return the default installed VM other wise it will iterate * through the BB specific VMs and pick the highest version as a default or return null when there is no BB specific VM is * available for iteration. * * @return defaultVM IVMInstall */ public static IVMInstall getDefaultBBVM() { IVMInstall defaultVm = JavaRuntime.getDefaultVMInstall(); if ((null == defaultVm) || !BlackBerryVMInstallType.VM_ID.equals(defaultVm.getVMInstallType().getId())) { defaultVm = null; // reset the default VM String vmId = null; // no default is found from workspace preferences and default // installed VM is either null or no BlackBerry type for (final IVMInstall vm : VMUtils.getInstalledBBVMs()) { if (BlackBerryVMInstallType.VM_ID.equals(vm.getVMInstallType().getId())) { vmId = vm.getId(); if (defaultVm == null) { defaultVm = vm; } else { if (defaultVm.getId().compareTo(vmId) < 0) { defaultVm = vm; } } } } } return defaultVm; // when no bb vm exists returns null } /** * Creates a new VM based on the attributes specified in the given execution environment description file. The format of the * file is defined by <code>http://wiki.eclipse.org/Execution_Environment_Descriptions</code>. * * @param eeFile * VM definition file * @param name * name for the VM, or <code>null</code> if a default name should be assigned * @param id * id to assign to the new VM * * @return VM standin * * @throws CoreException * the core exception * * @exception CoreException * if unable to create a VM from the given definition file */ public static VMStandin createVMFromDefinitionFile(final File eeFile, String name, final String id) throws CoreException { if ((null == eeFile) || !eeFile.exists() || !eeFile.isFile()) { return null; } synchronized (eeFile) { final ExecutionEnvironmentDescription description = new ExecutionEnvironmentDescription(eeFile); final BlackBerryVMInstallType bbType = (BlackBerryVMInstallType) JavaRuntime .getVMInstallType(BlackBerryVMInstallType.VM_ID); final IStatus defFileValidityStatus = BlackBerryVMInstallType.validateDefinitionFile(description); if (defFileValidityStatus.isOK()) { final VMStandin standin = new VMStandin(bbType, id); String vmName = name; if ((name == null) || (name.length() <= 0)) { vmName = description.getProperty(ExecutionEnvironmentDescription.EE_NAME); if (vmName == null) { vmName = eeFile.getName(); } } standin.setName(vmName); final String home = description.getProperty(ExecutionEnvironmentDescription.JAVA_HOME); final File homeFile = new File(home); final IStatus installLocValidityStatus = bbType.validateInstallLocation(homeFile); if (!installLocValidityStatus.isOK()) { throw new CoreException(installLocValidityStatus); } standin.setInstallLocation(new File(home)); standin.setLibraryLocations(description.getLibraryLocations()); standin.setVMArgs(description.getVMArguments()); standin.setJavadocLocation(BlackBerryVMInstallType.getJavadocLocation(description.getProperties())); standin.setAttribute(BlackBerryVMInstallType.ATTR_EXECUTION_ENVIRONMENT_ID, description.getProperty(ExecutionEnvironmentDescription.CLASS_LIB_LEVEL)); File exe = description.getExecutable(); if (exe == null) { exe = description.getConsoleExecutable(); } if (exe != null) { try { standin.setAttribute(BlackBerryVMInstallType.ATTR_JAVA_EXE, exe.getCanonicalPath()); } catch (final IOException e) { throw new CoreException(new Status(IStatus.ERROR, ContextManager.PLUGIN_ID, LaunchingMessages.JavaRuntime_24, e)); } } standin.setAttribute(BlackBerryVMInstallType.ATTR_JAVA_VERSION, description.getProperty(ExecutionEnvironmentDescription.LANGUAGE_LEVEL)); standin.setAttribute(BlackBerryVMInstallType.ATTR_DEFINITION_FILE, eeFile.getPath()); standin.setAttribute(BlackBerryVMInstallType.ATTR_DEBUG_ARGS, description.getProperty(ExecutionEnvironmentDescription.DEBUG_ARGS)); standin.setAttribute(BlackBerryVMInstallType.ATTR_RAPC_OUTPUT_FOLDER, description.getProperty(BlackBerryVMInstallType.EE_RAPC_OUTPUT_FOLDER)); standin.setAttribute(BlackBerryVMInstallType.ATTR_CLASSPATH_PROVIDER, RIMClasspathProvider.RIM_CLASSPATH_PROVIDER_ID); standin.setAttribute(BlackBerryVMInstallType.ATTR_DESCRIPTION, description.getProperty(BlackBerryVMInstallType.EE_DESCRIPTION)); standin.setAttribute(BlackBerryVMInstallType.ATTR_INTERNAL, description.getProperty(BlackBerryVMInstallType.EE_INTERNAL)); standin.setAttribute(BlackBerryVMInstallType.ATTR_DIRECTIVE, description.getProperty(BlackBerryVMInstallType.EE_DIRECTIVE)); standin.setAttribute(BlackBerryVMInstallType.ATTR_VERSION, description.getProperty(BlackBerryVMInstallType.EE_VERSION)); return standin; } _log.error("Failed createVMFromDefinitionFile: " + eeFile.getPath() + "| " + defFileValidityStatus); throw new CoreException(defFileValidityStatus); } } /** * Creates a new VM based on the attributes specified in the given execution environment description file. The format of the * file is defined by <code>http://wiki.eclipse.org/Execution_Environment_Descriptions</code>. * * @param eeFile * VM definition file * @param force * Boolean whether to force creation of VM depsite naming conflicts * * @return VM standin * * @throws CoreException * the core exception * * @exception CoreException * if unable to create a VM from the given definition file */ public static VMStandin createVMFromDefinitionFile(final File eeFile, boolean force) throws CoreException { VMStandin vm = null; final BlackBerryVMInstallType blackBerryVMInstallType = (BlackBerryVMInstallType) JavaRuntime .getVMInstallType(BlackBerryVMInstallType.VM_ID); if (blackBerryVMInstallType == null) { throw new CoreException(new Status(IStatus.WARNING, ContextManager.PLUGIN_ID, "Could not find instance of BlackBerry VM Install Type")); } final String vmName = VMUtils.getPropertyFromEEFile(eeFile, ExecutionEnvironmentDescription.EE_NAME); _log.trace("Attempting to create VM with name - " + vmName); if (force || (VMUtils.isVMNameValid(vmName) && (null == blackBerryVMInstallType.findVMInstall(vmName)))) { vm = VMUtils.createVMFromDefinitionFile(eeFile, vmName, vmName); } else { _log.trace("VM Creation skipped"); } return vm; } /** * Checks if is vM name valid. * * @param newName * the new name * * @return true, if is vM name valid */ private static boolean isVMNameValid(final String newName) { if ((newName == null) || (newName.trim().length() == 0)) { return false; } if (VMUtils.isDuplicateName(newName)) { return false; } final IStatus s = ResourcesPlugin.getWorkspace().validateName(newName, IResource.FILE); if (!s.isOK()) { return false; } return true; } /** * Checks if is duplicate name. * * @param newName * the new name * * @return true, if is duplicate name */ private static boolean isDuplicateName(final String newName) { final IVMInstall[] vms = JavaRuntime.getVMInstallType(BlackBerryVMInstallType.VM_ID).getVMInstalls(); for (final IVMInstall vm : vms) { if (newName.equals(vm.getName())) { return true; } } return false; } /** * Gets the string value of an EE property from a given EE file. * * @param eeFile * the ee file * @param property * the property * * @return the string value of the property */ static public String getPropertyFromEEFile(final File eeFile, final String property) { if ((null != eeFile) && eeFile.exists() && eeFile.isFile()) { InputStream inputStream = null; Properties properties = null; WeakReference<Properties> propsStub = null; WeakReference<InputStream> streamStub = null; try { propsStub = new WeakReference<Properties>(new Properties()); properties = propsStub.get(); streamStub = new WeakReference<InputStream>(new FileInputStream(eeFile)); inputStream = streamStub.get(); properties.load(inputStream); final String id = properties.getProperty(property); return id; } catch (final FileNotFoundException e) { _log.error("", e); //$NON-NLS-1$ } catch (final IOException e) { _log.error("", e); //$NON-NLS-1$ } finally { if (null != properties) { properties.clear(); if (propsStub != null) { propsStub.clear(); propsStub = null; } } if (null != inputStream) { try { inputStream.close(); if (streamStub != null) { streamStub.clear(); streamStub = null; } } catch (final IOException e) { _log.error("", e); //$NON-NLS-1$ } } } } return StringUtils.EMPTY; } /** * This method returns true when BlackBerry specific VM (JRE) is the default installed VM (JRE) in the workspace otherwise * false. * * @return boolean */ public static boolean isBlackBerryRuntimeTheWorkspaceDefault() { final IVMInstall install = JavaRuntime.getDefaultVMInstall(); if (null != install) { final IVMInstallType installType = install.getVMInstallType(); if (BlackBerryVMInstallType.VM_ID.equals(installType.getId())) { return true; } } return false; } /** * Checks if the given <code>vm</code> is a BlackBerry vm. * * @param vm * the vm * * @return true, if checks if is black berry vm */ public static boolean isBlackBerryVM(IVMInstall vm) { final IVMInstallType installType = vm.getVMInstallType(); if (BlackBerryVMInstallType.VM_ID.equalsIgnoreCase(installType.getId())) { return true; } return false; } /** * The Class VMComparator. */ static class VMMapEntryComparator implements Comparator<Map.Entry<String, ?>> { /* * (non-Javadoc) * * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object) */ public int compare(final Map.Entry<String, ?> obj1, final Map.Entry<String, ?> obj2) { final String word1 = obj1.getKey(); final String word2 = obj2.getKey(); return word1.compareToIgnoreCase(word2); } } /** * The Class VMComparator. */ static public class VMGeneralComparator implements Comparator<IVMInstall> { /* * (non-Javadoc) * * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object) */ public int compare(final IVMInstall obj1, final IVMInstall obj2) { final BlackBerrySDKInstall bbVM1 = (BlackBerrySDKInstall) obj1; final BlackBerrySDKInstall bbVM2 = (BlackBerrySDKInstall) obj2; final Version version1 = new Version(bbVM1.getVMVersion()); final Version version2 = new Version(bbVM2.getVMVersion()); return version1.compareTo(version2); } } /** * The class VMVersionComparator. * * @author bkurz * */ public static class VMVersionComparator implements Comparator<String> { @Override public int compare(String o1, String o2) { String[] tokensFirstVersion = o1.split("[.]"); String[] tokensSecondVersion = o2.split("[.]"); for (int i = 0; i < tokensFirstVersion.length; i++) { if (Integer.valueOf(tokensFirstVersion[i]) < Integer.valueOf(tokensSecondVersion[i])) { return -1; } else if (Integer.valueOf(tokensFirstVersion[i]) > Integer.valueOf(tokensSecondVersion[i])) { return 1; } } return 0; } } /** * Find VM by the given name. * * @param vmName * The VM name to be searched * @return The <code>IVMInstall</code> if found; or <code>null</code> */ public static IVMInstall findVMByName(String vmName) { List<IVMInstall> vms = VMUtils.getInstalledBBVMs(); for (IVMInstall vm : vms) { if (vm.getName().equals(vmName)) { return vm; } } return null; } /** * Find VM by the given id. * * @param vmId * The VM id to be searched * @return The <code>IVMInstall</code> if found; or <code>null</code> */ public static IVMInstall findVMById(String vmId) { List<IVMInstall> vms = VMUtils.getInstalledBBVMs(); for (IVMInstall vm : vms) { if (vm.getId().equals(vmId)) { return vm; } } return null; } /** * Returns the version of the given VM. It looks from the last segment of "ee.description". If it is not a valid version * string (x.x.x.x), returns default version 0.0.0.0. * * @param vm * The VM * @return The version of the VM. */ public static String getVMVersion(IVMInstall vm) { BlackBerrySDKInstall bbVM = (BlackBerrySDKInstall) vm; String ver = bbVM.getAttribute(BlackBerryVMInstallType.ATTR_VERSION); // new VMs has version in ee.version property if (ver != null) { return ver; } String desc = bbVM.getAttribute(BlackBerryVMInstallType.ATTR_DESCRIPTION); // Handle old VMs that do not have the description attribute if (desc == null) { return IConstants.DEFAULT_VM_VERSION; } String[] tokens = desc.split(" "); String version = IConstants.DEFAULT_VM_VERSION; if (tokens.length > 0) { if (Pattern.matches("[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+", tokens[tokens.length - 1])) { version = tokens[tokens.length - 1]; } else { _log.error("Invalid VM version found on " + vm.getId()); } } return version; } /** * Returns the SDK with the highest version number * * @return */ public static IVMInstall getLatestSDK() { IVMInstall latestVMInstall = null; VMVersionComparator comparator = new VMVersionComparator(); List<IVMInstall> installedSDK = VMUtils.getInstalledBBVMs(); for (IVMInstall vmInstall : installedSDK) { if (latestVMInstall == null || comparator.compare(VMUtils.getVMVersion(latestVMInstall), VMUtils.getVMVersion(vmInstall)) == -1) { latestVMInstall = vmInstall; } } return latestVMInstall; } /** * Returns if the given vm is an internal one (aka lynx) * * @param vm * The given VM * @return <code>true</code> if yes; otherwise returns <code>false</code> */ public static boolean isInternal(IVMInstall vm) { String isInternal = ((AbstractVMInstall) vm).getAttribute(BlackBerryVMInstallType.ATTR_INTERNAL); return isInternal != null && Integer.parseInt(isInternal) == 1; } /** * Gets the JRE level pre-defined preprocess directive for the given <code>bbVM</code>. If the .directive attribute is * specified in the .ee file (JAVA SDK after 12/17/09), will take precedence * * @param bbVM * @return */ public static String getJREDirective(BlackBerrySDKInstall bbVM) { if (bbVM == null) { return IConstants.EMPTY_STRING; } String bbvmd = bbVM.getAttribute(BlackBerryVMInstallType.ATTR_DIRECTIVE); if (bbvmd == null || bbvmd.length() == 0) { bbvmd = ContextManager.getDefault().getPreferenceStore().getString(IConstants.JRE_DIRECTIVE_PREFIX_KEY) + bbVM.getAttribute(BlackBerryVMInstallType.ATTR_RAPC_OUTPUT_FOLDER); } return bbvmd; } /** * Get the component pack level pre-defined preprocess directive for all installed BlackBerry JRE. * * @return */ static public final List<String> getAllJREDirectives() { List<String> directives = new ArrayList<String>(); List<IVMInstall> vmList = VMUtils.getInstalledBBVMs(); Collections.sort(vmList, new VMUtils.VMGeneralComparator()); BlackBerrySDKInstall bbVM; String JREDirective; for (int i = 0; i < vmList.size(); i++) { bbVM = (BlackBerrySDKInstall) vmList.get(i); JREDirective = VMUtils.getJREDirective(bbVM); if (!StringUtils.isBlank(JREDirective)) { directives.add(JREDirective); } } return directives; } /** * Get the component pack level pre-defined preprocess directive for the given <code>project</code>. * * @param project * @return */ static public final String getJREDirective(IJavaProject project) { BlackBerrySDKInstall bbVM; try { IVMInstall vm = JavaRuntime.getVMInstall(project); if (!(vm instanceof BlackBerrySDKInstall)) { if (vm != null) { _log.trace(vm.getName() + " is not a BlackBerry JRE"); } else { _log.trace(project.getProject().getName() + " does not have a valid BlackBerry JRE"); } return IConstants.EMPTY_STRING; } bbVM = (BlackBerrySDKInstall) JavaRuntime.getVMInstall(project); return VMUtils.getJREDirective(bbVM); } catch (CoreException e) { _log.error(e.getMessage()); return IConstants.EMPTY_STRING; } } }