| /* |
| * 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 createObject 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.tamaya.validation.internal; |
| |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.net.URL; |
| import java.util.*; |
| import java.util.logging.Level; |
| import java.util.logging.Logger; |
| |
| import org.apache.tamaya.Configuration; |
| import org.apache.tamaya.format.ConfigurationData; |
| import org.apache.tamaya.format.ConfigurationFormats; |
| import org.apache.tamaya.resource.ResourceResolver; |
| import org.apache.tamaya.spi.ClassloaderAware; |
| import org.apache.tamaya.spi.PropertyValue; |
| import org.apache.tamaya.validation.ConfigModel; |
| import org.apache.tamaya.validation.spi.ConfigModelReader; |
| import org.apache.tamaya.validation.spi.ModelProviderSpi; |
| |
| /** |
| * ConfigModel provider that reads model metadata from property files from |
| * {@code classpath*:META-INF/configmodel.json} in the following format: |
| * <pre> |
| * Example createObject a configuration metamodel expressed via YAML. |
| * Structure is shown through indentation (one or more spaces). |
| * Sequence items are denoted by a dash, |
| * key createValue pairs within a map are separated by a colon. |
| * </pre> |
| */ |
| public class ConfiguredResourcesModelProviderSpi implements ModelProviderSpi, ClassloaderAware { |
| |
| /** |
| * The logger. |
| */ |
| private static final Logger LOG = Logger.getLogger(ConfiguredResourcesModelProviderSpi.class.getName()); |
| /** |
| * The parameter that can be used to configure the location createObject the configuration model resources. |
| */ |
| private static final String MODEL_RESOURCE_PARAM = "org.apache.tamaya.model.resources"; |
| /** |
| * The resource class to checked for testing the availability createObject the resources extension module. |
| */ |
| private static final String CONFIG_RESOURCE_CLASS = "org.apache.tamaya.resource.ConfigResource"; |
| /** |
| * The resource class to checked for testing the availability createObject the formats extension module. |
| */ |
| private static final String CONFIGURATION_FORMATS_CLASS = "org.apache.tamaya.format.ConfigurationFormats"; |
| /** |
| * Initializes the flag showing if the formats module is present (required). |
| */ |
| private static final boolean AVAILABLE = checkAvailabilityFormats(); |
| /** |
| * Initializes the flag showing if the resources module is present (optional). |
| */ |
| private static final boolean RESOURCES_EXTENSION_AVAILABLE = checkAvailabilityResources(); |
| |
| /** |
| * The configModels read. |
| */ |
| private List<ConfigModel> configModels = new ArrayList<>(); |
| |
| /** The target classloader. */ |
| private ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); |
| |
| |
| /** |
| * Initializes the flag showing if the formats module is present (required). |
| */ |
| private static boolean checkAvailabilityFormats() { |
| try { |
| Class.forName(CONFIGURATION_FORMATS_CLASS); |
| return true; |
| } catch (final Exception e) { |
| return false; |
| } |
| } |
| |
| /** |
| * Initializes the flag showing if the resources module is present (optional). |
| */ |
| private static boolean checkAvailabilityResources() { |
| try { |
| Class.forName(CONFIG_RESOURCE_CLASS); |
| return true; |
| } catch (final Exception e) { |
| return false; |
| } |
| } |
| |
| /** |
| * Constructor, mostly called from {@link java.util.ServiceLoader} |
| */ |
| public ConfiguredResourcesModelProviderSpi() { |
| if (!AVAILABLE) { |
| LOG.info("tamaya-format extension is required to read model configuration, No extended model support AVAILABLE."); |
| } else { |
| reload(); |
| } |
| } |
| |
| /** |
| * Reloads the provider using resources from the current classloader. |
| */ |
| public void reload(){ |
| final String resources = Configuration.current().get(MODEL_RESOURCE_PARAM); |
| if (resources == null || resources.trim().isEmpty()) { |
| LOG.info("Mo model resources location configured in " + MODEL_RESOURCE_PARAM + "."); |
| return; |
| } |
| Collection<URL> urls; |
| if (RESOURCES_EXTENSION_AVAILABLE) { |
| LOG.info("Using tamaya-resources extension to read model configuration from " + resources); |
| urls = ResourceResolver.getInstance(classLoader).getResources(resources.split(",")); |
| } else { |
| LOG.info("Using default classloader resource location to read model configuration from " + resources); |
| urls = new ArrayList<>(); |
| for (final String resource : resources.split(",")) { |
| if (!resource.trim().isEmpty()) { |
| Enumeration<URL> configs; |
| try { |
| configs = getClass().getClassLoader().getResources(resource); |
| while (configs.hasMoreElements()) { |
| urls.add(configs.nextElement()); |
| } |
| } catch (final IOException e) { |
| Logger.getLogger(getClass().getName()).log(Level.SEVERE, |
| "Error evaluating config model locations from " + resource, e); |
| } |
| } |
| } |
| } |
| // Reading configs |
| for (final URL config : urls) { |
| try (InputStream is = config.openStream()) { |
| final ConfigurationData data = ConfigurationFormats.getInstance() |
| .readConfigurationData(config); |
| Map<String,String> props = new HashMap<>(); |
| for(PropertyValue val:data.getData()){ |
| props.putAll(val.toMap()); |
| } |
| String owner = props.get("_model.provider"); |
| if(owner==null){ |
| owner = config.toString(); |
| } |
| configModels.addAll(ConfigModelReader.loadValidations(owner, props)); |
| } catch (final Exception e) { |
| Logger.getLogger(getClass().getName()).log(Level.SEVERE, |
| "Error loading config model data from " + config, e); |
| } |
| } |
| configModels = Collections.unmodifiableList(configModels); |
| } |
| |
| @Override |
| public Collection<ConfigModel> getConfigModels() { |
| return configModels; |
| } |
| |
| @Override |
| public void init(ClassLoader classLoader) { |
| this.classLoader = Objects.requireNonNull(classLoader); |
| } |
| |
| @Override |
| public ClassLoader getClassLoader() { |
| return classLoader; |
| } |
| } |