Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id 92C7A200BED for ; Sat, 17 Dec 2016 11:27:42 +0100 (CET) Received: by cust-asf.ponee.io (Postfix) id 90BF6160B38; Sat, 17 Dec 2016 10:27:42 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id 316B6160B3B for ; Sat, 17 Dec 2016 11:27:40 +0100 (CET) Received: (qmail 22271 invoked by uid 500); 17 Dec 2016 10:27:39 -0000 Mailing-List: contact commits-help@zest.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@zest.apache.org Delivered-To: mailing list commits@zest.apache.org Received: (qmail 21921 invoked by uid 99); 17 Dec 2016 10:27:38 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Sat, 17 Dec 2016 10:27:38 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 2B401DFB8A; Sat, 17 Dec 2016 10:27:38 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: niclas@apache.org To: commits@zest.apache.org Date: Sat, 17 Dec 2016 10:27:46 -0000 Message-Id: <500805ca776546e18942b774d3fa82d6@git.apache.org> In-Reply-To: <2bda02e69e814fefafe6dd5d8de262bd@git.apache.org> References: <2bda02e69e814fefafe6dd5d8de262bd@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [10/81] [abbrv] [partial] zest-java git commit: ZEST-195 ; Replace all "zest" with "polygene" archived-at: Sat, 17 Dec 2016 10:27:42 -0000 http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/entity/EntityMixinsModel.java ---------------------------------------------------------------------- diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/entity/EntityMixinsModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/entity/EntityMixinsModel.java new file mode 100644 index 0000000..6993b6f --- /dev/null +++ b/core/runtime/src/main/java/org/apache/polygene/runtime/entity/EntityMixinsModel.java @@ -0,0 +1,117 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.polygene.runtime.entity; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; +import org.apache.polygene.api.composite.CompositeInstance; +import org.apache.polygene.api.entity.Lifecycle; +import org.apache.polygene.api.entity.LifecycleException; +import org.apache.polygene.api.property.StateHolder; +import org.apache.polygene.bootstrap.BindingException; +import org.apache.polygene.runtime.composite.MixinModel; +import org.apache.polygene.runtime.composite.MixinsModel; +import org.apache.polygene.runtime.composite.UsesInstance; +import org.apache.polygene.runtime.injection.InjectionContext; +import org.apache.polygene.runtime.model.Resolution; + +/** + * JAVADOC + */ +public final class EntityMixinsModel + extends MixinsModel +{ + List lifecycleMixins; + + @Override + public void bind( Resolution resolution ) + throws BindingException + { + super.bind( resolution ); + + // Find what mixins implement Lifecycle + for( int i = 0; i < mixinModels.size(); i++ ) + { + MixinModel mixinModel = mixinModels.get( i ); + if( Lifecycle.class.isAssignableFrom( mixinModel.mixinClass() ) ) + { + if( lifecycleMixins == null ) + { + lifecycleMixins = new ArrayList(); + } + + lifecycleMixins.add( i ); + } + } + } + + public Object newMixin( EntityInstance entityInstance, StateHolder state, Object[] mixins, Method method ) + { + MixinModel model = methodImplementation.get( method ); + InjectionContext injectionContext = new InjectionContext( entityInstance, UsesInstance.EMPTY_USES, state ); + Object mixin = model.newInstance( injectionContext ); + mixins[ methodIndex.get( method ) ] = mixin; + return mixin; + } + + public void invokeLifecycle( boolean create, Object[] mixins, CompositeInstance instance, StateHolder state ) + { + if( lifecycleMixins != null ) + { + InjectionContext injectionContext = new InjectionContext( instance, UsesInstance.EMPTY_USES, state ); + for( Integer lifecycleMixin : lifecycleMixins ) + { + Lifecycle lifecycle = (Lifecycle) mixins[ lifecycleMixin ]; + + if( lifecycle == null ) + { + lifecycle = (Lifecycle) mixinModels.get( lifecycleMixin ).newInstance( injectionContext ); + } + + if( create ) + { + try + { + lifecycle.create(); + } + catch( Exception ex ) + { + String message = "Unable to invoke create lifecycle on " + lifecycle; + throw new LifecycleException( message, ex ); + } + } + else + { + try + { + lifecycle.remove(); + } + catch( Exception ex ) + { + String message = "Unable to invoke remove lifecycle on " + lifecycle; + throw new LifecycleException( message, ex ); + } + } + } + } + } +} http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/entity/EntityModel.java ---------------------------------------------------------------------- diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/entity/EntityModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/entity/EntityModel.java new file mode 100644 index 0000000..4fd073d --- /dev/null +++ b/core/runtime/src/main/java/org/apache/polygene/runtime/entity/EntityModel.java @@ -0,0 +1,158 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.polygene.runtime.entity; + +import java.lang.reflect.Method; +import java.util.List; +import org.apache.polygene.api.common.ConstructionException; +import org.apache.polygene.api.common.MetaInfo; +import org.apache.polygene.api.common.Visibility; +import org.apache.polygene.api.composite.CompositeInstance; +import org.apache.polygene.api.constraint.ConstraintViolationException; +import org.apache.polygene.api.entity.EntityDescriptor; +import org.apache.polygene.api.entity.EntityReference; +import org.apache.polygene.api.entity.Queryable; +import org.apache.polygene.api.property.PropertyDescriptor; +import org.apache.polygene.api.property.StateHolder; +import org.apache.polygene.api.structure.ModuleDescriptor; +import org.apache.polygene.api.unitofwork.EntityCompositeAlreadyExistsException; +import org.apache.polygene.api.util.Annotations; +import org.apache.polygene.runtime.composite.CompositeMethodsModel; +import org.apache.polygene.runtime.composite.CompositeModel; +import org.apache.polygene.runtime.unitofwork.ModuleUnitOfWork; +import org.apache.polygene.spi.entity.EntityState; +import org.apache.polygene.spi.entitystore.EntityAlreadyExistsException; +import org.apache.polygene.spi.entitystore.EntityStoreException; +import org.apache.polygene.spi.entitystore.EntityStoreUnitOfWork; +import org.apache.polygene.spi.module.ModuleSpi; + +import static org.apache.polygene.api.identity.HasIdentity.IDENTITY_METHOD; + +/** + * JAVADOC + */ +public final class EntityModel extends CompositeModel + implements EntityDescriptor +{ + + private final boolean queryable; + + public EntityModel( ModuleDescriptor module, + List> types, + Visibility visibility, + MetaInfo info, + EntityMixinsModel mixinsModel, + EntityStateModel stateModel, + CompositeMethodsModel compositeMethodsModel + ) + { + super( module, types, visibility, info, mixinsModel, stateModel, compositeMethodsModel ); + + this.queryable = types.stream() + .flatMap( Annotations.ANNOTATIONS_OF ) + .filter( Annotations.isType( Queryable.class ) ) + .map( annot -> ( (Queryable) annot ).value() ) + .findFirst() + .orElse( true ); + } + + @Override + public boolean queryable() + { + return queryable; + } + + @Override + public EntityStateModel state() + { + return (EntityStateModel) super.state(); + } + + public EntityInstance newInstance( ModuleUnitOfWork uow, ModuleSpi moduleInstance, EntityState state ) + { + return new EntityInstance( uow, this, state ); + } + + public Object[] newMixinHolder() + { + return mixinsModel.newMixinHolder(); + } + + public Object newMixin( Object[] mixins, + EntityStateInstance entityState, + EntityInstance entityInstance, + Method method + ) + { + return ( (EntityMixinsModel) mixinsModel ).newMixin( entityInstance, entityState, mixins, method ); + } + + public EntityState newEntityState( EntityStoreUnitOfWork store, EntityReference reference ) + throws ConstraintViolationException, EntityStoreException + { + try + { + // New EntityState + EntityState entityState = store.newEntityState( reference, this ); + + // Set reference property + PropertyDescriptor persistentPropertyDescriptor = state().propertyModelFor( IDENTITY_METHOD ); + entityState.setPropertyValue( persistentPropertyDescriptor.qualifiedName(), reference.identity() ); + + return entityState; + } + catch( EntityAlreadyExistsException e ) + { + throw new EntityCompositeAlreadyExistsException( reference ); + } + catch( EntityStoreException e ) + { + throw new ConstructionException( "Could not create new entity in store", e ); + } + } + + public void initState( ModuleDescriptor module, EntityState entityState ) + { + // Set new properties to default value + state().properties().forEach( propertyDescriptor -> { + entityState.setPropertyValue( propertyDescriptor.qualifiedName(), propertyDescriptor.initialValue( module ) ); + } ); + + // Set new associations to null + state().associations().forEach( associationDescriptor -> { + entityState.setAssociationValue( associationDescriptor.qualifiedName(), null ); + } ); + + // Set new many-associations to empty + state().manyAssociations().forEach( associationDescriptor -> { + entityState.manyAssociationValueOf( associationDescriptor.qualifiedName() ); + } ); + + // Set new named-associations to empty + state().namedAssociations().forEach( associationDescriptor -> { + entityState.namedAssociationValueOf( associationDescriptor.qualifiedName() ); + } ); + } + + public void invokeLifecycle( boolean create, Object[] mixins, CompositeInstance instance, StateHolder state ) + { + ( (EntityMixinsModel) mixinsModel ).invokeLifecycle( create, mixins, instance, state ); + } +} http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/entity/EntityPropertyInstance.java ---------------------------------------------------------------------- diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/entity/EntityPropertyInstance.java b/core/runtime/src/main/java/org/apache/polygene/runtime/entity/EntityPropertyInstance.java new file mode 100644 index 0000000..2f57d9e --- /dev/null +++ b/core/runtime/src/main/java/org/apache/polygene/runtime/entity/EntityPropertyInstance.java @@ -0,0 +1,58 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.polygene.runtime.entity; + +import org.apache.polygene.runtime.property.PropertyInfo; +import org.apache.polygene.runtime.property.PropertyInstance; +import org.apache.polygene.spi.entity.EntityState; + +/** + * {@code EntityPropertyInstance} represents a property whose value must be backed by an EntityState. + */ +public class EntityPropertyInstance + extends PropertyInstance +{ + private final EntityState entityState; + + /** + * Construct an instance of {@code PropertyInstance} with the specified arguments. + * + * @param aPropertyInfo The property info. This argument must not be {@code null}. + * @param entityState EntityState + */ + @SuppressWarnings( "unchecked" ) + public EntityPropertyInstance( PropertyInfo aPropertyInfo, EntityState entityState ) + { + super( aPropertyInfo, (T) entityState.propertyValueOf( aPropertyInfo.qualifiedName() ) ); + this.entityState = entityState; + } + + /** + * Sets this property value. + * + * @param aNewValue The new value. + */ + @Override + public void set( T aNewValue ) + { + super.set( aNewValue ); + entityState.setPropertyValue( model.qualifiedName(), aNewValue ); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/entity/EntityStateInstance.java ---------------------------------------------------------------------- diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/entity/EntityStateInstance.java b/core/runtime/src/main/java/org/apache/polygene/runtime/entity/EntityStateInstance.java new file mode 100644 index 0000000..27660cc --- /dev/null +++ b/core/runtime/src/main/java/org/apache/polygene/runtime/entity/EntityStateInstance.java @@ -0,0 +1,232 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.polygene.runtime.entity; + +import java.lang.reflect.AccessibleObject; +import java.lang.reflect.Method; +import java.lang.reflect.Type; +import java.util.HashMap; +import java.util.Map; +import java.util.function.BiFunction; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import org.apache.polygene.api.association.Association; +import org.apache.polygene.api.association.AssociationStateHolder; +import org.apache.polygene.api.association.ManyAssociation; +import org.apache.polygene.api.association.NamedAssociation; +import org.apache.polygene.api.entity.EntityReference; +import org.apache.polygene.api.property.Property; +import org.apache.polygene.api.unitofwork.UnitOfWork; +import org.apache.polygene.api.util.Classes; +import org.apache.polygene.runtime.association.AssociationInstance; +import org.apache.polygene.runtime.association.AssociationModel; +import org.apache.polygene.runtime.association.ManyAssociationInstance; +import org.apache.polygene.runtime.association.ManyAssociationModel; +import org.apache.polygene.runtime.association.NamedAssociationInstance; +import org.apache.polygene.runtime.association.NamedAssociationModel; +import org.apache.polygene.runtime.property.PropertyModel; +import org.apache.polygene.runtime.unitofwork.BuilderEntityState; +import org.apache.polygene.spi.entity.EntityState; + +/** + * TODO + */ +public final class EntityStateInstance + implements AssociationStateHolder +{ + private Map state; + + private final EntityStateModel stateModel; + private EntityState entityState; + private final BiFunction entityFunction; + + public EntityStateInstance( EntityStateModel stateModel, final UnitOfWork uow, EntityState entityState ) + { + this.stateModel = stateModel; + this.entityState = entityState; + + entityFunction = ( entityReference, type ) -> uow.get( Classes.RAW_CLASS.apply( type ), entityReference.identity() ); + } + + @Override + @SuppressWarnings( "unchecked" ) + public Property propertyFor( AccessibleObject accessor ) + throws IllegalArgumentException + { + Map state = state(); + + Property property = (Property) state.get( accessor ); + + if( property == null ) + { + PropertyModel entityPropertyModel = stateModel.propertyModelFor( accessor ); + property = new EntityPropertyInstance<>( + entityState instanceof BuilderEntityState + ? entityPropertyModel.getBuilderInfo() + : entityPropertyModel, + entityState ); + state.put( accessor, property ); + } + + return property; + } + + @Override + public Stream> properties() + { + return stateModel.properties().map( descriptor -> propertyFor( descriptor.accessor() ) ); + } + + @Override + @SuppressWarnings( "unchecked" ) + public Association associationFor( AccessibleObject accessor ) + throws IllegalArgumentException + { + Map state = state(); + Association association = (Association) state.get( accessor ); + + if( association == null ) + { + final AssociationModel associationModel = stateModel.getAssociation( accessor ); + association = new AssociationInstance<>( + entityState instanceof BuilderEntityState + ? associationModel.getBuilderInfo() + : associationModel, + entityFunction, + new Property() + { + @Override + public EntityReference get() + { + return entityState.associationValueOf( associationModel.qualifiedName() ); + } + + @Override + public void set( EntityReference newValue ) + throws IllegalArgumentException, IllegalStateException + { + entityState.setAssociationValue( associationModel.qualifiedName(), newValue ); + } + } ); + state.put( accessor, association ); + } + + return association; + } + + @Override + public Stream> allAssociations() + { + return stateModel.associations().map( descriptor -> associationFor( descriptor.accessor() ) ); + } + + @Override + @SuppressWarnings( "unchecked" ) + public ManyAssociation manyAssociationFor( AccessibleObject accessor ) + { + Map state = state(); + + ManyAssociation manyAssociation = (ManyAssociation) state.get( accessor ); + + if( manyAssociation == null ) + { + ManyAssociationModel associationModel = stateModel.getManyAssociation( accessor ); + manyAssociation = new ManyAssociationInstance<>( + entityState instanceof BuilderEntityState + ? associationModel.getBuilderInfo() + : associationModel, + entityFunction, + entityState.manyAssociationValueOf( associationModel.qualifiedName() ) ); + state.put( accessor, manyAssociation ); + } + + return manyAssociation; + } + + @Override + public Stream> allManyAssociations() + { + return stateModel.manyAssociations().map( descriptor -> manyAssociationFor( descriptor.accessor() ) ); + } + + @Override + @SuppressWarnings( "unchecked" ) + public NamedAssociation namedAssociationFor( AccessibleObject accessor ) + { + Map state = state(); + + NamedAssociation namedAssociation = (NamedAssociation) state.get( accessor ); + + if( namedAssociation == null ) + { + NamedAssociationModel associationModel = stateModel.getNamedAssociation( accessor ); + namedAssociation = new NamedAssociationInstance<>( + entityState instanceof BuilderEntityState + ? associationModel.getBuilderInfo() + : associationModel, + entityFunction, + entityState.namedAssociationValueOf( associationModel.qualifiedName() ) ); + state.put( accessor, namedAssociation ); + } + + return namedAssociation; + } + + @Override + public Stream> allNamedAssociations() + { + return stateModel.namedAssociations().map( descriptor -> namedAssociationFor( descriptor.accessor() ) ); + } + + public void checkConstraints() + { + stateModel.properties().forEach( propertyDescriptor -> { + Property property = this.propertyFor( propertyDescriptor.accessor() ); + propertyDescriptor.checkConstraints( property.get() ); + } ); + + stateModel.associations().forEach( associationDescriptor -> { + Association association = this.associationFor( associationDescriptor.accessor() ); + associationDescriptor.checkConstraints( association.get() ); + } ); + + // TODO Should ManyAssociations and NamedAssociations be checked too? + } + + private Map state() + { + if( state == null ) + { + state = new HashMap<>(); + } + + return state; + } + + @Override + public String toString() + { + return "EntityState[" + state.entrySet().stream() + .map( entry -> ((Method) entry.getKey()).getName() + "=" + entry.getValue()) + .collect( Collectors.joining("\n ", " ", "\n") ) + + "]" + ; + } +} http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/entity/EntityStateModel.java ---------------------------------------------------------------------- diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/entity/EntityStateModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/entity/EntityStateModel.java new file mode 100644 index 0000000..7601b4e --- /dev/null +++ b/core/runtime/src/main/java/org/apache/polygene/runtime/entity/EntityStateModel.java @@ -0,0 +1,158 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.polygene.runtime.entity; + +import java.lang.reflect.AccessibleObject; +import java.util.stream.Stream; +import org.apache.polygene.api.association.AssociationDescriptor; +import org.apache.polygene.api.association.AssociationStateDescriptor; +import org.apache.polygene.api.common.QualifiedName; +import org.apache.polygene.api.util.HierarchicalVisitor; +import org.apache.polygene.api.util.VisitableHierarchy; +import org.apache.polygene.runtime.association.AssociationModel; +import org.apache.polygene.runtime.association.AssociationsModel; +import org.apache.polygene.runtime.association.ManyAssociationModel; +import org.apache.polygene.runtime.association.ManyAssociationsModel; +import org.apache.polygene.runtime.association.NamedAssociationModel; +import org.apache.polygene.runtime.association.NamedAssociationsModel; +import org.apache.polygene.runtime.composite.StateModel; +import org.apache.polygene.runtime.property.PropertiesModel; + +/** + * Model for EntityComposite state. + */ +public final class EntityStateModel + extends StateModel + implements AssociationStateDescriptor +{ + private final AssociationsModel associationsModel; + private final ManyAssociationsModel manyAssociationsModel; + private final NamedAssociationsModel namedAssociationsModel; + + public EntityStateModel( PropertiesModel propertiesModel, + AssociationsModel associationsModel, + ManyAssociationsModel manyAssociationsModel, + NamedAssociationsModel namedAssociationsModel ) + { + super( propertiesModel ); + this.associationsModel = associationsModel; + this.manyAssociationsModel = manyAssociationsModel; + this.namedAssociationsModel = namedAssociationsModel; + } + + public AssociationModel getAssociation( AccessibleObject accessor ) + throws IllegalArgumentException + { + return associationsModel.getAssociation( accessor ); + } + + @Override + public AssociationDescriptor getAssociationByName( String name ) + throws IllegalArgumentException + { + return associationsModel.getAssociationByName( name ); + } + + @Override + public AssociationDescriptor getAssociationByQualifiedName( QualifiedName name ) + throws IllegalArgumentException + { + return associationsModel.getAssociationByQualifiedName( name ); + } + + public ManyAssociationModel getManyAssociation( AccessibleObject accessor ) + throws IllegalArgumentException + { + return manyAssociationsModel.getManyAssociation( accessor ); + } + + @Override + public AssociationDescriptor getManyAssociationByName( String name ) + throws IllegalArgumentException + { + return manyAssociationsModel.getManyAssociationByName( name ); + } + + @Override + public AssociationDescriptor getManyAssociationByQualifiedName( QualifiedName name ) + throws IllegalArgumentException + { + return manyAssociationsModel.getManyAssociationByQualifiedName( name ); + } + + public NamedAssociationModel getNamedAssociation( AccessibleObject accessor ) + throws IllegalArgumentException + { + return namedAssociationsModel.getNamedAssociation( accessor ); + } + + @Override + public AssociationDescriptor getNamedAssociationByName( String name ) + throws IllegalArgumentException + { + return namedAssociationsModel.getNamedAssociationByName( name ); + } + + @Override + public AssociationDescriptor getNamedAssociationByQualifiedName( QualifiedName name ) + throws IllegalArgumentException + { + return namedAssociationsModel.getNamedAssociationByQualifiedName( name ); + } + + @Override + public Stream associations() + { + return associationsModel.associations(); + } + + @Override + public Stream manyAssociations() + { + return manyAssociationsModel.manyAssociations(); + } + + @Override + public Stream namedAssociations() + { + return namedAssociationsModel.namedAssociations(); + } + + @Override + public boolean accept( HierarchicalVisitor visitor ) + throws ThrowableType + { + if( visitor.visitEnter( this ) ) + { + if( ( (VisitableHierarchy) propertiesModel ).accept( visitor ) ) + { + if( ( (VisitableHierarchy) associationsModel ).accept( visitor ) ) + { + if( ( (VisitableHierarchy) manyAssociationsModel ).accept( visitor ) ) + { + ( (VisitableHierarchy) namedAssociationsModel ).accept( visitor ); + } + } + } + } + return visitor.visitLeave( this ); + } + +} http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/injection/Dependencies.java ---------------------------------------------------------------------- diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/injection/Dependencies.java b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/Dependencies.java new file mode 100644 index 0000000..31d8b75 --- /dev/null +++ b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/Dependencies.java @@ -0,0 +1,33 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.polygene.runtime.injection; + +import java.util.function.Function; +import java.util.stream.Stream; + +/** + * TODO + */ +public interface Dependencies +{ + Function> DEPENDENCIES_FUNCTION = Dependencies::dependencies; + + Stream dependencies(); +} http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/injection/DependencyModel.java ---------------------------------------------------------------------- diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/injection/DependencyModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/DependencyModel.java new file mode 100644 index 0000000..0c72658 --- /dev/null +++ b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/DependencyModel.java @@ -0,0 +1,421 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.polygene.runtime.injection; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.lang.reflect.TypeVariable; +import java.util.Collections; +import java.util.Iterator; +import java.util.function.Predicate; +import java.util.stream.Stream; +import org.apache.polygene.api.common.ConstructionException; +import org.apache.polygene.api.common.Optional; +import org.apache.polygene.api.composite.DependencyDescriptor; +import org.apache.polygene.api.util.Visitable; +import org.apache.polygene.api.util.Visitor; +import org.apache.polygene.bootstrap.BindingException; +import org.apache.polygene.bootstrap.InvalidInjectionException; +import org.apache.polygene.runtime.injection.provider.CachingInjectionProviderDecorator; +import org.apache.polygene.runtime.injection.provider.InjectionProviderException; +import org.apache.polygene.runtime.injection.provider.ServiceInjectionProviderFactory; +import org.apache.polygene.runtime.model.Binder; +import org.apache.polygene.runtime.model.Resolution; + +import static org.apache.polygene.api.util.Annotations.isType; + +/** + * JAVADOC + * move all the extraction code to a TypeUtils class + */ +public final class DependencyModel + implements Binder, DependencyDescriptor, Visitable +{ + public static boolean isOptional( Annotation injectionAnnotation, Annotation[] annotations ) + { + if( Stream.of( annotations ).anyMatch( isType( Optional.class ) ) ) + { + return true; + } + + Method[] methods = injectionAnnotation.annotationType().getMethods(); + for( Method method : methods ) + { + if( method.getName().equals( "optional" ) ) + { + try + { + return (Boolean) method.invoke( injectionAnnotation ); + } + catch( Throwable e ) + { + return false; + } + } + } + + return false; + } + + // Model + private final Annotation injectionAnnotation; + private final Type injectionType; + private final Class injectedClass; + private final Class rawInjectionClass; + private final boolean optional; + private final Annotation[] annotations; + + // Binding + private InjectionProvider injectionProvider; + + public DependencyModel( Annotation injectionAnnotation, + Type genericType, + Class injectedClass, + boolean optional, + Annotation[] annotations + ) + { + this.injectionAnnotation = injectionAnnotation; + this.injectedClass = injectedClass; + + this.injectionType = genericType; + this.optional = optional; + this.annotations = annotations; + this.rawInjectionClass = mapPrimitiveTypes( extractRawInjectionClass( injectedClass, injectionType ) ); + } + + @Override + public boolean accept( Visitor visitor ) + throws ThrowableType + { + return visitor.visit( this ); + } + + private Class extractRawInjectionClass( Class injectedClass, final Type injectionType ) + { + // Calculate raw injection type + if( injectionType instanceof Class ) + { + return (Class) injectionType; + } + else if( injectionType instanceof ParameterizedType ) + { + return (Class) ( (ParameterizedType) injectionType ).getRawType(); + } + else if( injectionType instanceof TypeVariable ) + { + return extractRawInjectionClass( injectedClass, (TypeVariable) injectionType ); + } + throw new IllegalArgumentException( + "Could not extract the rawInjectionClass of " + injectedClass + " and " + injectionType ); + } + + private Class extractRawInjectionClass( Class injectedClass, TypeVariable injectionTypeVariable ) + { + int index = 0; + for( TypeVariable typeVariable : injectionTypeVariable.getGenericDeclaration().getTypeParameters() ) + { + if( injectionTypeVariable.getName().equals( typeVariable.getName() ) ) + { + return (Class) getActualType( injectedClass, index ); + } + index++; + } + throw new IllegalArgumentException( + "Could not extract the rawInjectionClass of " + injectedClass + " and " + injectionTypeVariable ); + } + + // todo continue refactoring + + private Type getActualType( Class injectedClass, int index ) + { + // Type index found - map it to actual type + Type genericType = injectedClass; + Type type = null; + + while( !Object.class.equals( genericType ) && type == null ) + { + genericType = ( (Class) genericType ).getGenericSuperclass(); + if( genericType instanceof ParameterizedType ) + { + type = ( (ParameterizedType) genericType ).getActualTypeArguments()[ index ]; + } + else + { + Type[] genericInterfaces = ( (Class) genericType ).getGenericInterfaces(); + if( genericInterfaces.length > index ) + { + type = genericInterfaces[ index ]; + if( type instanceof ParameterizedType ) + { + type = ( (ParameterizedType) type ).getActualTypeArguments()[ index ]; + } + // TODO type may still be one of the generic interfaces??? + } + } + } + + if( type == null ) + { + type = Object.class; // Generic type with no constraints so Object is fine + } + + return type; + } + + // FIXME This method is unused, remove it. + private Type extractDependencyType( Type injectionType ) + { + if( injectionType instanceof ParameterizedType ) + { + return ( (ParameterizedType) injectionType ).getActualTypeArguments()[ 0 ]; + } + else if( injectionType instanceof TypeVariable ) + { + return ( (TypeVariable) injectionType ).getBounds()[ 0 ]; + } + return injectionType; + } + + // Model + @Override + public Annotation injectionAnnotation() + { + return injectionAnnotation; + } + + @Override + public Type injectionType() + { + return injectionType; + } + + @Override + public Class injectedClass() + { + return injectedClass; + } + + /** + * Get the raw dependency type. + *

+ * If the dependency uses generics this is the raw type, + * and otherwise it is the type of the field. + *

+ * Examples: + *

+ * {@code @Service MyService service} -> MyService + *

+ * {@code @Entity Iterable fooList} -> Iterable + *

+ * {@code @Entity Query fooQuery} -> Query + * + * @return raw injection type. + */ + @Override + public Class rawInjectionType() + { + return rawInjectionClass; + } + + @Override + public boolean optional() + { + return optional; + } + + @Override + public Annotation[] annotations() + { + return annotations; + } + + @Override + public void bind( Resolution resolution ) + throws BindingException + { + InjectionProviderFactory providerFactory = resolution.application().injectionProviderFactory(); + + try + { + injectionProvider = providerFactory.newInjectionProvider( resolution, this ); + + if( injectionProvider == null && !optional ) + { + String message = + "[Module " + resolution.module() + .name() + "] Non-optional @" + rawInjectionClass.getName() + " was not bound in " + injectedClass + .getName(); + throw new ConstructionException( message ); + } + } + catch( InvalidInjectionException e ) + { + throw new BindingException( "Could not bind dependency injection", e ); + } + } + + // Context + public Object inject( InjectionContext context ) + { + if( injectionProvider == null ) + { + return null; + } + Object injectedValue; + try + { + injectedValue = injectionProvider.provideInjection( context ); + } + catch( InjectionProviderException e ) + { + Throwable ex = e; + if( ex.getCause() != null ) + { + ex = ex.getCause(); + } + + String message = "[Module " + context.module().name() + "] InjectionProvider unable to resolve @" + + injectionAnnotation.annotationType().getSimpleName() + " " + injectionType.toString(); + throw new ConstructionException( message, ex ); + } + if( injectedValue == null && !optional ) + { + String simpleName = injectionAnnotation.annotationType().getSimpleName(); + String message = "[Module " + context.module().name() + "] Non-optional @" + + simpleName + " " + injectionType.toString() + + " was null in " + injectedClass.getName(); + if( simpleName.toLowerCase().contains( "service" ) + && !isServiceInjectionProvider() ) + { + message = message + ". Did you mean the @Service injection scope?"; + } + throw new ConstructionException( message ); + } + return getInjectedValue( injectedValue ); + } + + private boolean isServiceInjectionProvider() + { + + InjectionProvider provider = this.injectionProvider; + if( provider instanceof CachingInjectionProviderDecorator ){ + provider = ((CachingInjectionProviderDecorator) provider ).decoratedProvider(); + } + return ServiceInjectionProviderFactory.ServiceInjectionProvider.class.isAssignableFrom( provider.getClass() ); + } + + @SuppressWarnings( "unchecked" ) + private Object getInjectedValue( Object injectionResult ) + { + if( injectionResult == null ) + { + return null; + } + + if( injectionResult instanceof Iterable ) + { + if( Iterable.class.isAssignableFrom( rawInjectionClass ) + || rawInjectionClass.isInstance( injectionResult ) ) + { + return injectionResult; + } + else + { + Iterator iterator = ( (Iterable) injectionResult ).iterator(); + return iterator.hasNext() ? iterator.next() : null; + } + } + else + { + if( Iterable.class.equals( injectionType ) ) + { + return Collections.singleton( injectionResult ); + } + } + return injectionResult; + } + + private final static Class[] primitiveTypeMapping = { + boolean.class, Boolean.class, + byte.class, Byte.class, + short.class, Short.class, + char.class, Character.class, + long.class, Long.class, + double.class, Double.class, + float.class, Float.class, + int.class, Integer.class, + }; + + private Class mapPrimitiveTypes( Class rawInjectionType ) + { + if( rawInjectionType == null || !rawInjectionType.isPrimitive() ) + { + return rawInjectionType; + } + for( int i = 0; i < primitiveTypeMapping.length; i += 2 ) + { + if( primitiveTypeMapping[ i ].equals( rawInjectionType ) ) + { + return primitiveTypeMapping[ i + 1 ]; + } + } + return rawInjectionType; + } + + public boolean hasScope( final Class scope ) + { + return scope == null || scope.equals( injectionAnnotation().annotationType() ); + } + + public Class injectionAnnotationType() + { + if( injectionAnnotation == null ) + { + return null; + } + return injectionAnnotation.annotationType(); + } + + @Override + public String toString() + { + return injectionAnnotation + " for " + injectionType + " in " + injectedClass.getName(); + } + + public static class ScopeSpecification + implements Predicate + { + private final Class scope; + + public ScopeSpecification( Class scope ) + { + this.scope = scope; + } + + @Override + public boolean test( DependencyModel model ) + { + return model.hasScope( scope ); + } + } +} http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectedFieldModel.java ---------------------------------------------------------------------- diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectedFieldModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectedFieldModel.java new file mode 100644 index 0000000..e4fd289 --- /dev/null +++ b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectedFieldModel.java @@ -0,0 +1,165 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.polygene.runtime.injection; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Proxy; +import java.util.Collection; +import java.util.function.Predicate; +import java.util.stream.Stream; +import org.apache.polygene.api.composite.DependencyDescriptor; +import org.apache.polygene.api.composite.InjectedFieldDescriptor; +import org.apache.polygene.api.util.Classes; +import org.apache.polygene.api.util.HierarchicalVisitor; +import org.apache.polygene.api.util.VisitableHierarchy; +import org.apache.polygene.bootstrap.BindingException; +import org.apache.polygene.bootstrap.InjectionException; +import org.apache.polygene.runtime.composite.TransientInstance; +import org.apache.polygene.runtime.model.Resolution; + +import static java.util.Collections.emptyList; +import static java.util.Collections.singleton; + +/** + * JAVADOC + */ +public final class InjectedFieldModel + implements InjectedFieldDescriptor, Dependencies, VisitableHierarchy +{ + private DependencyModel dependencyModel; + private Field injectedField; + + public InjectedFieldModel( Field injectedField, DependencyModel dependencyModel ) + { + injectedField.setAccessible( true ); + this.injectedField = injectedField; + this.dependencyModel = dependencyModel; + } + + @Override + public Stream dependencies() + { + return Stream.of( dependencyModel ); + } + + @Override + public Field field() + { + return injectedField; + } + + @Override + public DependencyDescriptor dependency() + { + return dependencyModel; + } + + public void bind( Resolution resolution ) + throws BindingException + { + dependencyModel.bind( resolution.forField( injectedField ) ); + } + + public void inject( InjectionContext context, Object instance ) + { + Object value = dependencyModel.inject( context ); + try + { + injectedField.set( instance, value ); + } + catch( IllegalAccessException e ) + { + throw new InjectionException( e ); + } + catch( IllegalArgumentException e ) + { + String valueClassName; + if( value == null ) + { + valueClassName = ""; + } + else if( Proxy.isProxyClass( value.getClass() ) ) + { + InvocationHandler invocationHandler = Proxy.getInvocationHandler( value ); + if( invocationHandler instanceof TransientInstance ) + { + TransientInstance handler = (TransientInstance) invocationHandler; + valueClassName = Classes.toString( handler.descriptor().types() ) + + " in [" + handler.module().name() + "] of [" + handler.layer().name() + "]"; + } + else + { + valueClassName = invocationHandler.toString(); + } + } + else + { + valueClassName = value.getClass().getName(); + } + StringBuilder annotBuilder = new StringBuilder(); + for( Annotation annot : injectedField.getAnnotations() ) + { + String s = annot.toString(); + annotBuilder.append( "@" ).append( s.substring( s.lastIndexOf( '.' ) + 1, s.length() - 2 ) ); + annotBuilder.append( " " ); + } + String annots = annotBuilder.toString(); + String message = "Can not inject the field\n " + + injectedField.getDeclaringClass() + + "\n {\n " + annots + "\n " + + injectedField.getType().getSimpleName() + " " + injectedField.getName() + + "\n }\nwith value \n " + value + "\nof type\n " + + valueClassName; + throw new InjectionException( message, e ); + } + } + + @Override + public boolean accept( HierarchicalVisitor visitor ) + throws ThrowableType + { + if( visitor.visitEnter( this ) ) + { + visitor.visit( dependencyModel ); + } + return visitor.visitLeave( this ); + } + + public Collection filter( Predicate specification ) + { + if( specification.test( dependencyModel ) ) + { + return singleton( dependencyModel ); + } + else + { + return emptyList(); + } + } + + @Override + public String toString() + { + return "InjectedFieldModel{" + ", injectedField=" + injectedField + '}'; + } +} http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectedFieldsModel.java ---------------------------------------------------------------------- diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectedFieldsModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectedFieldsModel.java new file mode 100644 index 0000000..54c8312 --- /dev/null +++ b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectedFieldsModel.java @@ -0,0 +1,117 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.polygene.runtime.injection; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Field; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.lang.reflect.TypeVariable; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; +import java.util.stream.Stream; +import org.apache.polygene.api.injection.InjectionScope; +import org.apache.polygene.api.util.Classes; +import org.apache.polygene.api.util.Fields; +import org.apache.polygene.api.util.HierarchicalVisitor; +import org.apache.polygene.api.util.VisitableHierarchy; + +import static org.apache.polygene.api.util.Annotations.typeHasAnnotation; + +/** + * JAVADOC + */ +public final class InjectedFieldsModel + implements Dependencies, VisitableHierarchy +{ + private final List fields = new ArrayList<>(); + + public InjectedFieldsModel( Class fragmentClass ) + { + Fields.fieldsOf( fragmentClass ).forEach( field -> + Arrays.stream( field.getAnnotations() ) + .filter( typeHasAnnotation( InjectionScope.class ) ) + .filter( Objects::nonNull ) + .forEach( injectionAnnotation -> addModel( fragmentClass, field, injectionAnnotation ) + ) + ); + } + + private void addModel( Class fragmentClass, Field field, Annotation injectionAnnotation ) + { + Type genericType = field.getGenericType(); + if( genericType instanceof ParameterizedType ) + { + Type[] actualTypeArguments = ( (ParameterizedType) genericType ).getActualTypeArguments(); + Type rawType = ( (ParameterizedType) genericType ).getRawType(); + Type ownerType = ( (ParameterizedType) genericType ).getOwnerType(); + genericType = new ParameterizedTypeInstance( actualTypeArguments, rawType, ownerType ); + + for( int i = 0; i < actualTypeArguments.length; i++ ) + { + Type type = actualTypeArguments[ i ]; + if( type instanceof TypeVariable ) + { + type = Classes.resolveTypeVariable( (TypeVariable) type, field.getDeclaringClass(), fragmentClass ); + actualTypeArguments[ i ] = type; + } + } + } + + boolean optional = DependencyModel.isOptional( injectionAnnotation, field.getAnnotations() ); + DependencyModel dependencyModel = new DependencyModel( injectionAnnotation, genericType, fragmentClass, optional, field.getAnnotations() ); + InjectedFieldModel injectedFieldModel = new InjectedFieldModel( field, dependencyModel ); + this.fields.add( injectedFieldModel ); + } + + @Override + public Stream dependencies() + { + return fields.stream().flatMap( Dependencies::dependencies ); + } + + @Override + public boolean accept( HierarchicalVisitor modelVisitor ) + throws ThrowableType + { + if( modelVisitor.visitEnter( this ) ) + { + for( InjectedFieldModel field : fields ) + { + if( !field.accept( modelVisitor ) ) + { + break; + } + } + } + return modelVisitor.visitLeave( this ); + } + + public void inject( InjectionContext context, Object instance ) + { + for( InjectedFieldModel field : fields ) + { + field.inject( context, instance ); + } + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectedMethodModel.java ---------------------------------------------------------------------- diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectedMethodModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectedMethodModel.java new file mode 100644 index 0000000..f1dc19b --- /dev/null +++ b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectedMethodModel.java @@ -0,0 +1,93 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.polygene.runtime.injection; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.stream.Stream; +import org.apache.polygene.api.composite.InjectedMethodDescriptor; +import org.apache.polygene.api.util.HierarchicalVisitor; +import org.apache.polygene.api.util.VisitableHierarchy; +import org.apache.polygene.bootstrap.InjectionException; + +/** + * JAVADOC + */ +public final class InjectedMethodModel + implements InjectedMethodDescriptor, Dependencies, VisitableHierarchy +{ + // Model + private Method method; + private InjectedParametersModel parameters; + + public InjectedMethodModel( Method method, InjectedParametersModel parameters ) + { + this.method = method; + this.method.setAccessible( true ); + this.parameters = parameters; + } + + @Override + public Method method() + { + return method; + } + + @Override + public Stream dependencies() + { + return parameters.dependencies(); + } + + // Context + public void inject( InjectionContext context, Object instance ) + throws InjectionException + { + Object[] params = parameters.newParametersInstance( context ); + try + { + if( !method.isAccessible() ) + { + method.setAccessible( true ); + } + method.invoke( instance, params ); + } + catch( IllegalAccessException e ) + { + throw new InjectionException( e ); + } + catch( InvocationTargetException e ) + { + throw new InjectionException( e.getTargetException() ); + } + } + + @Override + public boolean accept( HierarchicalVisitor visitor ) + throws ThrowableType + { + if( visitor.visitEnter( this ) ) + { + parameters.accept( visitor ); + } + return visitor.visitLeave( this ); + } +} http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectedMethodsModel.java ---------------------------------------------------------------------- diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectedMethodsModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectedMethodsModel.java new file mode 100644 index 0000000..388a17b --- /dev/null +++ b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectedMethodsModel.java @@ -0,0 +1,137 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.polygene.runtime.injection; + +import java.lang.annotation.Annotation; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.lang.reflect.TypeVariable; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Optional; +import java.util.stream.Stream; +import org.apache.polygene.api.injection.InjectionScope; +import org.apache.polygene.api.util.Classes; +import org.apache.polygene.api.util.Methods; +import org.apache.polygene.api.util.HierarchicalVisitor; +import org.apache.polygene.api.util.VisitableHierarchy; + +import static org.apache.polygene.api.util.Annotations.typeHasAnnotation; + +/** + * JAVADOC + */ +public final class InjectedMethodsModel + implements Dependencies, VisitableHierarchy +{ + // Model + private final List methodModels = new ArrayList<>(); + + public InjectedMethodsModel( Class fragmentClass ) + { + Methods.methodsOf( fragmentClass ).forEach( method -> { + Annotation[][] parameterAnnotations = method.getParameterAnnotations(); + if( parameterAnnotations.length > 0 ) + { + InjectedParametersModel parametersModel = new InjectedParametersModel(); + final Type[] genericParameterTypes = method.getGenericParameterTypes(); + boolean found = true; + for( int i = 0; i < parameterAnnotations.length; i++ ) + { + Optional opt = Arrays.stream( parameterAnnotations[ i ] ) + .filter( typeHasAnnotation( InjectionScope.class ) ) + .findFirst(); + if( opt.isPresent() ) + { + Annotation injectionAnnotation = opt.get(); + Type genericType = genericParameterTypes[ i ]; + if( genericType instanceof ParameterizedType ) + { + genericType = createParameterizedTypeInstance( (ParameterizedType) genericType ); + + for( int j = 0; j < ( (ParameterizedType) genericType ).getActualTypeArguments().length; j++ ) + { + Type type = ( (ParameterizedType) genericType ).getActualTypeArguments()[ j ]; + if( type instanceof TypeVariable ) + { + type = Classes.resolveTypeVariable( (TypeVariable) type, method.getDeclaringClass(), fragmentClass ); + ( (ParameterizedType) genericType ).getActualTypeArguments()[ j ] = type; + } + } + } + boolean optional = DependencyModel.isOptional( injectionAnnotation, parameterAnnotations[ i ] ); + DependencyModel dependencyModel = new DependencyModel( injectionAnnotation, genericType, fragmentClass, optional, parameterAnnotations[ i ] ); + parametersModel.addDependency( dependencyModel ); + } + else + { + found = false; + break; + } + } + if( found ) + { + methodModels.add( new InjectedMethodModel( method, parametersModel ) ); + } + } + } ); + } + + private Type createParameterizedTypeInstance( ParameterizedType genericType ) + { + return new ParameterizedTypeInstance( + genericType.getActualTypeArguments(), genericType.getRawType(), genericType.getOwnerType() + ); + } + + @Override + public Stream dependencies() + { + return methodModels.stream().flatMap( InjectedMethodModel::dependencies ); + } + + // Context + public void inject( InjectionContext context, Object instance ) + { + for( InjectedMethodModel methodModel : methodModels ) + { + methodModel.inject( context, instance ); + } + } + + @Override + public boolean accept( HierarchicalVisitor visitor ) + throws ThrowableType + { + if( visitor.visitEnter( this ) ) + { + for( InjectedMethodModel methodModel : methodModels ) + { + if( !methodModel.accept( visitor ) ) + { + break; + } + } + } + return visitor.visitLeave( this ); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectedParametersModel.java ---------------------------------------------------------------------- diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectedParametersModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectedParametersModel.java new file mode 100644 index 0000000..82ccd20 --- /dev/null +++ b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectedParametersModel.java @@ -0,0 +1,95 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.polygene.runtime.injection; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Stream; +import org.apache.polygene.api.composite.InjectedParametersDescriptor; +import org.apache.polygene.api.util.HierarchicalVisitor; +import org.apache.polygene.api.util.VisitableHierarchy; + +/** + * JAVADOC + */ +public final class InjectedParametersModel + implements InjectedParametersDescriptor, Dependencies, VisitableHierarchy +{ + private final List parameterDependencies; + + public InjectedParametersModel() + { + parameterDependencies = new ArrayList<>(); + } + + @Override + public Stream dependencies() + { + return parameterDependencies.stream(); + } + + // Context + public Object[] newParametersInstance( InjectionContext context ) + { + Object[] parametersInstance = new Object[ parameterDependencies.size() ]; + + // Inject parameterDependencies + for( int j = 0; j < parameterDependencies.size(); j++ ) + { + DependencyModel dependencyModel = parameterDependencies.get( j ); + Object parameter = dependencyModel.inject( context ); + parametersInstance[ j ] = parameter; + } + + return parametersInstance; + } + + public void addDependency( DependencyModel dependency ) + { + parameterDependencies.add( dependency ); + } + + @Override + public boolean accept( HierarchicalVisitor visitor ) + throws ThrowableType + { + if( visitor.visitEnter( this ) ) + { + for( DependencyModel parameterDependency : parameterDependencies ) + { + if( !visitor.visit( parameterDependency ) ) + { + break; + } + } + } + return visitor.visitLeave( this ); + } + + @Override + public String toString() + { + return "InjectedParametersModel{" + + "parameterDependencies=" + parameterDependencies + + '}'; + } +} + http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectionContext.java ---------------------------------------------------------------------- diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectionContext.java b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectionContext.java new file mode 100644 index 0000000..dd89d85 --- /dev/null +++ b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectionContext.java @@ -0,0 +1,126 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.polygene.runtime.injection; + +import org.apache.polygene.api.composite.CompositeInstance; +import org.apache.polygene.api.property.StateHolder; +import org.apache.polygene.api.structure.ModuleDescriptor; +import org.apache.polygene.runtime.composite.ProxyReferenceInvocationHandler; +import org.apache.polygene.runtime.composite.UsesInstance; + +/** + * JAVADOC + */ +public final class InjectionContext +{ + private final ModuleDescriptor module; + private CompositeInstance compositeInstance; + private UsesInstance uses; + private StateHolder state; + private Object next; // Only used for concerns and side-effects + private ProxyReferenceInvocationHandler proxyHandler; + private Object instance; // Only used for inner classes + + // For mixins + + public InjectionContext( CompositeInstance compositeInstance, UsesInstance uses, StateHolder state ) + { + this.module = compositeInstance.module(); + this.compositeInstance = compositeInstance; + this.uses = uses; + this.state = state; + } + + // For concerns and side-effects + public InjectionContext( ModuleDescriptor module, Object next, ProxyReferenceInvocationHandler proxyHandler ) + { + this.module = module; + this.next = next; + this.proxyHandler = proxyHandler; + } + + public InjectionContext( ModuleDescriptor module, UsesInstance uses ) + { + this.module = module; + this.uses = uses; + } + + // For inner classes + public InjectionContext( ModuleDescriptor module, UsesInstance uses, Object instance ) + { + this.module = module; + this.uses = uses; + this.instance = instance; + } + + public ModuleDescriptor module() + { + return module; + } + + public CompositeInstance compositeInstance() + { + return compositeInstance; + } + + public UsesInstance uses() + { + return uses; + } + + public StateHolder state() + { + return state; + } + + public Object next() + { + return next; + } + + public Object instance() + { + return instance; + } + + public ProxyReferenceInvocationHandler proxyHandler() + { + return proxyHandler; + } + + public void setUses( UsesInstance uses ) + { + this.uses = uses; + } + + @Override + public String toString() + { + return "InjectionContext{" + + "compositeInstance=" + compositeInstance + + ", module=" + module + + ", uses=" + uses + + ", state=" + state + + ", next=" + next + + ", proxyHandler=" + proxyHandler + + '}'; + } +} http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectionProvider.java ---------------------------------------------------------------------- diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectionProvider.java b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectionProvider.java new file mode 100644 index 0000000..a21a352 --- /dev/null +++ b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectionProvider.java @@ -0,0 +1,32 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.polygene.runtime.injection; + +import org.apache.polygene.runtime.injection.provider.InjectionProviderException; + +/** + * JAVADOC + */ +public interface InjectionProvider +{ + Object provideInjection( InjectionContext context ) + throws InjectionProviderException; +} http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectionProviderFactory.java ---------------------------------------------------------------------- diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectionProviderFactory.java b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectionProviderFactory.java new file mode 100644 index 0000000..8671d4c --- /dev/null +++ b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectionProviderFactory.java @@ -0,0 +1,43 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.polygene.runtime.injection; + +import org.apache.polygene.bootstrap.InvalidInjectionException; +import org.apache.polygene.runtime.model.Resolution; + +/** + * JAVADOC + */ +public interface InjectionProviderFactory +{ + /** + * Binding a dependency given an injection resolution. If no binding + * can be found, return null. If the dependency is optional the dependency will + * then be explicitly set to null. + * + * @param resolution Injection resolution + * @param dependencyModel Dependency model + * @return InjectionProvider + * @throws InvalidInjectionException if the injection is invalid + */ + InjectionProvider newInjectionProvider( Resolution resolution, DependencyModel dependencyModel ) + throws InvalidInjectionException; +} http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/injection/ParameterizedTypeInstance.java ---------------------------------------------------------------------- diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/injection/ParameterizedTypeInstance.java b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/ParameterizedTypeInstance.java new file mode 100644 index 0000000..d1f2bc7 --- /dev/null +++ b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/ParameterizedTypeInstance.java @@ -0,0 +1,66 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.polygene.runtime.injection; + +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.util.Arrays; + +/** + * TODO + */ +public class ParameterizedTypeInstance + implements ParameterizedType +{ + private Type[] actualTypeArguments; + private Type rawType; + private Type ownerType; + + public ParameterizedTypeInstance( Type[] actualTypeArguments, Type rawType, Type ownerType ) + { + this.actualTypeArguments = actualTypeArguments; + this.rawType = rawType; + this.ownerType = ownerType; + } + + @Override + public Type[] getActualTypeArguments() + { + return actualTypeArguments; + } + + @Override + public Type getRawType() + { + return rawType; + } + + @Override + public Type getOwnerType() + { + return ownerType; + } + + @Override + public String toString() + { + return rawType.toString() + Arrays.asList( actualTypeArguments ); + } +} http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/CachingInjectionProviderDecorator.java ---------------------------------------------------------------------- diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/CachingInjectionProviderDecorator.java b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/CachingInjectionProviderDecorator.java new file mode 100644 index 0000000..3339a48 --- /dev/null +++ b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/CachingInjectionProviderDecorator.java @@ -0,0 +1,63 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.polygene.runtime.injection.provider; + +import org.apache.polygene.runtime.injection.InjectionContext; +import org.apache.polygene.runtime.injection.InjectionProvider; + +/** + * If a dependency resolution should be a singleton, wrap it with this + * to provide a single instance "cache". + */ +public final class CachingInjectionProviderDecorator + implements InjectionProvider +{ + private final InjectionProvider decoratedProvider; + private volatile Object singletonInstance; + + public CachingInjectionProviderDecorator( InjectionProvider injectionProvider ) + { + this.decoratedProvider = injectionProvider; + } + + public InjectionProvider decoratedProvider() + { + return decoratedProvider; + } + + @Override + public Object provideInjection( InjectionContext context ) + throws InjectionProviderException + { + if( singletonInstance == null ) + { + synchronized( this ) + { + if( singletonInstance == null ) + { + singletonInstance = decoratedProvider.provideInjection( context ); + } + } + } + + return singletonInstance; + } +} http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/CachingInjectionProviderFactoryDecorator.java ---------------------------------------------------------------------- diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/CachingInjectionProviderFactoryDecorator.java b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/CachingInjectionProviderFactoryDecorator.java new file mode 100644 index 0000000..3e0ea74 --- /dev/null +++ b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/CachingInjectionProviderFactoryDecorator.java @@ -0,0 +1,56 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.polygene.runtime.injection.provider; + +import org.apache.polygene.bootstrap.InvalidInjectionException; +import org.apache.polygene.runtime.injection.DependencyModel; +import org.apache.polygene.runtime.injection.InjectionProvider; +import org.apache.polygene.runtime.injection.InjectionProviderFactory; +import org.apache.polygene.runtime.model.Resolution; + +/** + * JAVADOC + */ +public class CachingInjectionProviderFactoryDecorator + implements InjectionProviderFactory +{ + private final InjectionProviderFactory decoratedFactory; + + public CachingInjectionProviderFactoryDecorator( InjectionProviderFactory decoratedFactory ) + { + this.decoratedFactory = decoratedFactory; + } + + @Override + public InjectionProvider newInjectionProvider( Resolution resolution, DependencyModel dependencyModel ) + throws InvalidInjectionException + { + InjectionProvider injectionProvider = decoratedFactory.newInjectionProvider( resolution, dependencyModel ); + if( injectionProvider != null ) + { + return new CachingInjectionProviderDecorator( injectionProvider ); + } + else + { + return null; + } + } +} http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/InjectionProviderException.java ---------------------------------------------------------------------- diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/InjectionProviderException.java b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/InjectionProviderException.java new file mode 100644 index 0000000..43a8872 --- /dev/null +++ b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/InjectionProviderException.java @@ -0,0 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.polygene.runtime.injection.provider; + +/** + * JAVADOC + */ +public class InjectionProviderException + extends RuntimeException +{ + public InjectionProviderException( String string ) + { + super( string ); + } + + public InjectionProviderException( String string, Throwable throwable ) + { + super( string, throwable ); + } +}