Package org.uberfire.backend.server.cdi

Source Code of org.uberfire.backend.server.cdi.SystemConfigProducer

package org.uberfire.backend.server.cdi;

import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.net.URI;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.context.spi.CreationalContext;
import javax.enterprise.event.Observes;
import javax.enterprise.inject.Any;
import javax.enterprise.inject.Default;
import javax.enterprise.inject.spi.AfterBeanDiscovery;
import javax.enterprise.inject.spi.AfterDeploymentValidation;
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.BeanManager;
import javax.enterprise.inject.spi.Extension;
import javax.enterprise.inject.spi.InjectionPoint;
import javax.enterprise.inject.spi.InjectionTarget;
import javax.enterprise.inject.spi.ProcessAnnotatedType;
import javax.enterprise.inject.spi.ProcessBean;
import javax.enterprise.util.AnnotationLiteral;
import javax.inject.Named;
import javax.inject.Singleton;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.uberfire.commons.cluster.ClusterServiceFactory;
import org.uberfire.commons.services.cdi.Startable;
import org.uberfire.commons.services.cdi.Startup;
import org.uberfire.commons.services.cdi.StartupType;
import org.uberfire.commons.services.cdi.Veto;
import org.uberfire.io.IOService;
import org.uberfire.io.impl.IOServiceNio2WrapperImpl;
import org.uberfire.io.impl.cluster.IOServiceClusterImpl;
import org.uberfire.java.nio.IOException;
import org.uberfire.java.nio.base.FileSystemState;
import org.uberfire.java.nio.file.FileStore;
import org.uberfire.java.nio.file.FileSystem;
import org.uberfire.java.nio.file.FileSystemAlreadyExistsException;
import org.uberfire.java.nio.file.InvalidPathException;
import org.uberfire.java.nio.file.Path;
import org.uberfire.java.nio.file.PathMatcher;
import org.uberfire.java.nio.file.PatternSyntaxException;
import org.uberfire.java.nio.file.WatchService;
import org.uberfire.java.nio.file.attribute.UserPrincipalLookupService;
import org.uberfire.java.nio.file.spi.FileSystemProvider;

public class SystemConfigProducer implements Extension {

    private static final Logger logger = LoggerFactory.getLogger( SystemConfigProducer.class );

    private static final String CDI_METHOD = "cdi";

    private static final String START_METHOD = System.getProperty( "org.uberfire.start.method", "cdi" );

    private final List<OrderedBean> startupEagerBeans = new LinkedList<OrderedBean>();
    private final List<OrderedBean> startupBootstrapBeans = new LinkedList<OrderedBean>();

    private final Comparator<OrderedBean> priorityComparator = new Comparator<OrderedBean>() {
        @Override
        public int compare( final OrderedBean o1,
                            final OrderedBean o2 ) {
            return o1.priority - o2.priority;
        }
    };

    public <X> void processBean( @Observes final ProcessBean<X> event ) {
        if ( event.getAnnotated().isAnnotationPresent( Startup.class ) && ( event.getAnnotated().isAnnotationPresent( ApplicationScoped.class )
                || event.getAnnotated().isAnnotationPresent( Singleton.class ) ) ) {
            final Startup startupAnnotation = event.getAnnotated().getAnnotation( Startup.class );
            final StartupType type = startupAnnotation.value();
            final int priority = startupAnnotation.priority();
            final Bean<?> bean = event.getBean();
            switch ( type ) {
                case EAGER:
                    startupEagerBeans.add( new OrderedBean( bean,
                                                            priority ) );
                    break;
                case BOOTSTRAP:
                    startupBootstrapBeans.add( new OrderedBean( bean,
                                                                priority ) );
                    break;
            }
        } else if ( event.getAnnotated().isAnnotationPresent( Named.class ) && ( event.getAnnotated().isAnnotationPresent( ApplicationScoped.class )
                || event.getAnnotated().isAnnotationPresent( Singleton.class ) ) ) {
            final Named namedAnnotation = event.getAnnotated().getAnnotation( Named.class );

            if (namedAnnotation.value().endsWith("-startable")) {
                final Bean<?> bean = event.getBean();
                startupBootstrapBeans.add( new OrderedBean( bean, 10 ) );
            }
        }
    }

    public void afterDeploymentValidation( final @Observes AfterDeploymentValidation event,
                                           final BeanManager manager ) {
        if (CDI_METHOD.equalsIgnoreCase(START_METHOD)) {
            //Force execution of Bootstrap bean's @PostConstruct methods first
            runPostConstruct( manager,
                              startupBootstrapBeans );

            //Followed by execution of remaining Eager bean's @PostConstruct methods
            runPostConstruct( manager,
                          startupEagerBeans );
        }
    }

