| /******************************************************************************* |
| * Copyright (c) 2007 Chase Technology Ltd - http://www.chasetechnology.co.uk |
| * 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: |
| * Doug Satchwell (Chase Technology Ltd) - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.wst.xsl.internal.launching; |
| |
| import java.io.BufferedInputStream; |
| import java.io.BufferedOutputStream; |
| import java.io.File; |
| import java.io.FileOutputStream; |
| import java.io.IOException; |
| import java.net.URL; |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| import org.eclipse.core.filesystem.EFS; |
| import org.eclipse.core.filesystem.IFileStore; |
| import org.eclipse.core.resources.IFile; |
| import org.eclipse.core.resources.IResource; |
| import org.eclipse.core.resources.ResourcesPlugin; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IPath; |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.NullProgressMonitor; |
| import org.eclipse.core.runtime.Path; |
| import org.eclipse.core.runtime.Platform; |
| import org.eclipse.core.runtime.Status; |
| import org.eclipse.core.variables.VariablesPlugin; |
| import org.eclipse.debug.core.DebugEvent; |
| import org.eclipse.debug.core.DebugPlugin; |
| import org.eclipse.debug.core.IBreakpointManager; |
| import org.eclipse.debug.core.IDebugEventSetListener; |
| import org.eclipse.debug.core.ILaunch; |
| import org.eclipse.debug.core.ILaunchConfiguration; |
| import org.eclipse.debug.core.ILaunchManager; |
| import org.eclipse.debug.core.model.IBreakpoint; |
| import org.eclipse.debug.core.model.IDebugTarget; |
| import org.eclipse.debug.core.model.ISourceLocator; |
| import org.eclipse.debug.core.model.IStackFrame; |
| import org.eclipse.jdt.launching.IVMRunner; |
| import org.eclipse.jdt.launching.JavaLaunchDelegate; |
| import org.eclipse.jface.dialogs.IDialogConstants; |
| import org.eclipse.jface.dialogs.MessageDialog; |
| import org.eclipse.ui.IWorkbenchWindow; |
| import org.eclipse.ui.PartInitException; |
| import org.eclipse.ui.PlatformUI; |
| import org.eclipse.ui.ide.IDE; |
| import org.eclipse.wst.xsl.launching.IDebugger; |
| import org.eclipse.wst.xsl.launching.IProcessorInstall; |
| import org.eclipse.wst.xsl.launching.IProcessorInvoker; |
| import org.eclipse.wst.xsl.launching.IProcessorJar; |
| import org.eclipse.wst.xsl.launching.XSLLaunchConfigurationConstants; |
| import org.eclipse.wst.xsl.launching.XSLTRuntime; |
| import org.eclipse.wst.xsl.launching.config.LaunchHelper; |
| import org.eclipse.wst.xsl.launching.model.IXSLConstants; |
| import org.eclipse.wst.xsl.launching.model.XSLDebugTarget; |
| |
| public class XSLTLaunchConfigurationDelegate extends JavaLaunchDelegate implements IDebugEventSetListener |
| { |
| private String mode; |
| private LaunchHelper launchHelper; |
| |
| private class XSLDebugEventSetListener implements IDebugEventSetListener |
| { |
| private ILaunch launch; |
| |
| public XSLDebugEventSetListener(ILaunch launch) |
| { |
| this.launch = launch; |
| } |
| |
| public void handleDebugEvents(DebugEvent[] events) |
| { |
| if (launch.getProcesses().length > 0) |
| { |
| for (DebugEvent debugEvent : events) |
| { |
| if (debugEvent.getSource() == launch.getProcesses()[0] && debugEvent.getKind() == DebugEvent.TERMINATE) |
| { |
| // remove self as listener |
| DebugPlugin.getDefault().removeDebugEventListener(this); |
| File file = launchHelper.getTarget(); |
| IFile ifile = ResourcesPlugin.getWorkspace().getRoot().getFileForLocation(new Path(file.getAbsolutePath())); |
| if (ifile != null) |
| {// refresh this workspace file.. |
| try |
| { |
| ifile.refreshLocal(IResource.DEPTH_ZERO, new NullProgressMonitor(){ |
| @Override |
| public void done() |
| { |
| openFileIfRequired(); |
| } |
| }); |
| } |
| catch (CoreException e) |
| { |
| LaunchingPlugin.log(e); |
| } |
| } |
| else |
| { |
| openFileIfRequired(); |
| } |
| } |
| } |
| } |
| } |
| |
| private void openFileIfRequired() |
| { |
| // TODO this is dirty - need to declare extension point and move the UI code into the UI plugin |
| if (launchHelper.getOpenFileOnCompletion()) |
| { |
| PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() |
| { |
| public void run() |
| { |
| // Open editor on new file. |
| IWorkbenchWindow dw = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); |
| try |
| { |
| File file = launchHelper.getTarget(); |
| Path path = new Path(file.getAbsolutePath()); |
| IFileStore filestore = EFS.getLocalFileSystem().getStore(path); |
| IDE.openEditorOnFileStore(dw.getActivePage(), filestore); |
| } |
| catch (PartInitException e) |
| { |
| LaunchingPlugin.log(e); |
| } |
| } |
| }); |
| } |
| } |
| } |
| |
| @Override |
| public synchronized void launch(ILaunchConfiguration configuration, final String mode, final ILaunch launch, IProgressMonitor monitor) throws CoreException |
| { |
| this.mode = mode; |
| launchHelper = new LaunchHelper(configuration); |
| launchHelper.save(getLaunchConfigFile()); |
| DebugPlugin.getDefault().addDebugEventListener(new XSLDebugEventSetListener(launch)); |
| |
| // the super.launch will add a Java source director if we set it to null here |
| final ISourceLocator configuredLocator = launch.getSourceLocator(); |
| launch.setSourceLocator(null); |
| |
| super.launch(configuration, mode, launch, monitor); |
| |
| // now get the java source locator |
| final ISourceLocator javaSourceLookupDirector = (ISourceLocator)launch.getSourceLocator(); |
| // now add our own participant to the java director |
| launch.setSourceLocator(new ISourceLocator(){ |
| |
| public Object getSourceElement(IStackFrame stackFrame) |
| { |
| // simply look at one and then the other |
| Object sourceElement = javaSourceLookupDirector.getSourceElement(stackFrame); |
| if (sourceElement == null) |
| sourceElement = configuredLocator.getSourceElement(stackFrame); |
| return sourceElement; |
| }}); |
| |
| // IJavaDebugTarget javaTarget = (IJavaDebugTarget)launch.getDebugTarget(); |
| // launch.removeDebugTarget(javaTarget); |
| |
| IDebugTarget javaTarget = launch.getDebugTarget(); |
| IDebugTarget xslTarget = new XSLDebugTarget(launch, launch.getProcesses()[0], launchHelper); |
| |
| // remove java as the primary target and make xsl the primary target |
| launch.removeDebugTarget(javaTarget); |
| launch.addDebugTarget(xslTarget); |
| // add this here to make java the non-primary target |
| // launch.addDebugTarget(javaTarget); |
| |
| // launch.addDebugTarget(new JavaXSLDebugTarget(launch, launch.getProcesses()[0], launchHelper, javaTarget)); |
| } |
| |
| /** |
| * Get the Java breakpoint and the XSL breakpoints |
| */ |
| @Override |
| protected IBreakpoint[] getBreakpoints(ILaunchConfiguration configuration) |
| { |
| IBreakpointManager breakpointManager = DebugPlugin.getDefault().getBreakpointManager(); |
| if (!breakpointManager.isEnabled()) |
| return null; |
| |
| IBreakpoint[] javaBreakpoints = super.getBreakpoints(configuration); |
| IBreakpoint[] xslBreakpoints = breakpointManager.getBreakpoints(IXSLConstants.ID_XSL_DEBUG_MODEL); |
| IBreakpoint[] breakpoints = new IBreakpoint[javaBreakpoints.length+xslBreakpoints.length]; |
| System.arraycopy(javaBreakpoints, 0, breakpoints, 0, javaBreakpoints.length); |
| System.arraycopy(xslBreakpoints, 0, breakpoints, javaBreakpoints.length, xslBreakpoints.length); |
| |
| return breakpoints; |
| } |
| |
| @Override |
| public boolean preLaunchCheck(ILaunchConfiguration configuration, String mode, IProgressMonitor monitor) throws CoreException |
| { |
| if (mode.equals(ILaunchManager.DEBUG_MODE)) |
| { |
| final IProcessorInstall install = getProcessorInstall(configuration, ILaunchManager.RUN_MODE); |
| if (install.getDebugger() == null) |
| { |
| final boolean[] result = new boolean[] |
| { false }; |
| // open a dialog for choosing a different install that does have |
| // an associated debugger |
| PlatformUI.getWorkbench().getDisplay().syncExec(new Runnable() |
| { |
| public void run() |
| { |
| String debuggingInstallId = LaunchingPlugin.getDefault().getPluginPreferences().getString(XSLLaunchConfigurationConstants.ATTR_DEFAULT_DEBUGGING_INSTALL_ID); |
| IProcessorInstall processor = XSLTRuntime.getProcessor(debuggingInstallId); |
| |
| IWorkbenchWindow dw = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); |
| |
| String title = Messages.getString("XSLTLaunchConfigurationDelegate.0"); //$NON-NLS-1$ |
| String message = Messages.getString("XSLTLaunchConfigurationDelegate.1") + install.getName() + Messages.getString("XSLTLaunchConfigurationDelegate.2") //$NON-NLS-1$ //$NON-NLS-2$ |
| + Messages.getString("XSLTLaunchConfigurationDelegate.3") + processor.getName() + Messages.getString("XSLTLaunchConfigurationDelegate.4");//$NON-NLS-1$ //$NON-NLS-2$ |
| |
| MessageDialog dialog = new MessageDialog(dw.getShell(), title, null, message, MessageDialog.QUESTION, |
| new String[] { IDialogConstants.OK_LABEL, IDialogConstants.CANCEL_LABEL }, 0); // yes is the default |
| |
| result[0] = dialog.open() == 0; |
| } |
| }); |
| return result[0]; |
| } |
| } |
| return super.preLaunchCheck(configuration, mode, monitor); |
| } |
| |
| @Override |
| public IVMRunner getVMRunner(ILaunchConfiguration configuration, String mode) throws CoreException |
| { |
| // comment this out in order to get java debugging as well as XSL debugging |
| // if (ILaunchManager.DEBUG_MODE.equals(mode)) |
| // return super.getVMRunner(configuration, ILaunchManager.RUN_MODE); |
| return super.getVMRunner(configuration, mode); |
| } |
| |
| private File getLaunchConfigFile() |
| { |
| IPath launchPath = Platform.getStateLocation(LaunchingPlugin.getDefault().getBundle()).append(Messages.getString("XSLTLaunchConfigurationDelegate.5")); //$NON-NLS-1$ |
| File launchDir = launchPath.toFile(); |
| if (!launchDir.exists()) |
| launchDir.mkdir(); |
| File featuresFile = new File(launchDir, Messages.getString("XSLTLaunchConfigurationDelegate.6")); //$NON-NLS-1$ |
| return featuresFile; |
| } |
| |
| @Override |
| public IPath getWorkingDirectoryPath(ILaunchConfiguration configuration) throws CoreException |
| { |
| String path = configuration.getAttribute(XSLLaunchConfigurationConstants.ATTR_PROCESSOR_WORKING_DIR, (String) null); |
| if (path != null) |
| { |
| path = VariablesPlugin.getDefault().getStringVariableManager().performStringSubstitution(path); |
| return new Path(path); |
| } |
| return null; |
| } |
| |
| private IProcessorInvoker getProcessorInvokerDescriptor(ILaunchConfiguration configuration) throws CoreException |
| { |
| String invokerId = configuration.getAttribute(XSLLaunchConfigurationConstants.INVOKER_DESCRIPTOR, (String) null); |
| if (invokerId == null) |
| invokerId = "org.eclipse.wst.xsl.launching.jaxp.invoke"; //$NON-NLS-1$ |
| return XSLTRuntime.getProcessorInvoker(invokerId); |
| } |
| |
| public static IProcessorInstall getProcessorInstall(ILaunchConfiguration configuration, String mode) throws CoreException |
| { |
| IProcessorInstall install; |
| boolean useDefaultProcessor = configuration.getAttribute(XSLLaunchConfigurationConstants.ATTR_USE_DEFAULT_PROCESSOR, true); |
| if (useDefaultProcessor) |
| { |
| install = XSLTRuntime.getDefaultProcessor(); |
| } |
| else |
| { |
| String processorId = configuration.getAttribute(XSLLaunchConfigurationConstants.ATTR_PROCESSOR, ""); //$NON-NLS-1$ |
| install = XSLTRuntime.getProcessor(processorId); |
| } |
| if (mode.equals(ILaunchManager.DEBUG_MODE) && install.getDebugger() == null) |
| { |
| String debuggingInstallId = LaunchingPlugin.getDefault().getPluginPreferences().getString(XSLLaunchConfigurationConstants.ATTR_DEFAULT_DEBUGGING_INSTALL_ID); |
| install = XSLTRuntime.getProcessor(debuggingInstallId); |
| } |
| return install; |
| } |
| |
| @Override |
| public String getMainTypeName(ILaunchConfiguration configuration) throws CoreException |
| { |
| if (ILaunchManager.DEBUG_MODE.equals(mode)) |
| return "org.eclipse.wst.xsl.debugger.DebugRunner"; //$NON-NLS-1$ |
| return "org.eclipse.wst.xsl.invoker.Main"; //$NON-NLS-1$ |
| } |
| |
| @Override |
| public String getProgramArguments(ILaunchConfiguration configuration) throws CoreException |
| { |
| // classname, sourceurl, output file |
| IProcessorInvoker invoker = getProcessorInvokerDescriptor(configuration); |
| String clazz = invoker.getInvokerClassName(); |
| |
| StringBuffer sb = new StringBuffer(); |
| sb.append(clazz); |
| sb.append(" "); //$NON-NLS-1$ |
| sb.append("\"" + getLaunchConfigFile().getAbsolutePath() + "\""); //$NON-NLS-1$ //$NON-NLS-2$ |
| sb.append(" "); //$NON-NLS-1$ |
| sb.append("\"" + launchHelper.getSource() + "\""); //$NON-NLS-1$ //$NON-NLS-2$ |
| sb.append(" "); //$NON-NLS-1$ |
| sb.append("\"" + launchHelper.getTarget().getAbsolutePath() + "\""); //$NON-NLS-1$ //$NON-NLS-2$ |
| if (ILaunchManager.DEBUG_MODE.equals(mode)) |
| { |
| IProcessorInstall install = getProcessorInstall(configuration, mode); |
| if (install.getDebugger() != null) |
| { |
| IDebugger debugger = install.getDebugger(); |
| String className = debugger.getClassName(); |
| sb.append(" -debug ").append(className).append(" "); //$NON-NLS-1$ //$NON-NLS-2$ |
| sb.append(launchHelper.getRequestPort()).append(" ").append(launchHelper.getEventPort()); //$NON-NLS-1$ |
| } |
| } |
| |
| return sb.toString(); |
| } |
| |
| @Override |
| public String[] getClasspath(ILaunchConfiguration configuration) throws CoreException |
| { |
| // get the classpath defined by the user |
| String[] userClasspath = super.getClasspath(configuration); |
| |
| // get the classpath required for the transformation |
| IProcessorInvoker invoker = getProcessorInvokerDescriptor(configuration); |
| List<String> invokerCP = new ArrayList<String>(); |
| for (String entry : invoker.getClasspathEntries()) |
| { |
| invokerCP.add(entry); |
| } |
| |
| // add the debugger... |
| IProcessorInstall install = getProcessorInstall(configuration, mode); |
| if (ILaunchManager.DEBUG_MODE.equals(mode) && install.getDebugger() != null) |
| { |
| String[] jars = install.getDebugger().getClassPath(); |
| for (String jar : jars) |
| { |
| invokerCP.add(jar); |
| } |
| } |
| |
| String[] invokerClasspath = (String[]) invokerCP.toArray(new String[0]); |
| |
| // add them together |
| String[] classpath = new String[userClasspath.length + invokerClasspath.length]; |
| System.arraycopy(invokerClasspath, 0, classpath, 0, invokerClasspath.length); |
| System.arraycopy(userClasspath, 0, classpath, invokerClasspath.length, userClasspath.length); |
| |
| return classpath; |
| } |
| |
| @Override |
| public String getVMArguments(ILaunchConfiguration configuration) throws CoreException |
| { |
| String vmargs = super.getVMArguments(configuration); |
| |
| IProcessorInstall install = getProcessorInstall(configuration, mode); |
| if (install != null && !install.getProcessorType().isJREDefault()) |
| { |
| // clear the endorsed dir |
| File tempDir = getEndorsedDir(); |
| if (tempDir.exists()) |
| { |
| File[] children = tempDir.listFiles(); |
| for (File child : children) |
| { |
| child.delete(); |
| } |
| tempDir.delete(); |
| } |
| tempDir.mkdir(); |
| |
| // move the required jars to the endorsed dir |
| IProcessorJar[] jars = install.getProcessorJars(); |
| for (int i = 0; i < jars.length; i++) |
| { |
| URL entry = jars[i].asURL(); |
| if (entry == null) |
| throw new CoreException(new Status(IStatus.ERROR, LaunchingPlugin.PLUGIN_ID, IStatus.ERROR, Messages.getString("XSLTLaunchConfigurationDelegate.23") + jars[i], null)); //$NON-NLS-1$ |
| File file = new File(tempDir, "END_" + i + ".jar"); //$NON-NLS-1$ //$NON-NLS-2$ |
| moveFile(entry, file); |
| } |
| // add the endorsed dir |
| vmargs += " -Djava.endorsed.dirs=\"" + tempDir.getAbsolutePath() + "\""; //$NON-NLS-1$ //$NON-NLS-2$ |
| String tfactory = install.getProcessorType().getTransformerFactoryName(); |
| if (tfactory != null) |
| vmargs += " -Djavax.xml.transform.TransformerFactory=" + install.getProcessorType().getTransformerFactoryName(); //$NON-NLS-1$ |
| } |
| return vmargs; |
| } |
| |
| private File getEndorsedDir() |
| { |
| IPath tempLocation = Platform.getStateLocation(LaunchingPlugin.getDefault().getBundle()).append("endorsed"); //$NON-NLS-1$ |
| return tempLocation.toFile(); |
| } |
| |
| private static void moveFile(URL src, File target) throws CoreException |
| { |
| BufferedOutputStream bos = null; |
| BufferedInputStream bis = null; |
| try |
| { |
| bos = new BufferedOutputStream(new FileOutputStream(target)); |
| bis = new BufferedInputStream(src.openStream()); |
| while (bis.available() > 0) |
| { |
| int size = bis.available(); |
| if (size > 1024) |
| size = 1024; |
| byte[] b = new byte[size]; |
| bis.read(b, 0, b.length); |
| bos.write(b); |
| } |
| } |
| catch (IOException e) |
| { |
| throw new CoreException(new Status(IStatus.ERROR, LaunchingPlugin.PLUGIN_ID, IStatus.ERROR, Messages.getString("XSLTLaunchConfigurationDelegate.7") + src + Messages.getString("XSLTLaunchConfigurationDelegate.31") + target, e)); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| finally |
| { |
| if (bis != null) |
| { |
| try |
| { |
| bis.close(); |
| } |
| catch (IOException e) |
| { |
| LaunchingPlugin.log(e); |
| } |
| } |
| if (bos != null) |
| { |
| try |
| { |
| bos.close(); |
| } |
| catch (IOException e) |
| { |
| LaunchingPlugin.log(e); |
| } |
| } |
| } |
| } |
| } |