/******************************************************************************* * Copyright (c) 2003, 2011 IBM Corporation 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: * IBM Corporation - Initial API and implementation *******************************************************************************/ package org.eclipse.jst.server.core.internal; import java.util.ArrayList; import java.util.Hashtable; import java.util.Iterator; import java.util.List; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.*; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.debug.core.ILaunch; import org.eclipse.jdt.core.IClasspathContainer; import org.eclipse.jdt.core.IClasspathEntry; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.launching.IVMInstall; import org.eclipse.jdt.launching.VMRunnerConfiguration; import org.eclipse.osgi.service.debug.DebugOptions; import org.eclipse.osgi.service.debug.DebugOptionsListener; import org.eclipse.osgi.util.NLS; import org.eclipse.wst.server.core.IRuntime; import org.eclipse.wst.server.core.IRuntimeLifecycleListener; import org.eclipse.wst.server.core.IRuntimeType; import org.eclipse.wst.server.core.ServerCore; import org.eclipse.wst.server.core.ServerUtil; import org.osgi.framework.BundleContext; /** * The main server tooling plugin class. */ public class JavaServerPlugin extends Plugin { /** * Java server plugin id */ public static final String PLUGIN_ID = "org.eclipse.jst.server.core"; // singleton instance of this class private static JavaServerPlugin singleton; // cached copy of all runtime classpath providers private static List<RuntimeClasspathProviderWrapper> runtimeClasspathProviders; // cached copy of all server profilers private static List<ServerProfiler> serverProfilers; // runtime listener private static IRuntimeLifecycleListener runtimeListener; /** * Create the JavaServerPlugin. */ public JavaServerPlugin() { super(); singleton = this; } /** * Returns the singleton instance of this plugin. * * @return a singleton instance */ public static JavaServerPlugin getInstance() { return singleton; } /** * @see Plugin#start(org.osgi.framework.BundleContext) */ public void start(BundleContext context) throws Exception { super.start(context); runtimeListener = new IRuntimeLifecycleListener() { public void runtimeAdded(IRuntime runtime) { handleRuntimeChange(runtime, 0); } public void runtimeChanged(IRuntime runtime) { handleRuntimeChange(runtime, 1); } public void runtimeRemoved(IRuntime runtime) { handleRuntimeChange(runtime, 2); } }; ServerCore.addRuntimeLifecycleListener(runtimeListener); // register the debug options listener final Hashtable<String, String> props = new Hashtable<String, String>(4); props.put(DebugOptions.LISTENER_SYMBOLICNAME, JavaServerPlugin.PLUGIN_ID); context.registerService(DebugOptionsListener.class.getName(), new Trace(), props); } /** * @see Plugin#stop(org.osgi.framework.BundleContext) */ public void stop(BundleContext context2) throws Exception { ServerCore.removeRuntimeLifecycleListener(runtimeListener); super.stop(context2); } /** * Handle a runtime change by potentially updating the classpath container. * * @param runtime a runtime */ protected void handleRuntimeChange(final IRuntime runtime, final int act) { if (runtime == null) throw new IllegalArgumentException(); if (Trace.FINEST) { Trace.trace(Trace.STRING_FINEST, "Possible runtime change: " + runtime); } if (runtime.getRuntimeType() == null) return; final RuntimeClasspathProviderWrapper rcpw = findRuntimeClasspathProvider(runtime.getRuntimeType()); if (rcpw != null && (rcpw.hasRuntimeClasspathChanged(runtime) || act != 1)) { final IPath serverContainerPath = new Path(RuntimeClasspathContainer.SERVER_CONTAINER) .append(rcpw.getId()).append(runtime.getId()); class RebuildRuntimeReferencesJob extends Job { public RebuildRuntimeReferencesJob() { super(NLS.bind(Messages.updateClasspathContainers, runtime.getName())); } public boolean belongsTo(Object family) { return ServerUtil.SERVER_JOB_FAMILY.equals(family); } public IStatus run(IProgressMonitor monitor) { IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects(); if (projects != null) { for (IProject project : projects) { if (project.isAccessible()) { try { if (!project.isNatureEnabled(JavaCore.NATURE_ID)) continue; IJavaProject javaProject = JavaCore.create(project); boolean found = false; IClasspathEntry[] ce = javaProject.getRawClasspath(); for (IClasspathEntry cp : ce) { if (cp.getEntryKind() == IClasspathEntry.CPE_CONTAINER) { if (serverContainerPath.isPrefixOf(cp.getPath())) found = true; } } if (Trace.FINEST) { Trace.trace(Trace.STRING_FINEST, "Classpath change on: " + project + " " + found); } if (found) { IRuntime runtime2 = runtime; if (act == 2) runtime2 = null; RuntimeClasspathContainer container = new RuntimeClasspathContainer(project, serverContainerPath, rcpw, runtime2, runtime.getId()); JavaCore.setClasspathContainer(serverContainerPath, new IJavaProject[] { javaProject }, new IClasspathContainer[] {container}, null); } } catch (Exception e) { if (Trace.SEVERE) { Trace.trace(Trace.STRING_SEVERE, "Could not update classpath container", e); } } } } } return Status.OK_STATUS; } } RebuildRuntimeReferencesJob job = new RebuildRuntimeReferencesJob(); job.schedule(); } } /** * Convenience method for logging. * * @param status a status */ private static void log(IStatus status) { getInstance().getLog().log(status); } public static void logWarning(String msg) { log(new Status(IStatus.WARNING, PLUGIN_ID, IStatus.OK, msg, null)); } /** * Returns an array of all known runtime classpath provider instances. * <p> * A new array is returned on each call, so clients may store or modify the * result. * </p> * * @return a possibly-empty array of runtime classpath provider instances * {@link RuntimeClasspathProviderWrapper} */ public static RuntimeClasspathProviderWrapper[] getRuntimeClasspathProviders() { if (runtimeClasspathProviders == null) loadRuntimeClasspathProviders(); RuntimeClasspathProviderWrapper[] rth = new RuntimeClasspathProviderWrapper[runtimeClasspathProviders.size()]; runtimeClasspathProviders.toArray(rth); return rth; } /** * Returns the runtime classpath provider that supports the given runtime type, or <code>null</code> * if none. This convenience method searches the list of known runtime * classpath providers ({@link #getRuntimeClasspathProviders()}) for the one with * a matching runtime type. * The runtimeType may not be null. * * @param runtimeType a runtime type * @return the runtime classpath provider instance, or <code>null</code> if * there is no runtime classpath provider that supports the given id */ public static RuntimeClasspathProviderWrapper findRuntimeClasspathProvider(IRuntimeType runtimeType) { if (runtimeType == null) throw new IllegalArgumentException(); if (runtimeClasspathProviders == null) loadRuntimeClasspathProviders(); Iterator iterator = runtimeClasspathProviders.iterator(); while (iterator.hasNext()) { RuntimeClasspathProviderWrapper runtimeClasspathProvider = (RuntimeClasspathProviderWrapper) iterator.next(); if (runtimeClasspathProvider.supportsRuntimeType(runtimeType)) return runtimeClasspathProvider; } return null; } /** * Returns the runtime classpath provider that supports the given runtime type id, * or <code>null</code> if none. This convenience method searches the list of known * runtime classpath providers ({@link #getRuntimeClasspathProviders()}) for the one * with a matching runtime type id. The id may not be null. * * @param id a runtime type id * @return the runtime classpath provider instance, or <code>null</code> if * there is no runtime classpath provider that supports the given id */ public static RuntimeClasspathProviderWrapper findRuntimeClasspathProviderBySupport(String id) { if (id == null) throw new IllegalArgumentException(); if (runtimeClasspathProviders == null) loadRuntimeClasspathProviders(); Iterator iterator = runtimeClasspathProviders.iterator(); while (iterator.hasNext()) { RuntimeClasspathProviderWrapper runtimeClasspathProvider = (RuntimeClasspathProviderWrapper) iterator.next(); if (runtimeClasspathProvider.supportsRuntimeType(id)) return runtimeClasspathProvider; } return null; } /** * Returns the runtime classpath provider with the given id, or <code>null</code> * if none. This convenience method searches the list of known runtime * classpath providers ({@link #getRuntimeClasspathProviders()}) for the one with * a matching runtime classpath provider id ({@link RuntimeClasspathProviderWrapper#getId()}). * The id may not be null. * * @param id the runtime classpath provider id * @return the runtime classpath provider instance, or <code>null</code> if * there is no runtime classpath provider with the given id */ public static RuntimeClasspathProviderWrapper findRuntimeClasspathProvider(String id) { if (id == null) throw new IllegalArgumentException(); if (runtimeClasspathProviders == null) loadRuntimeClasspathProviders(); Iterator iterator = runtimeClasspathProviders.iterator(); while (iterator.hasNext()) { RuntimeClasspathProviderWrapper runtimeClasspathProvider = (RuntimeClasspathProviderWrapper) iterator.next(); if (id.equals(runtimeClasspathProvider.getId())) return runtimeClasspathProvider; } return null; } /** * Load the runtime classpath providers. */ private static synchronized void loadRuntimeClasspathProviders() { if (runtimeClasspathProviders != null) return; if (Trace.CONFIG) { Trace.trace(Trace.STRING_CONFIG, "->- Loading .runtimeClasspathProviders extension point ->-"); } IExtensionRegistry registry = Platform.getExtensionRegistry(); IConfigurationElement[] cf = registry.getConfigurationElementsFor(JavaServerPlugin.PLUGIN_ID, "runtimeClasspathProviders"); List<RuntimeClasspathProviderWrapper> list = new ArrayList<RuntimeClasspathProviderWrapper>(cf.length); for (IConfigurationElement ce : cf) { try { list.add(new RuntimeClasspathProviderWrapper(ce)); if (Trace.CONFIG) { Trace.trace(Trace.STRING_CONFIG, " Loaded runtimeClasspathProviders: " + ce.getAttribute("id")); } } catch (Throwable t) { if (Trace.SEVERE) { Trace.trace(Trace.STRING_SEVERE, " Could not load runtimeClasspathProviders: " + ce.getAttribute("id"), t); } } } runtimeClasspathProviders = list; if (Trace.CONFIG) { Trace.trace(Trace.STRING_CONFIG, "-<- Done loading .runtimeClasspathProviders extension point -<-"); } } /** * Returns an array of all known server profiler instances. * <p> * A new array is returned on each call, so clients may store or modify the result. * </p> * * @return a possibly-empty array of server profiler instances * {@link ServerProfiler} */ public static ServerProfiler[] getServerProfilers() { if (serverProfilers == null) loadServerProfilers(); ServerProfiler[] sp = new ServerProfiler[serverProfilers.size()]; serverProfilers.toArray(sp); return sp; } /** * Load the server profilers. */ private static synchronized void loadServerProfilers() { if (serverProfilers != null) return; if (Trace.CONFIG) { Trace.trace(Trace.STRING_CONFIG, "->- Loading .serverProfilers extension point ->-"); } IExtensionRegistry registry = Platform.getExtensionRegistry(); IConfigurationElement[] cf = registry.getConfigurationElementsFor(JavaServerPlugin.PLUGIN_ID, "serverProfilers"); List<ServerProfiler> list = new ArrayList<ServerProfiler>(cf.length); for (IConfigurationElement ce : cf) { try { list.add(new ServerProfiler(ce)); if (Trace.CONFIG) { Trace.trace(Trace.STRING_CONFIG, " Loaded serverProfiler: " + ce.getAttribute("id")); } } catch (Throwable t) { if (Trace.SEVERE) { Trace.trace(Trace.STRING_SEVERE, " Could not load serverProfiler: " + ce.getAttribute("id"), t); } } } serverProfilers = list; if (Trace.CONFIG) { Trace.trace(Trace.STRING_CONFIG, "-<- Done loading .serverProfilers extension point -<-"); } } public static void configureProfiling(ILaunch launch, IVMInstall vmInstall, VMRunnerConfiguration vmConfig, IProgressMonitor monitor) throws CoreException { ServerProfiler[] sp = JavaServerPlugin.getServerProfilers(); if (sp == null || sp.length == 0) throw new CoreException(new Status(IStatus.ERROR, JavaServerPlugin.PLUGIN_ID, 0, Messages.errorNoProfiler, null)); String id = ProfilerPreferences.getInstance().getServerProfilerId(); if ( id != null ) { for ( int i = 0; i < sp.length; i++ ) { if ( sp[i].getId().equals(id) ) { sp[i].process(launch, vmInstall, vmConfig, monitor); return; } } } else { if ( sp.length == 1 ) { /* The user has not selected a profiler preference, but there is only one * registered so we can just call that */ sp[0].process(launch, vmInstall, vmConfig, monitor); } else { /* We have more than one profiler registered, but the user has not yet * configured their preference so we don't know which one to call. Throw * an exception and notify the user must configure the profiler * before continuing. */ throw new CoreException(new Status(IStatus.ERROR, JavaServerPlugin.PLUGIN_ID, 0, Messages.noProfilersSelected, null)); } } } }