Java tutorial
/* * Created on Mar 22, 2007 Copyright (C) 2001-5, Anthony Harrison anh23@pitt.edu * (jactr.org) This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of the License, * or (at your option) any later version. This library is distributed in the * hope that it will be useful, but WITHOUT ANY WARRANTY; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See * the GNU Lesser General Public License for more details. You should have * received a copy of the GNU Lesser General Public License along with this * library; if not, write to the Free Software Foundation, Inc., 59 Temple * Place, Suite 330, Boston, MA 02111-1307 USA */ package org.jactr.eclipse.runtime.launching; import java.net.URI; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.TreeSet; import org.antlr.runtime.tree.CommonTree; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IWorkspaceRoot; 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.debug.core.ILaunchConfiguration; import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; import org.eclipse.debug.core.ILaunchManager; import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants; import org.eclipse.pde.core.plugin.IPluginModelBase; import org.eclipse.pde.core.plugin.PluginRegistry; import org.eclipse.pde.core.plugin.TargetPlatform; import org.eclipse.pde.internal.launching.IPDEConstants; import org.jactr.eclipse.core.CorePlugin; import org.jactr.eclipse.core.bundles.BundleUtilities; import org.jactr.eclipse.core.bundles.descriptors.InstrumentDescriptor; import org.jactr.eclipse.core.bundles.descriptors.IterativeListenerDescriptor; import org.jactr.eclipse.core.bundles.descriptors.ModuleDescriptor; import org.jactr.eclipse.core.bundles.descriptors.RuntimeTracerDescriptor; import org.jactr.eclipse.core.bundles.descriptors.SensorDescriptor; import org.jactr.eclipse.core.bundles.registry.InstrumentRegistry; import org.jactr.eclipse.core.bundles.registry.IterativeListenerRegistry; import org.jactr.eclipse.core.bundles.registry.ModuleRegistry; import org.jactr.eclipse.core.bundles.registry.RuntimeTracerRegistry; import org.jactr.eclipse.core.bundles.registry.SensorRegistry; import org.jactr.eclipse.core.comp.CompilationUnitManager; import org.jactr.eclipse.core.comp.ICompilationUnit; import org.jactr.eclipse.runtime.RuntimePlugin; import org.jactr.eclipse.runtime.preferences.RuntimePreferences; import org.jactr.io.antlr3.builder.JACTRBuilder; import org.jactr.io.antlr3.misc.ASTSupport; /** * builds a valid ILaunchConfiguration for the ACTR launch environment, which * currently relies upon the PDE launch set up. * * @author developer */ public class ACTRLaunchConfigurationUtils { static private final Log LOGGER = LogFactory.getLog(ACTRLaunchConfigurationUtils.class); /** * return the project defined in the configuration * * @param configuration * @return project * @throws CoreException * if project doesnt exist */ static public IProject getProject(ILaunchConfiguration configuration) throws CoreException { IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); String projectName = configuration.getAttribute(IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, ""); try { IProject sourceProject = root.getProject(projectName); if (sourceProject.exists() && sourceProject.isOpen()) return sourceProject; else throw new RuntimeException("Could not get valid project from launchConfig:" + configuration); } catch (Exception e) { throw new RuntimeException("Could not get valid project from launchConfig:" + configuration, e); } } /** * return all the model files defined in the launch configuration * * @param configuration * @return * @throws CoreException * if none are defined */ static public Collection<IResource> getModelFiles(ILaunchConfiguration configuration) throws CoreException { IProject project = getProject(configuration); ArrayList<IResource> resources = new ArrayList<IResource>(); if (project == null) return resources; for (String modelFile : configuration.getAttribute(ACTRLaunchConstants.ATTR_MODEL_FILES, "").split(",")) if (modelFile.length() > 0) { IResource resource = project.findMember(modelFile, false); if (resource != null) resources.add(resource); } return resources; } /** * checks all the model files in the configuration for modules. if any of the * modules requires common reality then a sensor must have been defined. this * does not validate that the sensors actually meet the requirements of the * modules * * @param configuration * @return true if it does. throws exception otherwise * @throws CoreException */ static public boolean meetsCommonRealityRequirements(ILaunchConfiguration configuration) throws CoreException { boolean hasSensors = getRequiredSensors(configuration).size() != 0 || configuration.getAttribute(ACTRLaunchConstants.ATTR_USE_EMBED_CONTROLLER, false); for (IResource modelFile : getModelFiles(configuration)) for (ModuleDescriptor module : getModulesInModel(modelFile)) if (module.requiresCommonReality() && !hasSensors) throw new RuntimeException(modelFile.getName() + " requires CommonReality because of " + module.getName() + ", but no sensors are configured."); return true; } /** * returns all the modules required in a specific model * * @param modelFile * @return */ static public Collection<ModuleDescriptor> getModulesInModel(IResource modelFile) { ArrayList<ModuleDescriptor> modules = new ArrayList<ModuleDescriptor>(); Collection<ModuleDescriptor> allModules = ModuleRegistry.getRegistry() .getDescriptors(modelFile.getProject(), true); ICompilationUnit compilationUnit = CompilationUnitManager.acquire(modelFile); try { CommonTree modelTree = compilationUnit.getModelDescriptor(); if (modelTree == null) throw new IllegalArgumentException(modelFile.getName() + " has errors"); Map<String, CommonTree> extMap = ASTSupport.getMapOfTrees(modelTree, JACTRBuilder.MODULE); for (CommonTree extTree : extMap.values()) { String className = ((CommonTree) extTree.getFirstChildWithType(JACTRBuilder.CLASS_SPEC)).getText(); for (ModuleDescriptor module : allModules) if (module.getClassName().equals(className)) { modules.add(module); break; } /* * we might be tempted to throw an exception if there is an unresolved * class, but we hold that for the runtime itself */ } return modules; } finally { if (compilationUnit != null) CompilationUnitManager.release(compilationUnit); } } /** * return all the aliases for a specific model in the configuration * * @param modelFile * @param configuration * @return * @throws CoreException */ static public Collection<String> getModelAliases(IResource modelFile, ILaunchConfiguration configuration) throws CoreException { String path = modelFile.getFullPath().toOSString(); Set<String> aliases = new HashSet<String>(); for (String alias : configuration.getAttribute(ACTRLaunchConstants.ATTR_MODEL_ALIASES + path, "") .split(",")) { alias = alias.trim(); if (alias.length() > 0) aliases.add(alias); } return aliases; } /** * sets up the basic parameters needed for the eclipse launch. these are the * attributes that are set once and never need modifying * * @param workingCopy */ static public void setupPermanentAttributes(ILaunchConfigurationWorkingCopy workingCopy) throws CoreException { workingCopy.setAttribute(org.eclipse.pde.launching.IPDELauncherConstants.AUTOMATIC_VALIDATE, RuntimePlugin.getDefault().getPluginPreferences().getBoolean(RuntimePreferences.VERIFY_RUN_PREF)); /* * First, we tell the PDE launcher that we will be running an application * and what that application is */ workingCopy.setAttribute(org.eclipse.pde.launching.IPDELauncherConstants.USE_PRODUCT, false); if (workingCopy.getAttribute(ACTRLaunchConstants.ATTR_ITERATIONS, 0) == 0) workingCopy.setAttribute(org.eclipse.pde.launching.IPDELauncherConstants.APPLICATION, ACTRLaunchConstants.DEFAULT_APPLICATION); else workingCopy.setAttribute(org.eclipse.pde.launching.IPDELauncherConstants.APPLICATION, ACTRLaunchConstants.ITERATIVE_APPLICATION); /* * then we tell it where the workspace should be.. * ${system_property:user.home}/.jactr/workspaces/${project_name} this will * be resolved by the launcher */ workingCopy.setAttribute(org.eclipse.pde.launching.IPDELauncherConstants.LOCATION, ACTRLaunchConstants.NORMAL_WORKSPACE_LOCATION); /* * if true, we'd load ALL the bundles that are present in the current * environment we only want to load the required ones that we selected above */ workingCopy.setAttribute(org.eclipse.pde.launching.IPDELauncherConstants.USE_DEFAULT, false); /* * exclude optional bundles */ workingCopy.setAttribute(org.eclipse.pde.launching.IPDELauncherConstants.INCLUDE_OPTIONAL, false); /* * don't add everything in the workspace */ workingCopy.setAttribute(org.eclipse.pde.launching.IPDELauncherConstants.AUTOMATIC_ADD, false); /* * */ workingCopy.setAttribute(org.eclipse.pde.launching.IPDELauncherConstants.DESELECTED_WORKSPACE_PLUGINS, (String) null); if (LOGGER.isDebugEnabled()) LOGGER.debug("Applied permanent attributes " + workingCopy); } /** * set up the attributes that we just apply after Apply is clicked in the * config dialog * * @param workingCopy */ static public void setupPersistentAttributes(ILaunchConfigurationWorkingCopy workingCopy) throws CoreException { /* * we will use the default configuration location, which should be the * current environment's.. the name is RUNTYPE:runName.. */ IProject project = getProject(workingCopy); String configName = workingCopy.getName(); workingCopy.setAttribute(org.eclipse.pde.launching.IPDELauncherConstants.CONFIG_USE_DEFAULT_AREA, false); workingCopy.setAttribute(org.eclipse.pde.launching.IPDELauncherConstants.CONFIG_LOCATION, ACTRLaunchConstants.NORMAL_CONFIGURATION_LOCATION + project.getName() + "/" + configName); /* * what about core logging? that needs to be set up by the tab but for now.. */ boolean logging = workingCopy.getAttribute(ACTRLaunchConstants.ATTR_DEBUG_CORE_ENABLED, false); if (logging) { IResource logFile = project.findMember(workingCopy.getAttribute( ACTRLaunchConstants.ATTR_DEBUG_CORE_LOG_CONF, ACTRLaunchConstants.DEFAULT_CORE_LOG_CONF)); if (logFile != null && logFile.exists()) { StringBuilder vmArg = new StringBuilder(" -Dorg.apache.commons.logging.log="); vmArg.append(workingCopy.getAttribute(ACTRLaunchConstants.ATTR_DEBUG_CORE_LOGGER, ACTRLaunchConstants.DEFAULT_CORE_LOGGER)); vmArg.append(" -Dlog4j.configuration="); try { URI uri = logFile.getRawLocationURI(); vmArg.append(uri.toURL()).append(" ").append( workingCopy.getAttribute(IJavaLaunchConfigurationConstants.ATTR_VM_ARGUMENTS, "")); workingCopy.setAttribute(IJavaLaunchConfigurationConstants.ATTR_VM_ARGUMENTS, vmArg.toString()); } catch (Exception e) { CorePlugin.debug("failed to transform url " + logFile, e); logging = false; } } else logging = false; } if (!logging) workingCopy.setAttribute(IJavaLaunchConfigurationConstants.ATTR_VM_ARGUMENTS, "-Dorg.apache.commons.logging.log=org.apache.commons.logging.impl.SimpleLog " + workingCopy.getAttribute(IJavaLaunchConfigurationConstants.ATTR_VM_ARGUMENTS, "")); if (LOGGER.isDebugEnabled()) LOGGER.debug("Applied persistent attributes " + workingCopy); } /** * set up the information that is set strictly for the immediate launch. this * includes the working directory, environment file, program args * * @param workingCopy * @param mode * @param environmentFile */ static public void setupTemporaryAttributes(ILaunchConfigurationWorkingCopy workingCopy, String mode, IResource environmentFile) throws CoreException { StringBuilder arguments = new StringBuilder(); /* * make sure no splash screen is shown */ arguments.append("-name jACTR -nosplash "); /** * here's a mac specific bit of code * https://bugs.eclipse.org/bugs/show_bug.cgi?id=133072. The deal is that * eclipse (SWT) needs -ws carbon to run correctly. However if this is * provided, Swing/AWT calls will result in deadlock. The PDE tools * automatically add the -ws option, unless * IPDEUIConstants.APPEND_ARGS_EXPLICITLY is true (i.e. the program added it * already). So, if this is the mac, we explicitly add the program args, * excluding -ws. <br> * <br> * This works fine since we are launching within eclipse. If we were to * build a standalone app, on the mac, we'd need to add * --launcher.secondThread to the command line so to achieve a similar * effect. */ if (TargetPlatform.getWS().equals("carbon") || TargetPlatform.getWS().equals("cocoa")) { workingCopy.setAttribute(IPDEConstants.APPEND_ARGS_EXPLICITLY, true); // arguments.append("--launcher.secondThread "); arguments.append("-os ").append(TargetPlatform.getOS()).append(" "); arguments.append("-arch ").append(TargetPlatform.getOSArch()).append(" "); } if (workingCopy.getType().getIdentifier().equals("org.jactr.eclipse.runtime.launching.cr")) arguments.append(ACTRLaunchConstants.DEFAULT_CR_RUN_ARG); else if (workingCopy.getAttribute(ACTRLaunchConstants.ATTR_ITERATIONS, 0) != 0) arguments.append(ACTRLaunchConstants.ITERATIVE_APPLICATION_ARG); else if (ILaunchManager.DEBUG_MODE.equals(mode)) arguments.append(ACTRLaunchConstants.DEFAULT_APPLICATION_DEBUG_ARG); else arguments.append(ACTRLaunchConstants.DEFAULT_APPLICATION_RUN_ARG); arguments.append(" "); try { URI uri = environmentFile.getRawLocationURI(); arguments.append(uri.toURL()).append(" ") .append(workingCopy.getAttribute(IJavaLaunchConfigurationConstants.ATTR_PROGRAM_ARGUMENTS, "")); workingCopy.setAttribute(IJavaLaunchConfigurationConstants.ATTR_PROGRAM_ARGUMENTS, arguments.toString()); } catch (Exception e) { throw new CoreException(new Status(IStatus.ERROR, RuntimePlugin.PLUGIN_ID, "Could not get a valid url from " + environmentFile, e)); } /* * working directory - where the JVM is run from */ workingCopy.setAttribute(IJavaLaunchConfigurationConstants.ATTR_WORKING_DIRECTORY, environmentFile.getParent().getLocation().toOSString()); /* * now for the fun.. we need to get the plugin dependencies. first we get * the dependencies for the application.. we do this temporarily because.. * well, things change. */ Set<String> workspace = new TreeSet<String>(); Set<String> target = new TreeSet<String>(); computeBundleDependencies(workingCopy, workspace, target); StringBuilder workspaceBundles = new StringBuilder(); StringBuilder targetBundles = new StringBuilder(); for (String bundle : workspace) workspaceBundles.append(bundle).append(","); for (String bundle : target) targetBundles.append(bundle).append(","); if (workspaceBundles.length() > 0) workspaceBundles.delete(workspaceBundles.length() - 1, workspaceBundles.length()); if (targetBundles.length() > 0) targetBundles.delete(targetBundles.length() - 1, targetBundles.length()); workingCopy.setAttribute(org.eclipse.pde.launching.IPDELauncherConstants.SELECTED_WORKSPACE_PLUGINS, workspaceBundles.toString()); workingCopy.setAttribute(org.eclipse.pde.launching.IPDELauncherConstants.SELECTED_TARGET_PLUGINS, targetBundles.toString()); if (LOGGER.isDebugEnabled()) LOGGER.debug("Applied temporary attributes " + workingCopy); } /** * snag all the sensors that are defined in this configuration * * @param configuration * @return * @throws CoreException */ static public Collection<SensorDescriptor> getRequiredSensors(ILaunchConfiguration configuration) throws CoreException { IProject project = getProject(configuration); ArrayList<SensorDescriptor> descriptors = new ArrayList<SensorDescriptor>(); Collection<SensorDescriptor> installed = SensorRegistry.getRegistry().getDescriptors(project, true); String sensors = configuration.getAttribute(ACTRLaunchConstants.ATTR_COMMON_REALITY_SENSORS, ""); for (String sensor : sensors.split(",")) for (SensorDescriptor desc : installed) if (desc.getClassName().equals(sensor)) descriptors.add(desc); return descriptors; } static public Collection<IterativeListenerDescriptor> getRequiredListeners(ILaunchConfiguration configuration) throws CoreException { IProject project = getProject(configuration); ArrayList<IterativeListenerDescriptor> descriptors = new ArrayList<IterativeListenerDescriptor>(); Collection<IterativeListenerDescriptor> installed = IterativeListenerRegistry.getRegistry() .getDescriptors(project, true); String sensors = configuration.getAttribute(ACTRLaunchConstants.ATTR_ITERATIVE_LISTENERS, ""); for (String listener : sensors.split(",")) for (IterativeListenerDescriptor desc : installed) if (desc.getClassName().equals(listener)) descriptors.add(desc); if (LOGGER.isDebugEnabled()) { LOGGER.debug("Launch configuration for " + project.getName() + " : " + configuration.getAttributes()); LOGGER.debug("Required sensors : " + sensors); LOGGER.debug("Returning : " + descriptors); } return descriptors; } /** * return all the instruments that are required in this configuration * * @param configuration * @return * @throws CoreException */ static public Collection<InstrumentDescriptor> getRequiredInstruments(ILaunchConfiguration configuration) throws CoreException { IProject project = getProject(configuration); ArrayList<InstrumentDescriptor> descriptors = new ArrayList<InstrumentDescriptor>(); Collection<InstrumentDescriptor> installed = InstrumentRegistry.getRegistry().getDescriptors(project, true); String instruments = configuration.getAttribute(ACTRLaunchConstants.ATTR_INSTRUMENTS, ""); for (String instrument : instruments.split(",")) for (InstrumentDescriptor desc : installed) if (desc.getClassName().equals(instrument)) descriptors.add(desc); return descriptors; } static public Collection<RuntimeTracerDescriptor> getRequiredTracers(ILaunchConfiguration configuration) throws CoreException { IProject project = getProject(configuration); ArrayList<RuntimeTracerDescriptor> descriptors = new ArrayList<RuntimeTracerDescriptor>(); Collection<RuntimeTracerDescriptor> installed = RuntimeTracerRegistry.getRegistry().getDescriptors(project, true); String instruments = configuration.getAttribute(ACTRLaunchConstants.ATTR_TRACERS, ""); for (String instrument : instruments.split(",")) for (RuntimeTracerDescriptor desc : installed) if (desc.getClassName().equals(instrument)) descriptors.add(desc); return descriptors; } @SuppressWarnings("unchecked") static public void computeBundleDependencies(ILaunchConfigurationWorkingCopy configuration, Set<String> workspaceBundles, Set<String> targetBundles) throws CoreException { IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); String projectName = configuration.getAttribute(IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, ""); IProject sourceProject = null; if (projectName.length() != 0) sourceProject = root.getProject(projectName); // IProject project = root.getProject(configuration.getAttribute( // LaunchConfigurationConstants.ACTR_PROJECT, "")); Collection<String> appDependencies = null; if (configuration.getAttribute(ACTRLaunchConstants.ATTR_ITERATIONS, 0) == 0) appDependencies = BundleUtilities.getDependencies(ACTRLaunchConstants.DEFAULT_APPLICATION_BUNDLE); else appDependencies = BundleUtilities.getDependencies(ACTRLaunchConstants.ITERATIVE_APPLICATION_BUNDLE); Collection<String> currentDependencies = Collections.EMPTY_SET; if (sourceProject != null && sourceProject.exists()) currentDependencies = BundleUtilities.getDependencies(sourceProject); Collection<String> uniqueDependencies = new TreeSet<String>(); for (String bundleId : appDependencies) uniqueDependencies.add(bundleId); for (String bundleId : currentDependencies) uniqueDependencies.add(bundleId); /* * now for the sensors */ for (SensorDescriptor sensor : getRequiredSensors(configuration)) for (String bundleId : BundleUtilities.getDependencies(sensor.getContributor())) uniqueDependencies.add(bundleId); /* * and instruments */ for (InstrumentDescriptor instrument : getRequiredInstruments(configuration)) for (String bundleId : BundleUtilities.getDependencies(instrument.getContributor())) uniqueDependencies.add(bundleId); /* * now we determine where they are coming from, we preference workspace * plugins over installed ones so that you can self-host */ for (IPluginModelBase modelBase : PluginRegistry.getWorkspaceModels()) { String pluginId = modelBase.getPluginBase(true).getId(); // not entirely clear how to get the project from the model.. // this matters because if the project is closed, we shouldn't use it // IProject requiredProject = root.getProject(); // if (requiredProject.isAccessible()) if (pluginId != null && uniqueDependencies.remove(pluginId)) workspaceBundles.add(pluginId); } /* * and the rest we assume are targets */ targetBundles.addAll(uniqueDependencies); if (LOGGER.isDebugEnabled()) { LOGGER.debug("workspace : " + workspaceBundles.toString()); LOGGER.debug("target : " + targetBundles.toString()); } } }