Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

EditorLoader in crest main #11

Closed
rmannibucau opened this issue May 9, 2014 · 3 comments
Closed

EditorLoader in crest main #11

rmannibucau opened this issue May 9, 2014 · 3 comments

Comments

@rmannibucau
Copy link
Contributor

With crest you often need custom editors. When using xbean would be gret to get them loaded automatically. I used this code to do so (side note: I didnt check xbean was really optional so something to do before including it blindly - same loader system as for scanning could be used btw):

@Retention(RUNTIME)
@Target(TYPE)
public @interface Editor {
    Class<?> value();
}
import java.beans.PropertyEditorManager;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.util.ServiceLoader;

import org.apache.xbean.finder.Annotated;
import org.apache.xbean.finder.AnnotationFinder;
import org.apache.xbean.finder.UrlSet;
import org.apache.xbean.finder.archive.Archive;
import org.apache.xbean.finder.archive.ClasspathArchive;
import org.apache.xbean.finder.archive.CompositeArchive;
import org.tomitribe.util.JarLocation;

public class EditorLoader {
    static {
        try {
            new XBeanLoader().load();
        } catch (final Throwable skip) {
            // no-op
        }
        for (final Editor editor : ServiceLoader.load(Editor.class)) // class MyEditor extends AbstractConverter implements Editor
        {
            try {
                PropertyEditorManager.registerEditor(editor.value(), editor.getClass());
            } catch (final Exception e) {
                // no-op
            }
        }
    }

    public static void load() {
        // no-op
    }

    private static Archive thisArchive() {
        try {
            final Class<?> reference = EditorLoader.class;

            final File file = JarLocation.jarLocation(reference);
            return ClasspathArchive.archive(reference.getClassLoader(), file.toURI().toURL());
        } catch (final MalformedURLException e) {
            throw new IllegalStateException(e);
        }
    }

    private static Archive cpArchive() {
        try {
            final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
            return new ClasspathArchive(
                    classLoader,
                    new UrlSet(classLoader).excludeJvm().exclude(classLoader.getParent()).getUrls());
        } catch (final IOException e) {
            throw new IllegalStateException(e);
        }
    }

    // just allow lazy loading and avoid issues if XBean is not here
    private static class XBeanLoader {
        public void load() {
            final AnnotationFinder finder = new AnnotationFinder(new CompositeArchive(thisArchive(), cpArchive())).enableFindSubclasses();
            for (final Annotated<Class<?>> clazz : finder.findMetaAnnotatedClasses(Editor.class)) {
                PropertyEditorManager.registerEditor(clazz.getAnnotation(Editor.class).value(), clazz.get());
            }
        }
    }
}

and I wrapped crest main:

// just a wrapper to get custom editors
public class Main {
    public static void main(final String[] args) throws Exception {
        EditorLoader.load();
        org.tomitribe.crest.Main.main(args);
    }

    private Main() {
        // no-op
    }
}

Then to write a custom editor you just need to either decorate it with @Editor(editorClassKey) or without XBean also implement Editor (to use ServiceLoader - note this part could be removed and if we have a EditorLoader just use it to list editor classes with @Editor annotation which would be easier and more consistent).

@jeanouii
Copy link
Member

jeanouii commented May 9, 2014

Committed that way for now.

@jeanouii jeanouii closed this as completed May 9, 2014
@dblevins
Copy link
Member

dblevins commented May 9, 2014

Curious what pattern you're using that doesn't fit into "new Foo(String)" or the "Foo Foo.get(String)" patterns. Needing an editor should be the uncommon case.

On May 9, 2014, at 12:03 AM, Romain Manni-Bucau notifications@github.com wrote:

With crest you often need custom editors. When using xbean would be gret to get them loaded automatically. I used this code to do so (side note: I didnt check xbean was really optional so something to do before including it blindly - same loader system as for scanning could be used btw):

import java.beans.PropertyEditorManager;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.util.ServiceLoader;

import org.apache.xbean.finder.Annotated;
import org.apache.xbean.finder.AnnotationFinder;
import org.apache.xbean.finder.UrlSet;
import org.apache.xbean.finder.archive.Archive;
import org.apache.xbean.finder.archive.ClasspathArchive;
import org.apache.xbean.finder.archive.CompositeArchive;
import org.tomitribe.util.JarLocation;

public class EditorLoader {

static {

try {

new XBeanLoader().load();

} catch (final Throwable skip) {

// no-op

}

for (final Editor editor : ServiceLoader.load(Editor.class)) // class MyEditor extends AbstractConverter implements Editor

{

try {

PropertyEditorManager.registerEditor(editor.value(), editor.getClass());

} catch (final Exception e) {

// no-op

}

}

}

public static void load() {

// no-op

}

private static Archive thisArchive() {

try {

final Class<?> reference = EditorLoader.class;

final File file = JarLocation.jarLocation(reference);

return ClasspathArchive.archive(reference.getClassLoader(), file.toURI().toURL());

} catch (final MalformedURLException e) {

throw new IllegalStateException(e);

}

}

private static Archive cpArchive() {

try {

final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();

return new ClasspathArchive(

classLoader,

new UrlSet(classLoader).excludeJvm().exclude(classLoader.getParent()).getUrls());

} catch (final IOException e) {

throw new IllegalStateException(e);

}

}

// just allow lazy loading and avoid issues if XBean is not here

private static class XBeanLoader {

public void load() {

final AnnotationFinder finder = new AnnotationFinder(new CompositeArchive(thisArchive(), cpArchive())).enableFindSubclasses();

for (final Annotated<Class<?>> clazz : finder.findMetaAnnotatedClasses(Editor.class)) {

PropertyEditorManager.registerEditor(clazz.getAnnotation(Editor.class).value(), clazz.get());

}

}

}
}

and I wrapped crest main:

// just a wrapper to get custom editors
public class Main {

public static void main(final String[] args) throws Exception {

EditorLoader.load();

org.tomitribe.crest.Main.main(args);

}

private Main() {

// no-op

}
}
Then to write a custom editor you just need to either decorate it with @Editor(editorClassKey) or without XBean also implement Editor (to use ServiceLoader - note this part could be removed and if we have a EditorLoader just use it to list editor classes with @Editor annotation which would be easier and more consistent).


Reply to this email directly or view it on GitHub.

@rmannibucau
Copy link
Contributor Author

Well issue is more about Editors I want to override. Date or File ones for instance.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants