Hi,
Thankyou for your suggestion about the thread classloader. I have tried it (and had tried something similar in the production code) but it did not work. Using our own classloader was where I was coming from. I had removed it but cannot make the call to createNewEditor work try as I may. I cannot debug further as I do not have your source code. Below is the code from the sample that reproduces the problem. It is derived from your workspace-access plugin and only has minimal changes. Any insights would be appreciated.
Thanks
JF
POM:
Code: Select all
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.oxygenxml.samples</groupId>
<artifactId>oxygen-plugin-workspace-access-problem</artifactId>
<version>1.1.${maven.build.timestamp}</version>
<properties>
<!-- Timestamp of build -->
<timestamp>${maven.build.timestamp}</timestamp>
<maven.build.timestamp.format>yyyyMMddHHmmss</maven.build.timestamp.format>
</properties>
<repositories>
<repository>
<id>public</id>
<name>oXygen public artifacts</name>
<url>http://www.oxygenxml.com/maven</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>com.oxygenxml</groupId>
<artifactId>oxygen-sdk</artifactId>
<version>20.0.0.1</version>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>com.oxygenxml</groupId>
<artifactId>oxygen-xercesImpl</artifactId>
</exclusion>
<exclusion>
<groupId>xml-apis</groupId>
<artifactId>xml-apis</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- https://mvnrepository.com/artifact/xerces/xercesImpl -->
<dependency>
<groupId>xerces</groupId>
<artifactId>xercesImpl</artifactId>
<version>2.11.0</version>
</dependency>
</dependencies>
<build>
<finalName>${project.artifactId}-${project.version}</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
<!-- Copy the runtime dependencies to the lib folder. -->
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.8</version>
<executions>
<execution>
<phase>generate-resources</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/lib</outputDirectory>
<includeScope>runtime</includeScope>
</configuration>
</execution>
</executions>
</plugin>
<!-- We only want the final JAR package in the target folder so that it's
easier for users to identify it. -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.2</version>
<configuration>
<outputDirectory>${project.build.directory}/build</outputDirectory>
<archive>
<manifest>
<addClasspath>false</addClasspath>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.4</version>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<archiveBaseDirectory>${project.basedir}</archiveBaseDirectory>
<descriptors>
<descriptor>assembly.xml</descriptor>
</descriptors>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
<executions>
<execution>
<id>copy-resources</id>
<!-- here the phase you need -->
<phase>validate</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${basedir}/target/</outputDirectory>
<resources>
<resource>
<directory>${project.basedir}</directory>
<includes>
<include>addon.xml</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Assembly.xml
Code: Select all
<assembly
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
<id>plugin</id>
<formats>
<format>jar</format>
</formats>
<fileSets>
<fileSet>
<directory>target/lib</directory>
<outputDirectory>lib</outputDirectory>
<includes>
<include>**/*</include>
</includes>
</fileSet>
</fileSets>
<files>
<file>
<source>target/build/${project.build.finalName}.jar</source>
<outputDirectory>/lib</outputDirectory>
</file>
<file>
<source>plugin.xml</source>
<outputDirectory>/</outputDirectory>
<filtered>true</filtered>
</file>
</files>
</assembly>
Plugin
Code: Select all
<plugin
id="com.oxygenxml.plugin.ProblemWorkspaceAccess"
name="ProblemWorkspaceAccess"
description="Test"
version="${project.version}"
vendor="oXygen XML"
class="com.oxygenxml.sdksamples.workspace.WorkspaceAccessPlugin"
classLoaderType="preferReferencedResources">
<runtime>
<librariesFolder name="lib" />
</runtime>
<extension type="WorkspaceAccess"
class="com.oxygenxml.sdksamples.workspace.CustomWorkspaceAccessPluginExtension"/>
</plugin>
Addon
Code: Select all
<xt:extensions xmlns:xt="http://www.oxygenxml.com/ns/extension"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.oxygenxml.com/ns/extension http://www.oxygenxml.com/ns/extension/extensions.xsd">
<xt:extension xmlns:xt="http://www.oxygenxml.com/ns/extension"
id="com.oxygenxml.plugin.OherWorkspaceAccess">
<xt:location href="${project.build.finalName}-plugin.jar"/>
<xt:version>${project.version}</xt:version>
<xt:oxy_version>17.0+</xt:oxy_version>
<xt:type>plugin</xt:type>
<xt:author>Oxygen XML Editor</xt:author>
<xt:name>OtherCustomWorkspaceAccess</xt:name>
<xt:description><html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Other Sample Workspace Access plugin</title>
</head>
<body>
<div>
<p>This plugin installs access to the <oXygen/> workspace. That enables
<oXygen/> to open/save/close resources, access the editors content,
etc. Such a plugin must implement an WorkspacePluginExtension. </p>
<p>For more details see <a
href="http://www.oxygenxml.com/doc/ug-oxygen/index.html?q=/doc/ug-oxygen/concepts/workspace-access-plugin.html"
>http://www.oxygenxml.com/doc/ug-oxygen/index.html?q=/doc/ug-oxygen/concepts/workspace-access-plugin.html</a>
</p>
</div>
</body>
</html>
</xt:description><xt:license/>
</xt:extension>
</xt:extensions>
WorkspaceAccessPlugin code
Code: Select all
package com.oxygenxml.sdksamples.workspace;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.OpenOption;
import java.nio.file.StandardOpenOption;
import java.util.Arrays;
import java.util.List;
import javax.swing.AbstractAction;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JOptionPane;
import javax.xml.parsers.ParserConfigurationException;
import org.apache.xerces.jaxp.SAXParserFactoryImpl;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import ro.sync.exml.plugin.workspace.WorkspaceAccessPluginExtension;
import ro.sync.exml.workspace.api.standalone.MenuBarCustomizer;
import ro.sync.exml.workspace.api.standalone.StandalonePluginWorkspace;
import ro.sync.exml.workspace.api.util.XMLUtilAccess;
/**
* Plugin extension - workspace access extension.
*/
public class CustomWorkspaceAccessPluginExtension implements WorkspaceAccessPluginExtension {
/**
* @see ro.sync.exml.plugin.workspace.WorkspaceAccessPluginExtension#applicationStarted(ro.sync.exml.workspace.api.standalone.StandalonePluginWorkspace)
*/
@Override
public void applicationStarted(final StandalonePluginWorkspace pluginWorkspaceAccess) {
// Create your own main menu and add it to Oxygen or remove one of Oxygen's
// menus...
pluginWorkspaceAccess.addMenuBarCustomizer(new MenuBarCustomizer() {
/**
* @see ro.sync.exml.workspace.api.standalone.MenuBarCustomizer#customizeMainMenu(javax.swing.JMenuBar)
*/
@Override
public void customizeMainMenu(JMenuBar mainMenuBar) {
final JMenu myMenu = getMainMenu(mainMenuBar);
myMenu.add(createAboutParserMenuAction(pluginWorkspaceAccess));
myMenu.add(createParserMenuAction(pluginWorkspaceAccess));
myMenu.add(createNewEditorMenuAction(pluginWorkspaceAccess));
}
});
}
private static final String MenuName = "Problem Test Menu";
private static JMenu getMainMenu(JMenuBar mainMenuBar) {
Component[] components = mainMenuBar.getComponents();
final int index = getExistingMenuIndex(components, JMenu.class);
JMenu menu;
if (index >= 0) {
//Menu already exists
menu = (JMenu) components[index];
menu.addSeparator();
} else {
//Create new Menu
menu = new JMenu(MenuName);
menu.setName(MenuName);
// Add your menu before the Help menu
mainMenuBar.add(menu, mainMenuBar.getMenuCount() - 1);
}
return menu;
}
private static int getExistingMenuIndex(Component[] components, Class<?> cls) {
int index = -1;
if (components != null) {
for (int i = 0; index == -1 && i < components.length; i++) {
Component comp = components[i];
String name = comp.getName();
if (cls.isInstance(comp) && name != null && name.equals(MenuName)) {
index = i;
}
}
}
return index;
}
@SuppressWarnings("serial")
private AbstractAction createAboutParserMenuAction(final StandalonePluginWorkspace pluginWorkspaceAccess) {
return new AbstractAction("About Parser Menu") {
@Override
public void actionPerformed(ActionEvent actionevent) {
pluginWorkspaceAccess.showInformationMessage("Xerces version is " + getParserVersion());
}
};
}
@SuppressWarnings("serial")
private AbstractAction createParserMenuAction(final StandalonePluginWorkspace pluginWorkspaceAccess) {
return new AbstractAction("Parse Menu") {
@Override
public void actionPerformed(ActionEvent actionevent) {
try {
File f = createNewFile();
parseFile(f, pluginWorkspaceAccess);
pluginWorkspaceAccess.showInformationMessage("Parsed file " + f.getAbsolutePath() + " okay");
} catch (ParserConfigurationException | SAXException | IOException e) {
WorkspaceAccessPlugin.Log.error("Problem executing parse action", e);
JOptionPane.showMessageDialog((Component) pluginWorkspaceAccess.getParentFrame(),
exceptionToString(e), "Problem executing parse action", JOptionPane.ERROR_MESSAGE);
}
}
};
}
@SuppressWarnings("serial")
private AbstractAction createNewEditorMenuAction(final StandalonePluginWorkspace pluginWorkspaceAccess) {
return new AbstractAction("Open New editor Menu") {
@Override
public void actionPerformed(ActionEvent actionevent) {
//ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
try {
//Thread.currentThread().setContextClassLoader(pluginWorkspaceAccess.getClass().getClassLoader());
URL url = pluginWorkspaceAccess.createNewEditor(".xml", "text/xml", "<someXML/>");
pluginWorkspaceAccess.showInformationMessage("Created editor on " + url + " okay");
} catch (Exception e) {
WorkspaceAccessPlugin.Log.error("Problem executing createNewEditor action", e);
JOptionPane.showMessageDialog((Component) pluginWorkspaceAccess.getParentFrame(),
exceptionToString(e), "Problem executing parse action", JOptionPane.ERROR_MESSAGE);
}finally {
//Thread.currentThread().setContextClassLoader(contextClassLoader);
}
}
};
}
private static String exceptionToString(Throwable t) {
try (StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw)) {
t.printStackTrace(pw);
pw.close();
return sw.toString();
} catch (IOException e) {
return "Unable to write stack trace from " + e.getMessage();
}
}
private static void parseFile(File file, StandalonePluginWorkspace pluginWorkspaceAccess)
throws SAXException, ParserConfigurationException, IOException {
XMLUtilAccess xmlUtil = pluginWorkspaceAccess.getXMLUtilAccess();
XMLReader r = createXMLReader();
r.setEntityResolver(xmlUtil.getEntityResolver());
InputSource source = new InputSource(file.getAbsolutePath());
r.parse(source);
//pluginWorkspaceAccess.createNewEditor("xml", "text/xml", "<stuff/>");
}
private static XMLReader createXMLReader() throws SAXException, ParserConfigurationException {
SAXParserFactoryImpl xerces = new org.apache.xerces.jaxp.SAXParserFactoryImpl();
xerces.setNamespaceAware(true);
return xerces.newSAXParser().getXMLReader();
}
private static String getParserVersion() {
return org.apache.xerces.impl.Version.getVersion();
}
private static File createNewFile() throws IOException {
File f = File.createTempFile("TestOxygen", ".xml");
f.deleteOnExit();
List<String> lines = Arrays.asList("<someXML/>");
Files.write(f.toPath(), lines, StandardCharsets.UTF_8, StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING);
return f;
}
/**
* @see ro.sync.exml.plugin.workspace.WorkspaceAccessPluginExtension#applicationClosing()
*/
@Override
public boolean applicationClosing() {
// You can reject the application closing here
return true;
}
}