    private void runPostConstruct( final BeanManager manager,
                                   final List<OrderedBean> orderedBeans ) {
        //Sort first, by priority
        Collections.sort( orderedBeans,
                          priorityComparator );
        for ( OrderedBean ob : orderedBeans ) {
            // the call to toString() is a cheat to force the bean to be initialized
            final Bean<?> bean = ob.bean;
            manager.getReference( bean,
                                  bean.getBeanClass(),
                                  manager.createCreationalContext( bean ) ).toString();
        }
    }

    private class OrderedBean {

        Bean<?> bean;
        int priority;

        private OrderedBean( final Bean<?> bean,
                             final int priority ) {
            this.bean = bean;
            this.priority = priority;
        }
    }

    <T> void processAnnotatedType( @Observes ProcessAnnotatedType<T> pat ) {
        if ( pat.getAnnotatedType().isAnnotationPresent( Veto.class ) ) {
            pat.veto();
        }
    }

    void afterBeanDiscovery( @Observes final AfterBeanDiscovery abd,
                             final BeanManager bm ) {

        final boolean systemFSNotExists = bm.getBeans( "systemFS" ).isEmpty();

        if ( systemFSNotExists ) {
            buildSystemFS( abd, bm );
        }

        final boolean ioStrategyBeanNotFound = bm.getBeans( "ioStrategy" ).isEmpty();

        if ( ioStrategyBeanNotFound ) {
            buildIOStrategy( abd, bm );
        }

        if (!CDI_METHOD.equalsIgnoreCase(START_METHOD)) {
            buildStartableBean(abd, bm);
        }
    }

    private void buildSystemFS( final AfterBeanDiscovery abd,
                                final BeanManager bm ) {
        final InjectionTarget<DummyFileSystem> it = bm.createInjectionTarget( bm.createAnnotatedType( DummyFileSystem.class ) );

        abd.addBean( new Bean<FileSystem>() {

            @Override
            public Class<?> getBeanClass() {
                return FileSystem.class;
            }

            @Override
            public Set<InjectionPoint> getInjectionPoints() {
                return it.getInjectionPoints();
            }

            @Override
            public String getName() {
                return "systemFS";
            }

            @Override
            public Set<Annotation> getQualifiers() {

                return new HashSet<Annotation>() {{
                    add( new AnnotationLiteral<Default>() {
                    } );
                    add( new AnnotationLiteral<Any>() {
                    } );
                    add( new NamedLiteral( "systemFS" ) );
                }};
            }

            @Override
            public Class<? extends Annotation> getScope() {
                return ApplicationScoped.class;
            }

            @Override
            public Set<Class<? extends Annotation>> getStereotypes() {
                return Collections.emptySet();
            }

            @Override
            public Set<Type> getTypes() {
                return new HashSet<Type>() {{
                    add( FileSystem.class );
                    add( Object.class );
                }};
            }

            @Override
            public boolean isAlternative() {
                return false;
            }

            @Override
            public boolean isNullable() {
                return false;
            }

            @Override
            public FileSystem create( CreationalContext<FileSystem> ctx ) {
                final Bean<IOService> bean = (Bean<IOService>) bm.getBeans( "configIO" ).iterator().next();
                final CreationalContext<IOService> _ctx = bm.createCreationalContext( bean );
                final IOService ioService = (IOService) bm.getReference( bean, IOService.class, _ctx );

                FileSystem systemFS;
                try {
                    systemFS = ioService.newFileSystem( URI.create( "git://system" ),
                                                        new HashMap<String, Object>() {{
                                                            put( "init", Boolean.TRUE );
                                                        }} );
                } catch ( FileSystemAlreadyExistsException e ) {
                    systemFS = ioService.getFileSystem( URI.create( "git://system" ) );
                }

                return systemFS;
            }

            @Override
            public void destroy( final FileSystem instance,
                                 final CreationalContext<FileSystem> ctx ) {
                try {
                    instance.dispose();
                } catch ( final Exception ex ) {
                    logger.warn( ex.getMessage(), ex );
                }
                ctx.release();
            }
        } );
    }

