/******************************************************************************* * Copyright (c) 2012-2015 Codenvy, S.A. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Codenvy, S.A. - initial API and implementation *******************************************************************************/ package org.eclipse.che.jdt.core.launching.environments; import org.eclipse.che.jdt.core.launching.IVMInstallType; import org.eclipse.che.jdt.core.launching.LibraryLocation; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; import org.eclipse.jdt.core.IAccessRule; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.JavaCore; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Properties; /** * A contributed execution environment. * * @since 3.2 */ public class ExecutionEnvironment implements IExecutionEnvironment { // /** // * Add a VM changed listener to clear cached values when a VM changes or is removed // */ // private IVMInstallChangedListener fListener = new IVMInstallChangedListener() { // // /* (non-Javadoc) // * @see org.eclipse.jdt.launching.IVMInstallChangedListener#defaultVMInstallChanged(org.eclipse.jdt.launching.IVMInstall, org // * .eclipse.jdt.launching.IVMInstall) // */ // public void defaultVMInstallChanged(IVMInstall previous, IVMInstall current) { // } // // /* (non-Javadoc) // * @see org.eclipse.jdt.launching.IVMInstallChangedListener#vmAdded(org.eclipse.jdt.launching.IVMInstall) // */ // public void vmAdded(IVMInstall newVm) { // } // // /* (non-Javadoc) // * @see org.eclipse.jdt.launching.IVMInstallChangedListener#vmChanged(org.eclipse.jdt.launching.PropertyChangeEvent) // */ // public void vmChanged(PropertyChangeEvent event) { // if (event.getSource() != null) { // fParticipantMap.remove(event.getSource()); // fRuleCache.remove(event.getSource()); // } // } // // /* (non-Javadoc) // * @see org.eclipse.jdt.launching.IVMInstallChangedListener#vmRemoved(org.eclipse.jdt.launching.IVMInstall) // */ // public void vmRemoved(IVMInstall removedVm) { // fParticipantMap.remove(removedVm); // fRuleCache.remove(removedVm); // } // }; // // // /** // * The backing <code>IConfigurationElement</code> // */ // private IConfigurationElement fElement; /** * Environment specific rule participant or <code>null</code> if none. */ private IAccessRuleParticipant fRuleParticipant; /** * OSGi profile properties or <code>null</code> if none. */ private Properties fProfileProperties; /** * Whether profile properties have been initialized */ private boolean fPropertiesInitialized; // /** // * Set of compatible vm's - just the strictly compatible ones // */ // private Set<IVMInstall> fStrictlyCompatible = new HashSet<IVMInstall>(); // // /** // * All compatible vm's // */ // private List<IVMInstall> fCompatibleVMs = new ArrayList<IVMInstall>(); /** * default VM install or <code>null</code> if none */ private IVMInstallType fDefault = null; /** * Cache of access rule participants to consider for this environment. */ private IAccessRuleParticipant[] fParticipants = null; /** * Map of {IVMInstall -> Map of {participant -> IAccessRule[][]}}. * Caches access rules returned by each participant for a given VM. * @since 3.3 */ private Map<IVMInstallType, Map<IAccessRuleParticipant, IAccessRule[][]>> fParticipantMap = new HashMap<IVMInstallType, Map<IAccessRuleParticipant, IAccessRule[][]>>(); /** * Cache of VM -> IAccessRule[][] based on the current state of the participant * map. These are the union of the latest rules generated by the participants * for a specific VM. * @since 3.3 */ private Map<IVMInstallType, IAccessRule[][]> fRuleCache = new HashMap<IVMInstallType, IAccessRule[][]>(); /** * Wild card pattern matching all files */ private static final IPath ALL_PATTERN = new Path("**/*"); //$NON-NLS-1$ /** * Prefix of compiler settings in properties file */ private static final String COMPILER_SETTING_PREFIX = JavaCore.PLUGIN_ID + ".compiler"; //$NON-NLS-1$ private String id = "JavaSE-1.8"; /** * Constructor * @param element the backing {@link org.eclipse.core.runtime.IConfigurationElement} */ public ExecutionEnvironment() { fPropertiesInitialized = false; // String attribute = fElement.getAttribute(EnvironmentsManager.RULE_PARTICIPANT_ELEMENT); // if (attribute != null) { fRuleParticipant = new DefaultAccessRuleParticipant(); // } // JavaRuntime.addVMInstallChangedListener(fListener); } /** * Initializes the <code>EnvironmentsManager</code> */ private void init() { // EnvironmentsManager.getDefault().initializeCompatibilities(); } /* (non-Javadoc) * @see org.eclipse.jdt.launching.environments.IExecutionEnvironment#getId() */ public String getId() { // return fElement.getAttribute("id"); //$NON-NLS-1$ // throw new UnsupportedOperationException(); return id; } /* (non-Javadoc) * @see org.eclipse.jdt.launching.environments.IExecutionEnvironment#getDescription() */ public String getDescription() { // return fElement.getAttribute("description"); //$NON-NLS-1$ throw new UnsupportedOperationException(); } // /* (non-Javadoc) // * @see org.eclipse.jdt.launching.environments.IExecutionEnvironment#getCompatibleVMs() // */ // public IVMInstallType[] getCompatibleVMs() { // init(); // return fCompatibleVMs.toArray(new IVMInstall[fCompatibleVMs.size()]); // } // // /* (non-Javadoc) // * @see org.eclipse.jdt.launching.environments.IExecutionEnvironment#isStrictlyCompatible(org.eclipse.jdt.launching.IVMInstall) // */ // public boolean isStrictlyCompatible(IVMInstall vm) { // init(); // return fStrictlyCompatible.contains(vm); // } // // /* (non-Javadoc) // * @see org.eclipse.jdt.launching.environments.IExecutionEnvironment#getDefaultVM() // */ // public IVMInstall getDefaultVM() { // init(); // return fDefault; // } // // /* (non-Javadoc) // * @see org.eclipse.jdt.launching.environments.IExecutionEnvironment#setDefaultVM(org.eclipse.jdt.launching.IVMInstall) // */ // public void setDefaultVM(IVMInstall vm) { // init(); // if (vm != null && !fCompatibleVMs.contains(vm)) { // throw new IllegalArgumentException(NLS.bind(EnvironmentMessages.EnvironmentsManager_0, new String[]{getId()})); // } // if (vm != null && vm.equals(fDefault)) { // return; // } // fDefault = vm; // EnvironmentsManager.getDefault().updateDefaultVMs(); // // update classpath containers // rebindClasspathContainers(); // } // /** // * Updates Java projects referencing this environment, if any. // */ // private void rebindClasspathContainers() { // IJavaModel model = JavaCore.create(ResourcesPlugin.getWorkspace().getRoot()); // if (model != null) { // try { // List<IJavaProject> updates = new ArrayList<IJavaProject>(); // IJavaProject[] javaProjects = model.getJavaProjects(); // IPath path = JavaRuntime.newJREContainerPath(this); // for (int i = 0; i < javaProjects.length; i++) { // IJavaProject project = javaProjects[i]; // IClasspathEntry[] rawClasspath = project.getRawClasspath(); // for (int j = 0; j < rawClasspath.length; j++) { // IClasspathEntry entry = rawClasspath[j]; // if (entry.getEntryKind() == IClasspathEntry.CPE_CONTAINER) { // if (entry.getPath().equals(path)) { // updates.add(project); // } // } // } // } // if (!updates.isEmpty()) { // JavaCore.setClasspathContainer(path, // updates.toArray(new IJavaProject[updates.size()]), // new IClasspathContainer[updates.size()], // new NullProgressMonitor()); // } // } catch (JavaModelException e) { // LaunchingPlugin.log(e); // } // } // } // /** // * Adds the specified VM to the listing of compatible VMs, also // * adds the VM to the listing of strictly compatible ones based on // * the strictlyCompatible flag // * @param vm the VM to add to the environment // * @param strictlyCompatible if it is strictly compatible // */ // void add(IVMInstall vm, boolean strictlyCompatible) { // if (fCompatibleVMs.contains(vm)) { // return; // } // fCompatibleVMs.add(vm); // if (strictlyCompatible) { // fStrictlyCompatible.add(vm); // } // } // // /** // * Removes the specified VM from the listings of VMs // * @param vm the VM to remove // */ // void remove(IVMInstall vm) { // fCompatibleVMs.remove(vm); // fStrictlyCompatible.remove(vm); // } /** * Sets the default VM to be the one specified * @param vm the VM to set as the default */ void initDefaultVM(IVMInstallType vm) { fDefault = vm; } /* (non-Javadoc) * @see org.eclipse.jdt.launching.environments.IExecutionEnvironment#getAccessRules(org.eclipse.jdt.launching.IVMInstall, org.eclipse.jdt.launching.LibraryLocation[], org.eclipse.jdt.core.IJavaProject) */ public IAccessRule[][] getAccessRules(IVMInstallType vm, LibraryLocation[] libraries, IJavaProject project) { IAccessRuleParticipant[] participants = getParticipants(); Map<IAccessRuleParticipant, IAccessRule[][]> rulesByParticipant = collectRulesByParticipant(participants, vm, libraries, project); synchronized (this) { Map<IAccessRuleParticipant, IAccessRule[][]> cachedRules = fParticipantMap.get(vm); if (cachedRules == null || !cachedRules.equals(rulesByParticipant)) { ArrayList<List<IAccessRule>> libLists = new ArrayList<List<IAccessRule>>(); // array of lists of access rules for (int i = 0; i < libraries.length; i++) { libLists.add(new ArrayList<IAccessRule>()); } for (int i = 0; i < participants.length; i++) { IAccessRuleParticipant participant = participants[i]; addRules(rulesByParticipant.get(participant), libLists); } IAccessRule[][] allRules = new IAccessRule[libraries.length][]; for (int i = 0; i < libLists.size(); i++) { List<IAccessRule> l = libLists.get(i); allRules[i] = l.toArray(new IAccessRule[l.size()]); } fParticipantMap.put(vm, rulesByParticipant); fRuleCache.put(vm, allRules); return allRules; } return fRuleCache.get(vm); } } /** * Returns all access rule participants to consider for this environment. * Includes any participant contributed with this environment and all other * stand alone participants. * * @return access rule participants to consider for this environment */ private synchronized IAccessRuleParticipant[] getParticipants() { if (fParticipants == null) { // check participants first IAccessRuleParticipant[] participants = null;// EnvironmentsManager.getDefault().getAccessRuleParticipants(); if (fRuleParticipant != null) { // ensure environment specific provider is last and not duplicated LinkedHashSet<IAccessRuleParticipant> set = new LinkedHashSet<IAccessRuleParticipant>(); // for (int i = 0; i < participants.length; i++) { // set.add(participants[i]); // } // remove, add to make last set.remove(fRuleParticipant); set.add(fRuleParticipant); participants = set.toArray(new IAccessRuleParticipant[set.size()]); } fParticipants = participants; } return fParticipants; } /** * Returns a map of participant to the access rules for that participant for the given * VM, libraries, and project. * * @param participants access rule participants * @param vm the VM * @param libraries the {@link LibraryLocation}s * @param project the {@link org.eclipse.jdt.core.IJavaProject} context * @return the mapping of {@link IAccessRuleParticipant} to {@link org.eclipse.jdt.core.IAccessRule}s */ private Map<IAccessRuleParticipant, IAccessRule[][]> collectRulesByParticipant(IAccessRuleParticipant[] participants, IVMInstallType vm, LibraryLocation[] libraries, IJavaProject project) { Map<IAccessRuleParticipant, IAccessRule[][]> map = new HashMap<IAccessRuleParticipant, IAccessRule[][]>(); for (int i = 0; i < participants.length; i++) { // TODO: use safe runnable map.put(participants[i], participants[i].getAccessRules(this, vm, libraries, project)); } return map; } /** * Adds the access rules to each list in the given collection. If the last rule in a * given collection is the wild card pattern then no more rules are added to that collection. * * @param accessRules the list of {@link org.eclipse.jdt.core.IAccessRule}s * @param collect the array of lists to collect the {@link org.eclipse.jdt.core.IAccessRule}s in */ private void addRules(IAccessRule[][] accessRules, ArrayList<List<IAccessRule>> collect) { for (int i = 0; i < accessRules.length; i++) { IAccessRule[] libRules = accessRules[i]; List<IAccessRule> list = collect.get(i); // if the last rule is a **/* pattern, don't add any more rules, as they will have no effect if (!list.isEmpty()) { IAccessRule lastRule = list.get(list.size() - 1); if(lastRule.getPattern().equals(ALL_PATTERN)) { continue; } } for (int j = 0; j < libRules.length; j++) { list.add(libRules[j]); } } } /* (non-Javadoc) * @see org.eclipse.jdt.launching.environments.IExecutionEnvironment#getProfileProperties() */ public Properties getProfileProperties() { if (!fPropertiesInitialized) { fPropertiesInitialized = true; // String path = fElement.getAttribute("profileProperties"); //$NON-NLS-1$ // Bundle bundle = null; // if (path == null) { // // attempt default profiles known to OSGi // bundle = Platform.getBundle("org.eclipse.osgi"); //$NON-NLS-1$ // path = getId().replace('/', '_') + ".profile"; //$NON-NLS-1$ // } else { // // read provided file // bundle = Platform.getBundle(fElement.getContributor().getName()); // } // if (bundle != null && path != null) { fProfileProperties = getJavaProfileProperties(); // } } return fProfileProperties; } /** * Returns properties file contained in the specified bundle at the given * bundle relative path, or <code>null</code> if none. * * @param bundle bundle to locate file in * @param path bundle relative path to properties file * @return properties or <code>null</code> if none */ private Properties getJavaProfileProperties() { URL profileURL = getClass().getResource("/" + id + ".profile"); //bundle.getEntry(path); if (profileURL != null) { InputStream is = null; try { // profileURL = FileLocator.resolve(profileURL); is = profileURL.openStream(); if (is != null) { Properties profile = new Properties(); profile.load(is); return profile; } } catch (IOException e) { } finally { try { if (is != null) { is.close(); } } catch (IOException e) { } } } return null; } /* (non-Javadoc) * @see org.eclipse.jdt.launching.environments.IExecutionEnvironment#getSubEnvironments() */ public IExecutionEnvironment[] getSubEnvironments() { // Properties properties = getProfileProperties(); // Set<IExecutionEnvironment> subenv = new LinkedHashSet<IExecutionEnvironment>(); // if (properties != null) { // @SuppressWarnings("deprecation") // String subsets = properties.getProperty(Constants.FRAMEWORK_EXECUTIONENVIRONMENT); // if (subsets != null) { // String[] ids = subsets.split(","); //$NON-NLS-1$ // for (int i = 0; i < ids.length; i++) { // IExecutionEnvironment sub = JavaRuntime.getExecutionEnvironmentsManager().getEnvironment(ids[i].trim()); // if (sub != null && !sub.getId().equals(getId())) { // subenv.add(sub); // } // } // } // } // return subenv.toArray(new IExecutionEnvironment[subenv.size()]); throw new UnsupportedOperationException(); } /* (non-Javadoc) * @see org.eclipse.jdt.launching.environments.IExecutionEnvironment#getComplianceOptions() */ public Map<String, String> getComplianceOptions() { Properties properties = getProfileProperties(); if (properties != null) { Map<String, String> map = new HashMap<String, String>(); Iterator<?> iterator = properties.keySet().iterator(); while (iterator.hasNext()) { String key = (String) iterator.next(); if (key.startsWith(COMPILER_SETTING_PREFIX)) { map.put(key, properties.getProperty(key)); } } if (!map.isEmpty()) { return map; } } return null; } }