/**
* Copyright 2014 Otto (GmbH & Co KG)
*
* 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 com.ottogroup.bi.spqr.repository;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import org.apache.commons.lang3.StringUtils;
import com.ottogroup.bi.spqr.exception.RequiredInputMissingException;
import com.ottogroup.bi.spqr.pipeline.component.MicroPipelineComponent;
import com.ottogroup.bi.spqr.repository.exception.ComponentInstantiationFailedException;
import com.ottogroup.bi.spqr.repository.exception.UnknownComponentException;
/**
* Manages all configured component repositories. For each it creates a new {@link CachedComponentClassLoader} to keep
* classes isolated and thus support multi-version implementation
* @author mnxfst
* @since Dec 2, 2014
* TODO testing
*/
public class ComponentRepository {
/** list of all existing component class loaders */
private final List<CachedComponentClassLoader> componentClassLoaders = new ArrayList<>();
/**
* Adds a new folder to the repository
* @throws RequiredInputMissingException
* @throws IOException
*/
public Map<String, ComponentDescriptor> addComponentFolder(final String componentFolder) throws RequiredInputMissingException, IOException {
//////////////////////////////////////////////////////////////////////////////////////////
// validate provided input
if(StringUtils.isBlank(componentFolder)) {
throw new RequiredInputMissingException("Missing required component folder");
}
//
//////////////////////////////////////////////////////////////////////////////////////////
CachedComponentClassLoader componentClassLoader = new CachedComponentClassLoader(CachedComponentClassLoader.class.getClassLoader());
componentClassLoader.initialize(componentFolder);
this.componentClassLoaders.add(componentClassLoader);
return componentClassLoader.getManagedComponents();
}
/**
* Adds a component class loader explicitly - currently used for testing purpose only
* @param cachedComponentClassLoader
*/
protected void addComponentClassLoader(final CachedComponentClassLoader cachedComponentClassLoader) {
this.componentClassLoaders.add(cachedComponentClassLoader);
}
/**
* Looks up the reference {@link DataComponent}, instantiates it and passes over the provided {@link Properties}
* @param name name of component to instantiate (required)
* @param version version of component to instantiate (required)
* @param properties properties to use for instantiation
* @return
* @throws RequiredInputMissingException thrown in case a required parameter value is missing
* @throws ComponentInstantiationFailedException thrown in case the instantiation failed for any reason
* @throws UnknownComponentException thrown in case the name and version combination does not reference a managed component
*/
public MicroPipelineComponent newInstance(final String id, final String name, final String version, final Properties properties)
throws RequiredInputMissingException, ComponentInstantiationFailedException, UnknownComponentException {
//////////////////////////////////////////////////////////////////////////////////////////
// validate provided input
if(StringUtils.isBlank(id))
throw new RequiredInputMissingException("Missing required component id");
if(StringUtils.isBlank(name))
throw new RequiredInputMissingException("Missing required component name");
if(StringUtils.isBlank(version))
throw new RequiredInputMissingException("Missing required component version");
//
//////////////////////////////////////////////////////////////////////////////////////////
for(CachedComponentClassLoader pccl : this.componentClassLoaders) {
if(pccl.isManagedComponent(name, version)) {
return pccl.newInstance(id, name, version, properties);
}
}
throw new UnknownComponentException("Unknown component [name="+name+", version="+version+"]");
}
}