| /* |
| * 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.zest.runtime.structure; |
| |
| import java.util.Iterator; |
| import java.util.concurrent.ConcurrentHashMap; |
| import java.util.function.Predicate; |
| import java.util.stream.Stream; |
| import org.apache.zest.api.common.Visibility; |
| import org.apache.zest.api.composite.AmbiguousTypeException; |
| import org.apache.zest.api.composite.ModelDescriptor; |
| |
| import static java.util.stream.Stream.concat; |
| import static org.apache.zest.api.common.Visibility.application; |
| import static org.apache.zest.api.common.Visibility.module; |
| import static org.apache.zest.api.util.Classes.modelTypeSpecification; |
| |
| // Module ClassLoader |
| class ModuleClassLoader |
| extends ClassLoader |
| { |
| |
| private final ModuleModel moduleModel; |
| private final ConcurrentHashMap<String, Class<?>> classes = new ConcurrentHashMap<>(); |
| |
| ModuleClassLoader( ModuleModel moduleModel, ClassLoader classLoader ) |
| { |
| super( classLoader ); |
| this.moduleModel = moduleModel; |
| } |
| |
| @Override |
| protected Class<?> findClass( String className ) |
| throws ClassNotFoundException |
| { |
| try |
| { |
| Class<?> resultingClass = classes.computeIfAbsent( className, name -> |
| { |
| Predicate<ModelDescriptor> modelTypeSpecification = modelTypeSpecification( name ); |
| Stream<? extends ModelDescriptor> moduleModels = concat( |
| moduleModel.visibleObjects( Visibility.module ), |
| concat( |
| moduleModel.visibleEntities( Visibility.module ), |
| concat( |
| moduleModel.visibleTransients( Visibility.module ), |
| moduleModel.visibleValues( Visibility.module ) |
| ) |
| ) |
| ).filter( modelTypeSpecification ); |
| |
| Class<?> clazz = null; |
| Iterator<? extends ModelDescriptor> iterator = moduleModels.iterator(); |
| if( iterator.hasNext() ) |
| { |
| clazz = iterator.next().types().findFirst().orElse( null ); |
| |
| if( iterator.hasNext() ) |
| { |
| // Ambiguous exception |
| new AmbiguousTypeException( |
| "More than one model matches the classname " + name + ":" + iterator.next() |
| ); |
| } |
| } |
| |
| // Check layer |
| if( clazz == null ) |
| { |
| Stream<? extends ModelDescriptor> modelsInLayer1 = concat( |
| moduleModel.layer().visibleObjects( Visibility.layer ), |
| concat( |
| moduleModel.layer().visibleEntities( Visibility.layer ), |
| concat( |
| moduleModel.layer().visibleTransients( Visibility.layer ), |
| moduleModel.layer().visibleValues( Visibility.layer ) |
| ) |
| ) |
| ); |
| // TODO: What does this actually represents?? Shouldn't 'application' visible models already be handed back from lasyerInstance().visibleXyz() ?? |
| Stream<? extends ModelDescriptor> modelsInLayer2 = concat( |
| moduleModel.layer().visibleObjects( Visibility.application ), |
| concat( |
| moduleModel.layer().visibleEntities( Visibility.application ), |
| concat( |
| moduleModel.layer().visibleTransients( Visibility.application ), |
| moduleModel.layer().visibleValues( Visibility.application ) |
| ) |
| ) |
| ); |
| Stream<? extends ModelDescriptor> layerModels = concat( |
| modelsInLayer1, |
| modelsInLayer2 |
| ).filter( modelTypeSpecification ); |
| |
| Iterator<? extends ModelDescriptor> layerModelsIter = layerModels.iterator(); |
| if( layerModelsIter.hasNext() ) |
| { |
| clazz = layerModelsIter.next().types().findFirst().orElse( null ); |
| |
| if( layerModelsIter.hasNext() ) |
| { |
| // Ambiguous exception |
| new AmbiguousTypeException( |
| "More than one model matches the classname " + name + ":" + layerModelsIter.next() |
| ); |
| } |
| } |
| } |
| |
| // Check used layers |
| if( clazz == null ) |
| { |
| Stream<? extends ModelDescriptor> usedLayersModels = concat( |
| moduleModel.layer() |
| .usedLayers() |
| .layers() |
| .flatMap( layer -> layer.visibleObjects( module ) ), |
| concat( |
| moduleModel.layer() |
| .usedLayers() |
| .layers() |
| .flatMap( layer -> layer.visibleEntities( Visibility.layer ) ), |
| concat( |
| moduleModel.layer() |
| .usedLayers() |
| .layers() |
| .flatMap( layer -> layer.visibleTransients( application ) ), |
| moduleModel.layer() |
| .usedLayers() |
| .layers() |
| .flatMap( layer -> layer.visibleValues( application ) ) |
| ) |
| ) |
| ).filter( modelTypeSpecification ); |
| |
| Iterator<? extends ModelDescriptor> usedLayersModelsIter = usedLayersModels.iterator(); |
| if( usedLayersModelsIter.hasNext() ) |
| { |
| clazz = usedLayersModelsIter.next().types().findFirst().orElse( null ); |
| |
| if( usedLayersModelsIter.hasNext() ) |
| { |
| // Ambiguous exception |
| new AmbiguousTypeException( |
| "More than one model matches the classname " + name + ":" + usedLayersModelsIter.next() |
| ); |
| } |
| } |
| } |
| return clazz; |
| } ); |
| if( resultingClass == null ) |
| { |
| throw new ClassNotFoundException(); |
| } |
| return resultingClass; |
| } |
| catch( AmbiguousTypeException e ) |
| { |
| throw new ClassNotFoundException( className, e ); |
| } |
| } |
| } |