    private void buildIOStrategy( final AfterBeanDiscovery abd,
                                  final BeanManager bm ) {

        final InjectionTarget<IOServiceNio2WrapperImpl> it = bm.createInjectionTarget( bm.createAnnotatedType( IOServiceNio2WrapperImpl.class ) );

        abd.addBean( new Bean<IOService>() {

            @Override
            public Class<?> getBeanClass() {
                return IOService.class;
            }

            @Override
            public Set<InjectionPoint> getInjectionPoints() {
                return it.getInjectionPoints();
            }

            @Override
            public String getName() {
                return "ioStrategy";
            }

            @Override
            public Set<Annotation> getQualifiers() {

                return new HashSet<Annotation>() {{
                    add( new AnnotationLiteral<Default>() {
                    } );
                    add( new AnnotationLiteral<Any>() {
                    } );
                    add( new NamedLiteral( "ioStrategy" ) );
                }};
            }

            @Override
            public Class<? extends Annotation> getScope() {
                return ApplicationScoped.class;
            }

            @Override
            public Set<Class<? extends Annotation>> getStereotypes() {
                return Collections.emptySet();
            }

            @Override
            public Set<Type> getTypes() {
                return new HashSet<Type>() {{
                    add( IOService.class );
                    add( Object.class );
                }};
            }

            @Override
            public boolean isAlternative() {
                return false;
            }

            @Override
            public boolean isNullable() {
                return false;
            }

            @Override
            public IOService create( CreationalContext<IOService> ctx ) {

                final Bean<ClusterServiceFactory> clusterFactoryBean = (Bean<ClusterServiceFactory>) bm.getBeans( "clusterServiceFactory" ).iterator().next();
                final CreationalContext<ClusterServiceFactory> _ctx = bm.createCreationalContext( clusterFactoryBean );
                final ClusterServiceFactory clusterServiceFactory = (ClusterServiceFactory) bm.getReference( clusterFactoryBean, ClusterServiceFactory.class, _ctx );

                final IOService result;

                if ( clusterServiceFactory == null ) {
                    result = new IOServiceNio2WrapperImpl();
                } else {
                    result = new IOServiceClusterImpl( new IOServiceNio2WrapperImpl(), clusterServiceFactory );
                }

                return result;
            }

            @Override
            public void destroy( final IOService instance,
                                 final CreationalContext<IOService> ctx ) {
                instance.dispose();
                ctx.release();
            }
        } );
    }

    private void buildStartableBean( final AfterBeanDiscovery abd,
            final BeanManager bm ) {

        abd.addBean( new Bean<Startable>() {

            @Override
            public Class<?> getBeanClass() {
                return Startable.class;
            }

            @Override
            public Set<InjectionPoint> getInjectionPoints() {
                return Collections.emptySet();
            }

            @Override
            public String getName() {
                return "startablebean";
            }

            @Override
            public Set<Annotation> getQualifiers() {

                return new HashSet<Annotation>() {{
                    add( new AnnotationLiteral<Default>() {
                    } );
                    add( new AnnotationLiteral<Any>() {
                    } );
                }};
            }

            @Override
            public Class<? extends Annotation> getScope() {
                return ApplicationScoped.class;
            }

            @Override
            public Set<Class<? extends Annotation>> getStereotypes() {
                return Collections.emptySet();
            }

            @Override
            public Set<Type> getTypes() {
                return new HashSet<Type>() {{
                    add( Startable.class );
                    add( Object.class );
                }};
            }

            @Override
            public boolean isAlternative() {
                return false;
            }

            @Override
            public boolean isNullable() {
                return false;
            }

            @Override
            public Startable create( CreationalContext<Startable> ctx ) {


                return new Startable() {
                    @Override
                    public int hashCode() {
                        return super.hashCode();
                    }

                    @Override
                    public void start() {
                        //Force execution of Bootstrap bean's @PostConstruct methods first
                        runPostConstruct( bm,
                                startupBootstrapBeans );

                        //Followed by execution of remaining Eager bean's @PostConstruct methods
                        runPostConstruct( bm,
                                startupEagerBeans );
                    }
                };
            }

            @Override
            public void destroy( final Startable instance,
                    final CreationalContext<Startable> ctx ) {

                ctx.release();
            }
        } );
    }

    public static class DummyFileSystem implements FileSystem {

        private FileSystemState state = FileSystemState.NORMAL;

        @Override
        public FileSystemProvider provider() {
            return null;
        }

        @Override
        public boolean isOpen() {
            return false;
        }

        @Override
        public boolean isReadOnly() {
            return false;
        }

        @Override
        public String getSeparator() {
            return null;
        }

        @Override
        public Iterable<Path> getRootDirectories() {
            return null;
        }

        @Override
        public Iterable<FileStore> getFileStores() {
            return null;
        }

        @Override
        public Set<String> supportedFileAttributeViews() {
            return null;
        }

        @Override
        public Path getPath( String first,
                             String... more ) throws InvalidPathException {
            return null;
        }

        @Override
        public PathMatcher getPathMatcher( String syntaxAndPattern ) throws IllegalArgumentException, PatternSyntaxException, UnsupportedOperationException {
            return null;
        }

        @Override
        public UserPrincipalLookupService getUserPrincipalLookupService() throws UnsupportedOperationException {
            return null;
        }

        @Override
        public WatchService newWatchService() throws UnsupportedOperationException, IOException {
            return null;
        }

        @Override
        public void close() throws IOException {

        }

        @Override
        public void dispose() {

        }
    }

    private class DummyStarable implements Startable {

        @Override
        public void start() {

        }
    }

    public class NamedLiteral extends AnnotationLiteral<Named> implements Named {

        private final String value;

        public String value() {
            return value;
        }

        public NamedLiteral( String value ) {
            this.value = value;
        }

    }
}
TOP

Related Classes of org.uberfire.backend.server.cdi.SystemConfigProducer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.