| /******************************************************************************* |
| * 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.launching.config; |
| |
| import java.io.BufferedWriter; |
| import java.io.ByteArrayInputStream; |
| import java.io.File; |
| import java.io.FileNotFoundException; |
| import java.io.FileWriter; |
| import java.io.IOException; |
| import java.net.MalformedURLException; |
| import java.net.ServerSocket; |
| import java.net.URL; |
| import java.util.Iterator; |
| import java.util.Map; |
| |
| import javax.xml.parsers.ParserConfigurationException; |
| import javax.xml.transform.TransformerException; |
| |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IPath; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.Path; |
| import org.eclipse.core.runtime.Status; |
| import org.eclipse.core.variables.VariablesPlugin; |
| import org.eclipse.debug.core.ILaunchConfiguration; |
| import org.eclipse.wst.xsl.internal.launching.LaunchingPlugin; |
| import org.eclipse.wst.xsl.internal.launching.PreferenceUtil; |
| import org.eclipse.wst.xsl.invoker.config.PipelineDefinition; |
| import org.eclipse.wst.xsl.invoker.config.TransformDefinition; |
| import org.eclipse.wst.xsl.invoker.config.TypedValue; |
| import org.eclipse.wst.xsl.launching.IFeature; |
| import org.eclipse.wst.xsl.launching.IOutputProperty; |
| import org.eclipse.wst.xsl.launching.IProcessorInstall; |
| import org.eclipse.wst.xsl.launching.IProcessorType; |
| import org.eclipse.wst.xsl.launching.XSLLaunchConfigurationConstants; |
| import org.eclipse.wst.xsl.launching.XSLTRuntime; |
| import org.w3c.dom.Document; |
| |
| public class LaunchHelper |
| { |
| private IPath sourceFile; |
| private final URL source; |
| private final File target; |
| private final LaunchFeatures features; |
| private final LaunchPipeline pipeline; |
| private final LaunchProperties outputProperties; |
| private int requestPort = -1; |
| private int eventPort = -1; |
| private final boolean openFileOnCompletion; |
| |
| public LaunchHelper(ILaunchConfiguration configuration) throws CoreException |
| { |
| source = hydrateSourceFileURL(configuration); |
| target = hydrateOutputFile(configuration); |
| features = hydrateFeatures(configuration); |
| outputProperties = hydrateOutputProperties(configuration); |
| pipeline = hydratePipeline(configuration); |
| openFileOnCompletion = configuration.getAttribute(XSLLaunchConfigurationConstants.ATTR_OPEN_FILE, true); |
| } |
| |
| public int getRequestPort() |
| { |
| if (requestPort == -1) |
| requestPort = findFreePort(); |
| return requestPort; |
| } |
| |
| public int getEventPort() |
| { |
| if (eventPort == -1) |
| eventPort = findFreePort(); |
| return eventPort; |
| } |
| |
| public LaunchProperties getProperties() |
| { |
| return outputProperties; |
| } |
| |
| public LaunchFeatures getFeatures() |
| { |
| return features; |
| } |
| |
| public LaunchPipeline getPipeline() |
| { |
| return pipeline; |
| } |
| |
| public URL getSource() |
| { |
| return source; |
| } |
| |
| public File getTarget() |
| { |
| return target; |
| } |
| |
| public void save(File file) throws CoreException |
| { |
| BufferedWriter writer = null; |
| try |
| { |
| // ensure it exists |
| file.createNewFile(); |
| writer = new BufferedWriter(new FileWriter(file)); |
| PipelineDefinition pdef = new PipelineDefinition(); |
| for (Iterator<?> iter = features.getFeatures().iterator(); iter.hasNext();) |
| { |
| LaunchAttribute att = (LaunchAttribute) iter.next(); |
| pdef.addFeature(new TypedValue(att.uri, att.type, att.value)); |
| } |
| for (Iterator<?> iter = pipeline.getTransformDefs().iterator(); iter.hasNext();) |
| { |
| LaunchTransform lt = (LaunchTransform) iter.next(); |
| TransformDefinition tdef = new TransformDefinition(); |
| URL url = pathToURL(lt.getLocation()); |
| tdef.setStylesheetURL(url.toExternalForm()); |
| tdef.setResolverClass(lt.getResolver()); |
| for (Iterator<?> iterator = lt.getParameters().iterator(); iterator.hasNext();) |
| { |
| LaunchAttribute att = (LaunchAttribute) iterator.next(); |
| tdef.addParameter(new TypedValue(att.uri, att.type, att.value)); |
| } |
| // set the output props for the LAST transform only |
| if (!iter.hasNext()) |
| { |
| for (Iterator<?> iterator = outputProperties.getProperties().entrySet().iterator(); iterator.hasNext();) |
| { |
| Map.Entry entry = (Map.Entry) iterator.next(); |
| String name = (String) entry.getKey(); |
| String value = (String) entry.getValue(); |
| if (name != null && value != null) |
| tdef.setOutputProperty(name, value); |
| } |
| } |
| pdef.addTransformDef(tdef); |
| } |
| |
| Document doc = pdef.toXML(); |
| String s = PreferenceUtil.serializeDocument(doc); |
| writer.write(s); |
| } |
| catch (FileNotFoundException e) |
| { |
| throw new CoreException(new Status(IStatus.ERROR, LaunchingPlugin.PLUGIN_ID, IStatus.ERROR, "File not found", e)); |
| } |
| catch (IOException e) |
| { |
| throw new CoreException(new Status(IStatus.ERROR, LaunchingPlugin.PLUGIN_ID, IStatus.ERROR, "IO Exception", e)); |
| } |
| catch (ParserConfigurationException e) |
| { |
| throw new CoreException(new Status(IStatus.ERROR, LaunchingPlugin.PLUGIN_ID, IStatus.ERROR, "ParserConfigurationException", e)); |
| } |
| catch (TransformerException e) |
| { |
| throw new CoreException(new Status(IStatus.ERROR, LaunchingPlugin.PLUGIN_ID, IStatus.ERROR, "TransformerException", e)); |
| } |
| finally |
| { |
| if (writer != null) |
| { |
| try |
| { |
| writer.close(); |
| } |
| catch (IOException e) |
| { |
| LaunchingPlugin.log(e); |
| } |
| } |
| } |
| } |
| |
| private LaunchProperties hydrateOutputProperties(ILaunchConfiguration configuration) throws CoreException |
| { |
| LaunchProperties properties = null; |
| boolean usePreferenceProperties = configuration.getAttribute(XSLLaunchConfigurationConstants.ATTR_USE_PROPERTIES_FROM_PREFERENCES, true); |
| IProcessorType defaultType = XSLTRuntime.getJREDefaultProcessor().getProcessorType(); |
| IProcessorType pt = getProcessorInstall(configuration).getProcessorType(); |
| if (usePreferenceProperties) |
| { |
| properties = new LaunchProperties(); |
| // get the standard properties |
| for (Object element : defaultType.getOutputPropertyValues().entrySet()) |
| { |
| Map.Entry entry = (Map.Entry) element; |
| String name = (String) entry.getKey(); |
| String value = (String) entry.getValue(); |
| properties.setProperty(name, value); |
| } |
| // get the processor-specific properties |
| if (!pt.equals(defaultType)) |
| { |
| for (Object element : pt.getOutputPropertyValues().entrySet()) |
| { |
| Map.Entry entry = (Map.Entry) element; |
| String name = (String) entry.getKey(); |
| String value = (String) entry.getValue(); |
| properties.setProperty(name, value); |
| } |
| } |
| } |
| else |
| { |
| String s = configuration.getAttribute(XSLLaunchConfigurationConstants.ATTR_OUTPUT_PROPERTIES, (String) null); |
| if (s != null && s.length() > 0) |
| { |
| ByteArrayInputStream inputStream = new ByteArrayInputStream(s.getBytes()); |
| properties = LaunchProperties.fromXML(inputStream); |
| // ensure all properties pertain to the current processor type |
| IOutputProperty[] defaultProps = defaultType.getOutputProperties(); |
| IOutputProperty[] specificProps = pt.getOutputProperties(); |
| IOutputProperty[] props = new IOutputProperty[specificProps.length + defaultProps.length]; |
| System.arraycopy(specificProps, 0, props, 0, specificProps.length); |
| System.arraycopy(defaultProps, 0, props, specificProps.length, defaultProps.length); |
| for (Iterator<?> iterator = properties.getProperties().keySet().iterator(); iterator.hasNext();) |
| { |
| String key = (String) iterator.next(); |
| boolean found = false; |
| for (IOutputProperty outputProperty : props) |
| { |
| if (outputProperty.getURI().equals(key)) |
| { |
| found = true; |
| } |
| } |
| if (!found) |
| properties.removeProperty(key); |
| } |
| } |
| } |
| return properties; |
| } |
| |
| private LaunchFeatures hydrateFeatures(ILaunchConfiguration configuration) throws CoreException |
| { |
| LaunchFeatures features = null; |
| boolean useDefaultFeatures = configuration.getAttribute(XSLLaunchConfigurationConstants.ATTR_USE_FEATURES_FROM_PREFERENCES, true); |
| if (useDefaultFeatures) |
| { |
| features = new LaunchFeatures(); |
| IProcessorType pt = getProcessorInstall(configuration).getProcessorType(); |
| Map<?, ?> fvals = pt.getFeatureValues(); |
| for (Iterator<?> iter = fvals.entrySet().iterator(); iter.hasNext();) |
| { |
| Map.Entry entry = (Map.Entry) iter.next(); |
| String uri = (String) entry.getKey(); |
| IFeature feature = getFeature(pt.getFeatures(), uri); |
| features.addFeature(new LaunchAttribute(uri, feature.getType(), (String) entry.getValue())); |
| } |
| } |
| else |
| { |
| String s = configuration.getAttribute(XSLLaunchConfigurationConstants.ATTR_FEATURES, (String) null); |
| if (s != null && s.length() > 0) |
| { |
| ByteArrayInputStream inputStream = new ByteArrayInputStream(s.getBytes()); |
| features = LaunchFeatures.fromXML(inputStream); |
| } |
| } |
| return features; |
| } |
| |
| private IFeature getFeature(IFeature[] features, String uri) |
| { |
| for (IFeature feature : features) |
| { |
| if (feature.getURI().equals(uri)) |
| return feature; |
| } |
| return null; |
| } |
| |
| private LaunchPipeline hydratePipeline(ILaunchConfiguration configuration) throws CoreException |
| { |
| LaunchPipeline pipeline = null; |
| String s = configuration.getAttribute(XSLLaunchConfigurationConstants.ATTR_PIPELINE, (String) null); |
| if (s != null && s.length() > 0) |
| { |
| ByteArrayInputStream inputStream = new ByteArrayInputStream(s.getBytes()); |
| pipeline = LaunchPipeline.fromXML(inputStream); |
| } |
| return pipeline; |
| } |
| |
| private URL hydrateSourceFileURL(ILaunchConfiguration configuration) throws CoreException |
| { |
| String sourceFileExpr = configuration.getAttribute(XSLLaunchConfigurationConstants.ATTR_INPUT_FILE, (String) null); |
| sourceFile = getSubstitutedPath(sourceFileExpr); |
| URL url = pathToURL(sourceFile); |
| return url; |
| } |
| |
| private URL pathToURL(IPath sourceFile) throws CoreException |
| { |
| URL url = null; |
| try |
| { |
| url = sourceFile.toFile().toURL(); |
| } |
| catch (MalformedURLException e) |
| { |
| throw new CoreException(new Status(IStatus.ERROR, LaunchingPlugin.PLUGIN_ID, IStatus.ERROR, sourceFile.toString(), e)); |
| } |
| return url; |
| } |
| |
| private File hydrateOutputFile(ILaunchConfiguration configuration) throws CoreException |
| { |
| IPath outputFile = null; |
| boolean useDefaultOutputFile = configuration.getAttribute(XSLLaunchConfigurationConstants.ATTR_USE_DEFAULT_OUTPUT_FILE, true); |
| if (!useDefaultOutputFile) |
| { |
| String outputFileExpr = configuration.getAttribute(XSLLaunchConfigurationConstants.ATTR_OUTPUT_FILE, (String) null); |
| outputFile = getSubstitutedPath(outputFileExpr); |
| } |
| else |
| { |
| // TODO: where is the default output file? And must share this with |
| // the value displayed in the UI. |
| outputFile = (IPath) sourceFile.clone(); |
| outputFile = outputFile.addFileExtension("out").addFileExtension("xml"); |
| } |
| return outputFile.toFile(); |
| } |
| |
| private static IPath getSubstitutedPath(String path) throws CoreException |
| { |
| if (path != null) |
| { |
| path = VariablesPlugin.getDefault().getStringVariableManager().performStringSubstitution(path); |
| return new Path(path); |
| } |
| return null; |
| } |
| |
| private IProcessorInstall getProcessorInstall(ILaunchConfiguration configuration) throws CoreException |
| { |
| boolean useDefaultProcessor = configuration.getAttribute(XSLLaunchConfigurationConstants.ATTR_USE_DEFAULT_PROCESSOR, true); |
| if (useDefaultProcessor) |
| return XSLTRuntime.getDefaultProcessor(); |
| String processorId = configuration.getAttribute(XSLLaunchConfigurationConstants.ATTR_PROCESSOR, ""); |
| IProcessorInstall processor = XSLTRuntime.getProcessor(processorId); |
| return processor; |
| } |
| |
| /** |
| * Returns a free port number on localhost, or -1 if unable to find a free |
| * port. |
| * |
| * @return a free port number on localhost, or -1 if unable to find a free |
| * port |
| */ |
| public static int findFreePort() |
| { |
| ServerSocket socket = null; |
| try |
| { |
| socket = new ServerSocket(0); |
| return socket.getLocalPort(); |
| } |
| catch (IOException e) |
| { |
| LaunchingPlugin.log(e); |
| } |
| finally |
| { |
| if (socket != null) |
| { |
| try |
| { |
| socket.close(); |
| } |
| catch (IOException e) |
| { |
| LaunchingPlugin.log(e); |
| } |
| } |
| } |
| return -1; |
| } |
| |
| public boolean getOpenFileOnCompletion() |
| { |
| return openFileOnCompletion; |
| } |
| } |