users@jaxb.java.net

Re: Plugin problem

From: Aleksei Valikov <valikov_at_gmx.net>
Date: Wed, 17 Aug 2005 10:58:50 +0200

Hi.

> I have a problem to integrate a plugin with JAXB 2.0. It is a very simple
> plugin which does nothing. Problem is xjc doesn't instanciate it.
> I put my plugin in a separated jar and launch xjc with the command line :
> java -Dcom.sun.tools.xjc.Options.findServices=true -classpath
> "jaxb-ri-20050815\lib\jaxb-xjc.jar;plug.jar" com.sun.tools.xjc.XJCFacade
>
> I got the error :
> java.lang.ArrayStoreException
> at java.lang.System.arraycopy(Native Method)
> at java.util.ArrayList.toArray(ArrayList.java:305)
> at com.sun.tools.xjc.Options.findServices(Options.java:590)
> at com.sun.tools.xjc.Options.findServices(Options.java:527)
>
> I looked at the sources, and it seems there is a problem with classloaders,
> the Plugin class is loaded two times.

I've also had problems with classloaders when writing plugins for jaxb2.

> Then I looked in the mailing list and found, somebody already had this
> problem and solved it.
> However I don't know what to do !

As far as I remember, I've fixed the classloaders somehow... But I can't
tell you what exactly I did. Try searching the mailing list archieve, I
must have reported the solution.

> I tried to put my plugin directly into jaxb-xjc.jar with standard plugins.
> I thought only one Classloader would be used.
> But I still have the error !
>
> What is the standard way to add a plugin ? Is there any example (which does
> not use Ant task) ?

I've attached the base test case I used to test plugins with JAXB 2.0.
You only need to implement newPlugin() method.

Hope it helps.

ps. I think we really need jaxbcommons2. Seems like more people are
attracted by plugins in jaxb2.

Bye.
/lexi


package org.jvnet.hyperjaxb.plugin.tests;

import java.io.File;
import java.io.FileFilter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import junit.framework.TestCase;

import org.apache.commons.io.filefilter.SuffixFileFilter;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.sun.tools.xjc.Driver;
import com.sun.tools.xjc.Options;
import com.sun.tools.xjc.Plugin;

/**
 * Abstract test for plugins.
 *
 * @author Aleksei Valikov
 */
public abstract class AbstractPluginTest extends TestCase{
        
        /**
         * Logger.
         */
        protected Log log = LogFactory.getLog(AbstractPluginTest.class);
        
        /**
         * Plugin.
         */
        protected Plugin plugin;

        /**
         * Constructs a new test case.
         *
         * @param name
         * test name.
         */
        public AbstractPluginTest(final String name) {
                super(name);
        }

        /**
         * Test setup.
         *
         * @throws Exception
         * In case of setup problems.
         */
        public void setUp() throws Exception {
                super.setUp();
                plugin = newPlugin();
        }

        /**
         * Returns command-line arguments for XJC invocation. This array will be
         * constructed of what {_at_link #getOptions()},{_at_link #getBindingOptions()},
         * {_at_link #getAddonOptions()}and {_at_link #getSchemaOptions()}return.
         *
         * @return Command-line arguments for XJC invocation.
         */
        public String[] getArguments() {
                final List<String> options = getOptions();
                final List<String> bindingOptions = getBindingOptions();
                final List<String> addonOptions = getAddonOptions();
                final List<String> schemaOptions = getSchemaOptions();

                final List<String> args = new ArrayList<String>();
                
                args.addAll(options);
                args.addAll(bindingOptions);
                args.addAll(addonOptions);
                args.addAll(schemaOptions);
                return (String[]) args.toArray(new String[]{});
        }

        /**
         * Returns command-line options for the add-on.
         *
         * @return Command line options for the add-on.
         */
        public List<String> getOptions() {
                return Arrays.asList(new String[] { "-d", getGeneratedSourcesDir().getAbsolutePath() });
        }
        
        protected boolean isDebug()
        {
                return true;
        }

        protected boolean isNv()
        {
                return true;
        }

        protected boolean isExtension()
        {
                return true;
        }
/**
         * Returns a string array of add-on command-line options.
         *
         * @return Command-line options for the add-on.
         */
        public List<String> getAddonOptions()
        {
                final List<String> addonOptions = new ArrayList<String>();
                if (isDebug())
                        addonOptions.add("-debug");
                if (isNv())
                        addonOptions.add("-nv");
                if (isExtension())
                        addonOptions.add("-extension");
                addonOptions.add("-" + plugin.getOptionName());
                return addonOptions;
        }
        

        /**
         * Returns schema options.
         *
         * @return Schema options.
         */
        public List<String> getSchemaOptions() {
                final File[] schemaFiles = getSchemaFiles();
                final List<String> schemaOptions = new ArrayList<String>(schemaFiles.length);
                for (int index = 0; index < schemaFiles.length; index++) {
                        final File schemaFile = schemaFiles[index];
                        schemaOptions.add(schemaFile.getAbsolutePath());
                }
                return schemaOptions;
        }
        
        public File getSchemaDirectory()
        {
                return new File("schema");
        }

        /**
         * Returns an array of schema files.
         *
         * @return Array of schema files.
         */
        public File[] getSchemaFiles() {
                
                final FileFilter fileFilter = new SuffixFileFilter(".xsd");
                return getSchemaDirectory().listFiles(fileFilter);
        }
        
        public File getBindingDirectory()
        {
                return new File("binding");
    }

        /**
         * Returns an array of binding files.
         *
         * @return An array of binding files.
         */
        public File[] getBindingFiles() {
                final FileFilter fileFilter = new SuffixFileFilter(".xml");
                return getBindingDirectory().listFiles(fileFilter);
        }

        /**
         * Binding options.
         *
         * @return Binding options.
         */
        public List<String> getBindingOptions() {
                final File[] bindingFiles = getBindingFiles();
                final List<String> bindingOptions = new ArrayList<String>();
                if (null != bindingFiles && bindingFiles.length > 0) {
                        bindingOptions.add("-b");
                        for (int index = 0; index < bindingFiles.length; index++) {
                                final File bindingFile = bindingFiles[index];
                                bindingOptions.add(bindingFile.getAbsolutePath());
                        }
                }
                return bindingOptions;
        }

        /**
         * Directory where the sources will be generated.
         *
         * @return "Generated sources" directory.
         */
        public File getGeneratedSourcesDir() {
                final File generatedSourcesDir = new File("generated.src");
                if (!generatedSourcesDir.exists()) {
                        generatedSourcesDir.mkdirs();
                }
                return generatedSourcesDir;
        }
        
        protected abstract Plugin newPlugin();

        /**
         * Runs the test.
         *
         * @throws Exception
         * In case a problem occurs during running the test.
         */
        public void testRun() throws Exception {
                try {
                        Options.allPlugins.add(plugin);
                        Driver.run(getArguments(), System.out, System.err);
                } catch (Exception ex) {
                        ex.printStackTrace();
                        throw ex;
                }
        }
}