All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.dbrain.binder.system.app.AppImpl Maven / Gradle / Ivy

There is a newer version: 0.13
Show newest version
/*
 * Copyright [2015] [Eric Poitras]
 *
 *     Licensed under the Apache License, Version 2.0 (the "License");
 *     you may not use this file except in compliance with the License.
 *     You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 *     Unless required by applicable law or agreed to in writing, software
 *     distributed under the License is distributed on an "AS IS" BASIS,
 *     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *     See the License for the specific language governing permissions and
 *     limitations under the License.
 */

package org.dbrain.binder.system.app;

import org.dbrain.binder.app.App;
import org.dbrain.binder.app.Binder;
import org.dbrain.binder.app.Module;
import org.dbrain.binder.directory.Qualifiers;
import org.dbrain.binder.directory.ServiceKey;
import org.dbrain.binder.system.http.server.HttpStandardScopeComponent;
import org.dbrain.binder.system.http.webapp.WebAppComponent;
import org.dbrain.binder.system.lifecycle.BaseClassAnalyzer;
import org.dbrain.binder.system.scope.StandardScopeComponent;
import org.dbrain.binder.system.txs.TransactionComponent;
import org.dbrain.binder.system.util.AnnotationBuilder;
import org.glassfish.hk2.api.MultiException;
import org.glassfish.hk2.api.ServiceLocatorFactory;
import org.glassfish.hk2.utilities.ServiceLocatorUtilities;

import javax.inject.Named;
import java.lang.annotation.Annotation;
import java.util.List;
import java.util.Objects;
import java.util.UUID;

/**
 * Created by epoitras on 3/4/15.
 */
public class AppImpl implements App {

    private static final ServiceLocatorFactory serviceLocatorFactory = ServiceLocatorFactory.getInstance();

    private final String                               name;
    private final org.glassfish.hk2.api.ServiceLocator delegate;
    private final ThreadLocal currentBinder = new ThreadLocal<>();

    public AppImpl() {
        this( UUID.randomUUID().toString() );
    }

    // TODO @epoitras Does not works in a "multi-threaded" concurrent scenario.
    public AppImpl( String name ) {
        this.name = name;
        this.delegate = serviceLocatorFactory.create( name );

        ServiceLocatorUtilities.addClasses( delegate, BaseClassAnalyzer.class );
        delegate.setDefaultClassAnalyzerName( BaseClassAnalyzer.BINDER_ANALYZER_NAME );
        ServiceLocatorUtilities.addOneConstant( delegate, this );

        configure( binder -> binder.bind( SimpleBindingContext.class ) //
                           .to( Binder.BindingContext.class ) //
                           .to( SimpleBindingContext.class ) //
                           .providedBy( () -> currentBinder.get().getBindingContext() ) );

        ServiceLocatorUtilities.enablePerThreadScope( delegate );

        configure( binder -> {
            binder.bindComponent( TransactionComponent.class );
            binder.bindComponent( StandardScopeComponent.class );
        } );

        configure( binder -> {
            binder.bindComponent( HttpStandardScopeComponent.class );
            binder.bindComponent( WebAppComponent.class );
        } );

    }

    /**
     * @return The name of the application.
     */
    @Override
    public String getName() {
        return name;
    }

    @Override
    public void configure( Module configurator ) {
        try {
            SimpleBinder binder = startConfiguration();
            configurator.configure( binder );
            commitConfiguration();
        } catch ( Exception e ) {
            throw new MultiException( e );
        }
    }

    @Override
    public void configure( Class ... modules ) {
        for ( Class module: modules ) {
            configure( getOrCreateInstance( module ) );
        }
    }

    /**
     * @return Start a new session of configuration.
     */
    private SimpleBinder startConfiguration() {
        if ( currentBinder.get() != null ) {
            throw new IllegalStateException( "Cannot configure twice on the same thread at the same time." );
        }
        currentBinder.set( new SimpleBinder( this, new SimpleBindingContext() ) );
        return currentBinder.get();
    }

