From 5cb1152d1c31d48b910a09d07284610343771499 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20L=C3=A4ubrich?= Date: Mon, 30 Oct 2023 19:54:34 +0100 Subject: [PATCH] Extract code from ConvertSchemaToHTML Ant Task into reusable PDE class Currently non trivial work is done inside the ConvertSchemaToHTML ant task. This extract that parts into SchemaToHTMLConverter so it can be reused by other build frameworks (e.g. maven/tycho) --- .../core/schema/SchemaToHTMLConverter.java | 186 ++++++++++++++++++ .../core/ant/ConvertSchemaToHTML.java | 152 +------------- 2 files changed, 193 insertions(+), 145 deletions(-) create mode 100644 ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/schema/SchemaToHTMLConverter.java diff --git a/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/schema/SchemaToHTMLConverter.java b/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/schema/SchemaToHTMLConverter.java new file mode 100644 index 0000000000..8202cd5201 --- /dev/null +++ b/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/schema/SchemaToHTMLConverter.java @@ -0,0 +1,186 @@ +/******************************************************************************* + * Copyright (c) 2000, 2023 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + * Christoph Läubrich - extract into reusable class + *******************************************************************************/ +package org.eclipse.pde.internal.core.schema; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.util.Locale; +import java.util.Map; +import java.util.Objects; +import java.util.function.Consumer; + +import javax.xml.parsers.ParserConfigurationException; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.osgi.util.ManifestElement; +import org.eclipse.osgi.util.NLS; +import org.eclipse.pde.core.plugin.IPluginExtensionPoint; +import org.eclipse.pde.core.plugin.IPluginModelBase; +import org.eclipse.pde.internal.core.ICoreConstants; +import org.eclipse.pde.internal.core.PDECoreMessages; +import org.eclipse.pde.internal.core.XMLDefaultHandler; +import org.eclipse.pde.internal.core.builders.SchemaTransformer; +import org.eclipse.pde.internal.core.ischema.ISchemaInclude; +import org.eclipse.pde.internal.core.plugin.ExternalFragmentModel; +import org.eclipse.pde.internal.core.plugin.ExternalPluginModel; +import org.eclipse.pde.internal.core.plugin.ExternalPluginModelBase; +import org.eclipse.pde.internal.core.util.HeaderMap; +import org.osgi.framework.BundleException; +import org.osgi.framework.Constants; +import org.xml.sax.SAXException; + +/** + * Takes a plug-in and created HTML reference documents for all schema (.exsd) + * files. + * + */ +public class SchemaToHTMLConverter { + + private final SchemaTransformer fTransformer = new SchemaTransformer(); + private File baseDir; + private URL cssURL; + + public SchemaToHTMLConverter(File baseDir, URL cssURL) { + this.baseDir = baseDir; + this.cssURL = cssURL; + } + + @SuppressWarnings("restriction") + public void generate(String manifest, String destination, SchemaProvider schemaProvider, + Consumer errorConsumer) throws IOException, CoreException { + Objects.requireNonNull(manifest, "manifest can't be null"); //$NON-NLS-1$ + Objects.requireNonNull(destination, "destination can't be null"); //$NON-NLS-1$ + IPluginModelBase model = readManifestFile(manifest); + if (model == null) { + return; + } + + String pluginID = model.getPluginBase().getId(); + if (pluginID == null) { + pluginID = getPluginID(manifest); + } + + IPluginExtensionPoint[] extPoints = model.getPluginBase().getExtensionPoints(); + for (IPluginExtensionPoint extPoint : extPoints) { + String schemaLocation = extPoint.getSchema(); + + if (schemaLocation == null || schemaLocation.equals("")) { //$NON-NLS-1$ + continue; + } + Schema schema = null; + try { + File schemaFile = new File(model.getInstallLocation(), schemaLocation); + XMLDefaultHandler handler = new XMLDefaultHandler(); + try { + org.eclipse.core.internal.runtime.XmlProcessorFactory.createSAXParserWithErrorOnDOCTYPE() + .parse(schemaFile, handler); + } catch (SAXException | ParserConfigurationException e) { + throw new IOException("XML Parser error", e); //$NON-NLS-1$ + } + @SuppressWarnings("deprecation") + URL url = schemaFile.toURL(); + SchemaDescriptor desc = new SchemaDescriptor(extPoint.getFullId(), url, schemaProvider); + schema = (Schema) desc.getSchema(false); + + // Check that all included schemas are available + ISchemaInclude[] includes = schema.getIncludes(); + for (ISchemaInclude include : includes) { + if (include.getIncludedSchema() == null) { + errorConsumer.accept(NLS.bind(PDECoreMessages.ConvertSchemaToHTML_CannotFindIncludedSchema, + include.getLocation(), schemaFile)); + } + } + + File directory = IPath.fromOSString(destination).isAbsolute() ? new File(destination) + : new File(baseDir, destination); + if (!directory.exists() || !directory.isDirectory()) { + if (!directory.mkdirs()) { + schema.dispose(); + return; + } + } + + String id = extPoint.getId(); + if (id.indexOf('.') == -1) { + id = pluginID + "." + id; //$NON-NLS-1$ + } + File file = new File(directory, id.replace('.', '_') + ".html"); //$NON-NLS-1$ + try (PrintWriter out = new PrintWriter( + new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8), true)) { + fTransformer.transform(schema, out, cssURL, SchemaTransformer.BUILD); + } + } finally { + if (schema != null) { + schema.dispose(); + } + } + } + } + + protected String getPluginID(String manifest) throws IOException { + File file = IPath.fromOSString(manifest).isAbsolute() ? new File(manifest) : new File(baseDir, manifest); + File OSGiFile = new File(file.getParentFile(), ICoreConstants.BUNDLE_FILENAME_DESCRIPTOR); + + if (OSGiFile.exists()) { + try (FileInputStream manifestStream = new FileInputStream(OSGiFile)) { + Map headers = ManifestElement.parseBundleManifest(manifestStream, new HeaderMap<>()); + String value = headers.get(Constants.BUNDLE_SYMBOLICNAME); + if (value == null) { + return null; + } + ManifestElement[] elements = ManifestElement.parseHeader(Constants.BUNDLE_SYMBOLICNAME, value); + if (elements.length > 0) { + return elements[0].getValue(); + } + } catch (BundleException bundleException) { + throw new IOException("Invalid Manifest " + OSGiFile, bundleException); //$NON-NLS-1$ + } + } + return null; + } + + protected IPluginModelBase readManifestFile(String manifest) throws IOException, CoreException { + File file = IPath.fromOSString(manifest).isAbsolute() ? new File(manifest) : new File(baseDir, manifest); + try (InputStream stream = new BufferedInputStream(new FileInputStream(file))) { + ExternalPluginModelBase model = null; + switch (file.getName().toLowerCase(Locale.ENGLISH)) { + case ICoreConstants.FRAGMENT_FILENAME_DESCRIPTOR: + model = new ExternalFragmentModel(); + break; + case ICoreConstants.PLUGIN_FILENAME_DESCRIPTOR: + model = new ExternalPluginModel(); + break; + default: + stream.close(); + throw new IOException(NLS.bind(PDECoreMessages.Builders_Convert_illegalValue, "manifest")); //$NON-NLS-1$ + } + String parentPath = file.getParentFile().getAbsolutePath(); + model.setInstallLocation(parentPath); + model.load(stream, false); + stream.close(); + return model; + } + } + +} diff --git a/ui/org.eclipse.pde.core/src_ant/org/eclipse/pde/internal/core/ant/ConvertSchemaToHTML.java b/ui/org.eclipse.pde.core/src_ant/org/eclipse/pde/internal/core/ant/ConvertSchemaToHTML.java index 549f39de30..9779922d5e 100644 --- a/ui/org.eclipse.pde.core/src_ant/org/eclipse/pde/internal/core/ant/ConvertSchemaToHTML.java +++ b/ui/org.eclipse.pde.core/src_ant/org/eclipse/pde/internal/core/ant/ConvertSchemaToHTML.java @@ -13,43 +13,21 @@ *******************************************************************************/ package org.eclipse.pde.internal.core.ant; -import java.io.BufferedInputStream; import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.InputStream; -import java.io.OutputStreamWriter; -import java.io.PrintWriter; import java.net.MalformedURLException; import java.net.URL; -import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; -import java.util.Locale; -import java.util.Map; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.Project; import org.apache.tools.ant.Task; import org.eclipse.core.runtime.IPath; -import org.eclipse.osgi.util.ManifestElement; import org.eclipse.osgi.util.NLS; -import org.eclipse.pde.core.plugin.IPluginExtensionPoint; -import org.eclipse.pde.core.plugin.IPluginModelBase; -import org.eclipse.pde.internal.core.ICoreConstants; import org.eclipse.pde.internal.core.PDECore; import org.eclipse.pde.internal.core.PDECoreMessages; -import org.eclipse.pde.internal.core.XMLDefaultHandler; -import org.eclipse.pde.internal.core.builders.SchemaTransformer; -import org.eclipse.pde.internal.core.ischema.ISchemaInclude; -import org.eclipse.pde.internal.core.plugin.ExternalFragmentModel; -import org.eclipse.pde.internal.core.plugin.ExternalPluginModel; -import org.eclipse.pde.internal.core.plugin.ExternalPluginModelBase; import org.eclipse.pde.internal.core.schema.PathSchemaProvider; -import org.eclipse.pde.internal.core.schema.Schema; -import org.eclipse.pde.internal.core.schema.SchemaDescriptor; -import org.eclipse.pde.internal.core.util.HeaderMap; -import org.osgi.framework.Constants; +import org.eclipse.pde.internal.core.schema.SchemaToHTMLConverter; /** * Ant task that takes a plug-in and created HTML reference documents for all schema (.exsd) files. @@ -57,14 +35,12 @@ */ public class ConvertSchemaToHTML extends Task { - private final SchemaTransformer fTransformer = new SchemaTransformer(); private String manifest; private String destination; private URL cssURL; private String additionalSearchPaths; @Override - @SuppressWarnings("restriction") public void execute() throws BuildException { if (destination == null) { throw new BuildException(NLS.bind(PDECoreMessages.Builders_Convert_missingAttribute, "destination")); //$NON-NLS-1$ @@ -75,70 +51,12 @@ public void execute() throws BuildException { if (!IPath.fromOSString(destination).isValidPath(destination)) { throw new BuildException(NLS.bind(PDECoreMessages.Builders_Convert_illegalValue, "destination")); //$NON-NLS-1$ } - - IPluginModelBase model = readManifestFile(); - if (model == null) { - return; - } - - String pluginID = model.getPluginBase().getId(); - if (pluginID == null) { - pluginID = getPluginID(); - } - - List searchPaths = getSearchPaths(); - - IPluginExtensionPoint[] extPoints = model.getPluginBase().getExtensionPoints(); - for (IPluginExtensionPoint extPoint : extPoints) { - String schemaLocation = extPoint.getSchema(); - - if (schemaLocation == null || schemaLocation.equals("")) { //$NON-NLS-1$ - continue; - } - Schema schema = null; - try { - File schemaFile = new File(model.getInstallLocation(), schemaLocation); - XMLDefaultHandler handler = new XMLDefaultHandler(); - org.eclipse.core.internal.runtime.XmlProcessorFactory.createSAXParserWithErrorOnDOCTYPE() - .parse(schemaFile, handler); - URL url = schemaFile.toURL(); - SchemaDescriptor desc = new SchemaDescriptor(extPoint.getFullId(), url, - new PathSchemaProvider(searchPaths)); - schema = (Schema) desc.getSchema(false); - - // Check that all included schemas are available - ISchemaInclude[] includes = schema.getIncludes(); - for (ISchemaInclude include : includes) { - if (include.getIncludedSchema() == null) { - log(NLS.bind(PDECoreMessages.ConvertSchemaToHTML_CannotFindIncludedSchema, include.getLocation(), schemaFile), Project.MSG_ERR); - } - } - - File directory = IPath.fromOSString(destination).isAbsolute() ? new File(destination) : new File(getProject().getBaseDir(), destination); - if (!directory.exists() || !directory.isDirectory()) { - if (!directory.mkdirs()) { - schema.dispose(); - return; - } - } - - String id = extPoint.getId(); - if (id.indexOf('.') == -1) - { - id = pluginID + "." + id; //$NON-NLS-1$ - } - File file = new File(directory, id.replace('.', '_') + ".html"); //$NON-NLS-1$ - try (PrintWriter out = new PrintWriter( - new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8), true)) { - fTransformer.transform(schema, out, cssURL, SchemaTransformer.BUILD); - } - } catch (Exception e) { - throw new BuildException(e); - } finally { - if (schema != null) { - schema.dispose(); - } - } + SchemaToHTMLConverter converter = new SchemaToHTMLConverter(getProject().getBaseDir(), cssURL); + try { + converter.generate(manifest, destination, new PathSchemaProvider(getSearchPaths()), + err -> log(err, Project.MSG_ERR)); + } catch (Exception e) { + throw new BuildException(e); } } @@ -209,28 +127,6 @@ public void setCSSURL(URL url) { cssURL = url; } - private String getPluginID() { - File file = IPath.fromOSString(manifest).isAbsolute() ? new File(manifest) : new File(getProject().getBaseDir(), manifest); - File OSGiFile = new File(file.getParentFile(), ICoreConstants.BUNDLE_FILENAME_DESCRIPTOR); - - if (OSGiFile.exists()) { - try (FileInputStream manifestStream = new FileInputStream(OSGiFile)) { - Map headers = ManifestElement.parseBundleManifest(manifestStream, new HeaderMap<>()); - String value = headers.get(Constants.BUNDLE_SYMBOLICNAME); - if (value == null) { - return null; - } - ManifestElement[] elements = ManifestElement.parseHeader(Constants.BUNDLE_SYMBOLICNAME, value); - if (elements.length > 0) { - return elements[0].getValue(); - } - } catch (Exception e1) { - System.out.print(e1.getMessage()); - } - } - return null; - } - /** * @return user specified search paths or null */ @@ -255,38 +151,4 @@ private List getSearchPaths() { return result; } - private IPluginModelBase readManifestFile() throws BuildException { - File file = IPath.fromOSString(manifest).isAbsolute() ? new File(manifest) : new File(getProject().getBaseDir(), manifest); - InputStream stream = null; - try { - stream = new BufferedInputStream(new FileInputStream(file)); - } catch (Exception e) { - throw new BuildException(e); - } - - ExternalPluginModelBase model = null; - try { - switch (file.getName().toLowerCase(Locale.ENGLISH)) { - case ICoreConstants.FRAGMENT_FILENAME_DESCRIPTOR: - model = new ExternalFragmentModel(); - break; - case ICoreConstants.PLUGIN_FILENAME_DESCRIPTOR: - model = new ExternalPluginModel(); - break; - default: - stream.close(); - throw new BuildException(NLS.bind(PDECoreMessages.Builders_Convert_illegalValue, "manifest")); //$NON-NLS-1$ - } - - String parentPath = file.getParentFile().getAbsolutePath(); - model.setInstallLocation(parentPath); - model.load(stream, false); - stream.close(); - } catch (Exception e) { - throw new BuildException(e); - } - - return model; - } - }