blob: 961981f958774a166a0111986e27d804964b5909 [file] [log] [blame]
/*
* 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.apache.felix.atomos.utils.core;
import java.lang.reflect.Method;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Stream;
import org.apache.felix.atomos.utils.api.Context;
import org.apache.felix.atomos.utils.api.FileType;
import org.apache.felix.atomos.utils.api.RegisterServiceCall;
import org.apache.felix.atomos.utils.substrate.api.dynproxy.DynamicProxyConfiguration;
import org.apache.felix.atomos.utils.substrate.api.reflect.ReflectionConfiguration;
import org.apache.felix.atomos.utils.substrate.api.resource.ResourceConfiguration;
import org.apache.felix.atomos.utils.substrate.impl.config.DefaultDynamicProxyConfiguration;
import org.apache.felix.atomos.utils.substrate.impl.config.DefaultReflectionClassConfiguration;
import org.apache.felix.atomos.utils.substrate.impl.config.DefaultReflectionConfiguration;
import org.apache.felix.atomos.utils.substrate.impl.config.DefaultReflectionConstructorConfiguration;
import org.apache.felix.atomos.utils.substrate.impl.config.DefaultReflectionFieldConfiguration;
import org.apache.felix.atomos.utils.substrate.impl.config.DefaultReflectionMethodConfiguration;
import org.apache.felix.atomos.utils.substrate.impl.config.DefaultResourceConfiguration;
public class ContextImpl implements Context
{
private final Map<Path, FileType> paths = new HashMap<>();
private final Collection<DefaultReflectionClassConfiguration> reflectConfigs = new ArrayList<>();
private final List<RegisterServiceCall> registerServiceCalls = new ArrayList<>();
private final DefaultResourceConfiguration resourceConfig = new DefaultResourceConfiguration();
private final DefaultDynamicProxyConfiguration dynamicProxyConfigs = new DefaultDynamicProxyConfiguration();
@Override
public void addDynamicProxyConfigs(String... items)
{
dynamicProxyConfigs.addItem(items);
}
@Override
public void addFile(Path path, FileType type)
{
//maybe copy
paths.put(path, type);
}
@Override
//parameterTypes==null means not Set
//parameterTypes=={} means no method parameter
public void addReflecionMethod(String mName, Class<?>[] parameterTypes,
Class<?> clazz)
{
for (Method m : clazz.getDeclaredMethods())
{
if (mName.equals(m.getName()))
{
if (parameterTypes == null)
{
DefaultReflectionClassConfiguration config = computeIfAbsent(
clazz.getName());
config.add(new DefaultReflectionMethodConfiguration(mName, null));
break;
}
else if (Arrays.equals(m.getParameterTypes(), parameterTypes))
{
DefaultReflectionClassConfiguration config = computeIfAbsent(
clazz.getName());
String[] sParameterTypes = Stream.of(parameterTypes).sequential().map(
Class::getName).toArray(String[]::new);
config.add(
new DefaultReflectionMethodConfiguration(mName, sParameterTypes));
break;
}
}
}
Class<?> superClass = clazz.getSuperclass();
if (superClass != null)
{
addReflecionMethod(mName, parameterTypes, superClass);
}
}
@Override
public void addReflectionClass(String className)
{
computeIfAbsent(className);
}
@Override
public void addReflectionConstructor(String bundleActivatorClassName,
String[] parameterTypeNames)
{
computeIfAbsent(bundleActivatorClassName).add(
new DefaultReflectionConstructorConfiguration(parameterTypeNames));
}
@Override
public void addReflectionConstructorAllPublic(String clazzName)
{
computeIfAbsent(clazzName).setAllPublicConstructors(true);
}
@Override
public void addReflectionField(String fName, Class<?> clazz)
{
boolean exists = Stream.of(clazz.getDeclaredFields()).anyMatch(
f -> f.getName().equals(fName));
if (exists)
{
DefaultReflectionClassConfiguration config = computeIfAbsent(clazz.getName());
config.add(new DefaultReflectionFieldConfiguration(fName));
}
Class<?> superClass = clazz.getSuperclass();
if (superClass != null)
{
addReflectionField(fName, superClass);
}
}
@Override
public void addReflectionFieldsAllPublic(String className)
{
computeIfAbsent(className).setAllPublicFields(true);
}
@Override
public void addReflectionMethodsAllPublic(String className)
{
computeIfAbsent(className).setAllPublicMethods(true);
}
@Override
public void addRegisterServiceCalls(RegisterServiceCall registerServiceCall)
{
registerServiceCalls.add(registerServiceCall);
}
@Override
public void addResourceConfig(ResourceConfiguration resourceConfig)
{
this.resourceConfig.addResourcePackage(resourceConfig.getResourcePackages());
this.resourceConfig.addResourcePattern(resourceConfig.getResourcePatterns());
this.resourceConfig.addResourceBundle(resourceConfig.getResourceBundles());
}
private DefaultReflectionClassConfiguration computeIfAbsent(final String className)
{
Optional<DefaultReflectionClassConfiguration> oConfig = reflectConfigs.stream().filter(
c -> c.getClassName().equals(className)).findFirst();
DefaultReflectionClassConfiguration rc = null;
if (oConfig.isPresent())
{
rc = oConfig.get();
}
else
{
rc = new DefaultReflectionClassConfiguration(className);
reflectConfigs.add(rc);
}
return rc;
}
@Override
public DynamicProxyConfiguration getDynamicProxyConfig()
{
return dynamicProxyConfigs;
}
@Override
public Stream<Path> getFiles(FileType... fileType)
{
return paths.entrySet().parallelStream().filter(
e -> List.of(fileType).stream().filter(Objects::nonNull).anyMatch(
t -> t.equals(e.getValue()))).map(Entry::getKey);
}
Map<Path, FileType> getPaths()
{
return Map.copyOf(paths);
}
@Override
public ReflectionConfiguration getReflectConfig()
{
return new DefaultReflectionConfiguration(List.copyOf(reflectConfigs));
}
@Override
public List<RegisterServiceCall> getRegisterServiceCalls()
{
return registerServiceCalls;
}
@Override
public ResourceConfiguration getResourceConfig()
{
return resourceConfig;
}
}