    private void commitConfiguration() {
        if ( currentBinder.get() == null ) {
            throw new IllegalStateException( "No configuration to commit." );
        }
        try {
            currentBinder.get().commit();
        } finally {
            currentBinder.set( null );
        }
    }

    @Override
    public  T locate( Class serviceClass ) {
        return delegate.getService( serviceClass );
    }

    @Override
    public  T locate( Class serviceClass, String name ) {
        return delegate.getService( serviceClass, name );
    }

    @Override
    public  T locate( Class serviceClass, Class qualifier ) {
        return delegate.getService( serviceClass, AnnotationBuilder.of( qualifier ) );
    }

    @Override
    public  T locate( ServiceKey serviceKey ) {
        Qualifiers qualifiers = serviceKey.getQualifiers();
        T result;
        if ( qualifiers.size() > 0 ) {
            result = delegate.getService( serviceKey.getServiceType(), qualifiers.toArray() );
        } else {
            result = delegate.getService( serviceKey.getServiceType() );
        }
        return result;
    }

    @Override
    public  T locate( Class serviceClass, Qualifiers qualifiers ) {
        T result;
        if ( qualifiers.size() > 0 ) {
            result = delegate.getService( serviceClass, qualifiers.toArray() );
        } else {
            result = delegate.getService( serviceClass );
        }
        return result;
    }

    @Override
    public  T getInstance( Class serviceClass ) {
        T result = locate( serviceClass );
        Objects.requireNonNull( result,
                                "Service of class " + serviceClass.getName() + " is not found in application " + getName() + "." );
        return result;
    }

    @Override
    public  T getInstance( Class serviceClass, String name ) {
        T result = locate( serviceClass, name );
        Objects.requireNonNull( result,
                                "Service of class " + serviceClass.getName() + " is not found in application " + getName() + "." );
        return result;
    }

    @Override
    public  T getInstance( Class serviceClass, Class qualifier ) {
        T result = locate( serviceClass, qualifier );
        Objects.requireNonNull( result,
                                "Service of class " + serviceClass.getName() + " is not found in application " + getName() + "." );
        return result;
    }

    @Override
    public  T getInstance( ServiceKey serviceKey ) {
        T result = locate( serviceKey );
        Objects.requireNonNull( result,
                                "Service of class " + serviceKey.getServiceType() + " is not found in application " + getName() + "." );
        return result;
    }

    @Override
    public  T getInstance( Class serviceClass, Qualifiers qualifiers ) {
        T result = locate( serviceClass, qualifiers );
        Objects.requireNonNull( result,
                                "Service of class " + serviceClass + " is not found in application " + getName() + "." );
        return result;
    }

    @Override
    public  T getOrCreateInstance( Class serviceClass ) {
        return getOrCreateInstance( ServiceKey.of( serviceClass ) );
    }

    @Override
    public  T getOrCreateInstance( ServiceKey serviceKey ) {
        T result = locate( serviceKey );

        // Use the Jit path only for unqualified services
        if ( result == null && serviceKey.getQualifiers().size() == 0 ) {
            result = delegate.createAndInitialize( serviceKey.getServiceClass() );
        }
        Objects.requireNonNull( result,
                                "Cannot create instance of " + serviceKey.getServiceClass()
                                                                         .getName() + " using application " + getName() + "." );
        return result;
    }

    @Override
    public  List listServices( Class serviceClass ) {
        return delegate.getAllServices( serviceClass );
    }

    @Override
    public  List listServices( Class serviceClass, String name ) {
        return delegate.getAllServices( serviceClass, AnnotationBuilder.of( Named.class, name ) );
    }

    @Override
    public  List listServices( Class serviceClass, Class qualifier ) {
        return delegate.getAllServices( serviceClass, AnnotationBuilder.of( qualifier ) );
    }

    @Override
    public  List listServices( Class serviceClass, Qualifiers qualifiers ) {
        return delegate.getAllServices( serviceClass, qualifiers.toArray() );
    }

    @Override
    public void close() throws Exception {
        delegate.shutdown();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy