/************************************************************************************* * Copyright (c) 2008-2014 Red Hat, Inc. and others. * 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: * JBoss by Red Hat - Initial implementation. ************************************************************************************/ package org.jboss.tools.arquillian.core; import java.io.IOException; import java.util.HashMap; import java.util.Map; import javax.xml.parsers.SAXParserFactory; import org.eclipse.core.internal.runtime.InternalPlatform; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResourceChangeEvent; import org.eclipse.core.resources.IResourceChangeListener; import org.eclipse.core.resources.IResourceDelta; import org.eclipse.core.resources.IResourceDeltaVisitor; import org.eclipse.core.resources.IWorkspaceRoot; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.resources.WorkspaceJob; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.ILog; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.preferences.IEclipsePreferences; import org.eclipse.core.runtime.preferences.InstanceScope; import org.eclipse.debug.core.DebugPlugin; import org.eclipse.debug.core.ILaunchConfiguration; import org.eclipse.debug.core.ILaunchConfigurationListener; import org.eclipse.jdt.core.ElementChangedEvent; import org.eclipse.jdt.core.IElementChangedListener; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.IJavaElementDelta; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.preferences.ScopedPreferenceStore; import org.jboss.tools.arquillian.core.internal.ArquillianConstants; import org.jboss.tools.arquillian.core.internal.archives.ArchiveContainer; import org.jboss.tools.arquillian.core.internal.classpath.ArquillianClassLoader; import org.jboss.tools.arquillian.core.internal.dependencies.DependencyCache; import org.jboss.tools.arquillian.core.internal.launcher.ArquillianLaunchConfigurationDelegate; import org.jboss.tools.arquillian.core.internal.natures.ArquillianNature; import org.jboss.tools.arquillian.core.internal.util.ArquillianUtility; import org.jboss.tools.common.jdt.debug.RemoteDebugActivator; import org.osgi.framework.Bundle; import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; import org.osgi.util.tracker.ServiceTracker; public class ArquillianCoreActivator implements BundleActivator { // The plug-in ID public static final String PLUGIN_ID = "org.jboss.tools.arquillian.core"; //$NON-NLS-1$ private static Map<String, ArquillianClassLoader> loaders = new HashMap<String, ArquillianClassLoader>(); // The shared instance private static ArquillianCoreActivator plugin; private static BundleContext context; private ServiceTracker parserTracker = null; private ScopedPreferenceStore preferenceStore; private IElementChangedListener elementChangedListener = new IElementChangedListener() { @Override public void elementChanged(ElementChangedEvent event) { IJavaElementDelta delta = event.getDelta(); processDelta(delta); } private boolean processDelta(IJavaElementDelta delta) { int kind= delta.getKind(); int flags= delta.getFlags(); IJavaElement element= delta.getElement(); int elementType= element.getElementType(); if (isClassPathChange(delta)) { cleanup(element.getJavaProject()); return true; } if (elementType == IJavaElement.JAVA_PROJECT) { if ((flags & (IJavaElementDelta.F_CLOSED | IJavaElementDelta.F_OPENED)) != 0) { cleanup(element.getJavaProject()); return true; } if ((flags & IJavaElementDelta.F_RESOLVED_CLASSPATH_CHANGED) != 0) { cleanup(element.getJavaProject()); return true; } if (kind == IJavaElementDelta.ADDED) { cleanup(element.getJavaProject()); return true; } } IJavaElementDelta[] affectedChildren= delta.getAffectedChildren(); for (IJavaElementDelta d:affectedChildren) { if (processDelta(d)) { return true; } } return false; } public void cleanup(IJavaProject javaProject) { removeProjectLoader(javaProject.getProject()); ArchiveContainer.remove(javaProject.getProject()); DependencyCache.removeDependencies(javaProject.getProject()); } private boolean isClassPathChange(IJavaElementDelta delta) { if (delta.getElement().getElementType() != IJavaElement.PACKAGE_FRAGMENT_ROOT) return false; int flags= delta.getFlags(); return (delta.getKind() == IJavaElementDelta.CHANGED && ((flags & IJavaElementDelta.F_ADDED_TO_CLASSPATH) != 0) || ((flags & IJavaElementDelta.F_REMOVED_FROM_CLASSPATH) != 0) || ((flags & IJavaElementDelta.F_REORDER) != 0)); } }; private IResourceChangeListener resourceChangeListener = new IResourceChangeListener() { @Override public void resourceChanged(IResourceChangeEvent event) { if (event.getType() != IResourceChangeEvent.POST_CHANGE) { return; } IResourceDelta delta = event.getDelta(); if (delta == null) { return; } try { delta.accept(new IResourceDeltaVisitor() { @Override public boolean visit(IResourceDelta delta) throws CoreException { IResource resource = delta.getResource(); if (resource instanceof IWorkspaceRoot) { return true; } if (resource instanceof IProject) { if ( (delta.getFlags() & IResourceDelta.OPEN) != 0) { IProject project = (IProject) resource; if (project.isOpen() && project.hasNature(ArquillianNature.ARQUILLIAN_NATURE_ID)) { fixProject(project); } } return false; } return false; } }); } catch (CoreException e) { ArquillianCoreActivator.log(e); } } }; private ILaunchConfigurationListener launchConfigurationListener = new ILaunchConfigurationListener() { @Override public void launchConfigurationRemoved(ILaunchConfiguration configuration) {} @Override public void launchConfigurationChanged(ILaunchConfiguration configuration) {} @Override public void launchConfigurationAdded(ILaunchConfiguration configuration) { if (configuration.getName() != null && configuration.getName().startsWith(RemoteDebugActivator.JBOSS_TEMP_JAVA_APPLICATION)) { return; } IPreferenceStore prefs = ArquillianCoreActivator.getDefault().getPreferenceStore(); boolean enabled = prefs.getBoolean(ArquillianConstants.ENABLE_DEFAULT_VM_ARGUMENTS); if (!enabled) { return; } try { String typeId = configuration.getType().getIdentifier(); boolean add = prefs.getBoolean(ArquillianConstants.ADD_DEFAULT_VM_ARGUMENTS_TO_JUNIT_TESTNG) && (ArquillianConstants.JUNIT_LAUNCHCONFIG_TYPE_ID.equals(typeId) || ArquillianConstants.TESTNG_LAUNCHCONFIG_TYPE_ID.equals(typeId) ); if (add || ArquillianLaunchConfigurationDelegate.ID.equals(typeId)) { String arguments = prefs.getString(ArquillianConstants.DEFAULT_VM_ARGUMENTS); if (arguments != null && !arguments.isEmpty()) { arguments = arguments.trim(); ArquillianUtility.addArguments(configuration, arguments, true); } } } catch (CoreException e) { log(e); } } }; static BundleContext getContext() { return context; } /* * (non-Javadoc) * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext) */ public void start(BundleContext bundleContext) throws Exception { plugin = this; ArquillianCoreActivator.context = bundleContext; JavaCore.addElementChangedListener(elementChangedListener); DebugPlugin.getDefault().getLaunchManager().addLaunchConfigurationListener(launchConfigurationListener); ResourcesPlugin.getWorkspace().addResourceChangeListener(resourceChangeListener, IResourceChangeEvent.POST_CHANGE); IEclipsePreferences prefs = InstanceScope.INSTANCE.getNode(ArquillianCoreActivator.PLUGIN_ID); boolean firstStart = prefs.getBoolean(ArquillianConstants.FIRST_START, true); if (firstStart) { fixProjects(); } } private void fixProjects() { WorkspaceJob job = new WorkspaceJob("Fixing projects") { @Override public IStatus runInWorkspace(IProgressMonitor monitor) throws CoreException { if (!PlatformUI.isWorkbenchRunning()) { return Status.OK_STATUS; } try { IProject[] projects = ResourcesPlugin.getWorkspace().getRoot() .getProjects(); for (IProject project : projects) { if (monitor.isCanceled()) { return Status.CANCEL_STATUS; } if (project.isAccessible() && project.isOpen() && project.hasNature(ArquillianNature.ARQUILLIAN_NATURE_ID)) { ArquillianUtility.addBuilder(project); } } IEclipsePreferences prefs = InstanceScope.INSTANCE.getNode(ArquillianCoreActivator.PLUGIN_ID); prefs.putBoolean(ArquillianConstants.FIRST_START, false); prefs.flush(); } catch (Exception e) { ArquillianCoreActivator.log(e); } return Status.OK_STATUS; } }; job.schedule(); } private void fixProject(final IProject project) { if (project == null || !project.isAccessible()) { return; } WorkspaceJob job = new WorkspaceJob("Fixing the '" + project.getName() + "' project") { @Override public IStatus runInWorkspace(IProgressMonitor monitor) throws CoreException { if (!PlatformUI.isWorkbenchRunning()) { return Status.OK_STATUS; } if (project.isAccessible() && project.hasNature(ArquillianNature.ARQUILLIAN_NATURE_ID)) { ArquillianUtility.addBuilder(project); } return Status.OK_STATUS; } }; job.schedule(); } /* * (non-Javadoc) * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext) */ public void stop(BundleContext bundleContext) throws Exception { plugin = null; ArquillianCoreActivator.context = null; JavaCore.removeElementChangedListener(elementChangedListener); ResourcesPlugin.getWorkspace().removeResourceChangeListener(resourceChangeListener); DebugPlugin.getDefault().getLaunchManager().removeLaunchConfigurationListener(launchConfigurationListener); if (preferenceStore != null) { preferenceStore.save(); } } /** * Returns the shared instance * * @return the shared instance */ public static ArquillianCoreActivator getDefault() { return plugin; } public static void log(Exception e, String message) { IStatus status = new Status(IStatus.ERROR, PLUGIN_ID, message, e); plugin.getLog().log(status); } public static void log(Throwable e) { IStatus status = new Status(IStatus.ERROR, PLUGIN_ID, e .getLocalizedMessage(), e); plugin.getLog().log(status); } public static void logError(String message) { IStatus status = new Status(IStatus.ERROR, PLUGIN_ID, message); plugin.getLog().log(status); } public static void logWarning(String message) { IStatus status = new Status(IStatus.WARNING, PLUGIN_ID, message); plugin.getLog().log(status); } public ILog getLog() { Bundle bundle = context.getBundle(); return InternalPlatform.getDefault().getLog(bundle); } public ClassLoader getClassLoader(IJavaProject javaProject) { synchronized (this) { if (javaProject == null) { return null; } String projectName = javaProject.getProject().getName(); ArquillianClassLoader loader = loaders.get(projectName); if (loader == null) { loader = new ArquillianClassLoader(javaProject); loaders.put(projectName, loader); } return loader; } } public void removeProjectLoader(IProject project) { synchronized (this) { String projectName = project.getName(); ArquillianClassLoader loader = loaders.get(projectName); if (loader != null) { try { loader.close(); } catch (IOException e) { log(e); } loaders.remove(projectName); } } } public IPreferenceStore getPreferenceStore() { if (preferenceStore == null) { preferenceStore = new ScopedPreferenceStore(InstanceScope.INSTANCE, PLUGIN_ID); } return preferenceStore; } public IPath getStateLocation() { Bundle bundle = Platform.getBundle(PLUGIN_ID); return InternalPlatform.getDefault().getStateLocation(bundle, true); } /* * Return the registered SAX parser factory or null if one * does not exist. */ public SAXParserFactory getFactory() { if (parserTracker == null) { parserTracker = new ServiceTracker(getContext(), SAXParserFactory.class.getName(), null); parserTracker.open(); } SAXParserFactory theFactory = (SAXParserFactory) parserTracker.getService(); if (theFactory != null) theFactory.setNamespaceAware(true); return theFactory; } }