| package org.apache.hawq.pxf.api.utilities; |
| |
| /* |
| * 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. |
| */ |
| |
| |
| import org.apache.commons.collections.IteratorUtils; |
| import org.apache.commons.configuration.Configuration; |
| import org.apache.commons.configuration.ConfigurationException; |
| import org.apache.commons.configuration.XMLConfiguration; |
| import org.apache.commons.lang.StringUtils; |
| import org.apache.commons.logging.Log; |
| import org.apache.commons.logging.LogFactory; |
| |
| import java.net.URL; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.TreeMap; |
| |
| import static org.apache.hawq.pxf.api.utilities.ProfileConfException.MessageFormat.*; |
| |
| /** |
| * This enum holds the profiles files: pxf-profiles.xml and pxf-profiles-default.xml. |
| * It exposes a public static method getProfilePluginsMap(String plugin) which returns the requested profile plugins |
| */ |
| public enum ProfilesConf { |
| INSTANCE; // enum singleton |
| // not necessary to declare LOG as static final, because this is a singleton |
| private Log LOG = LogFactory.getLog(ProfilesConf.class); |
| private Map<String, Map<String, String>> profilesMap; |
| private final static String EXTERNAL_PROFILES = "pxf-profiles.xml"; |
| private final static String INTERNAL_PROFILES = "pxf-profiles-default.xml"; |
| |
| /** |
| * Constructs the ProfilesConf enum singleton instance. |
| * <p/> |
| * External profiles take precedence over the internal ones and override them. |
| */ |
| private ProfilesConf() { |
| profilesMap = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); |
| loadConf(INTERNAL_PROFILES, true); |
| loadConf(EXTERNAL_PROFILES, false); |
| if (profilesMap.isEmpty()) { |
| throw new ProfileConfException(PROFILES_FILE_NOT_FOUND, EXTERNAL_PROFILES); |
| } |
| LOG.info("PXF profiles loaded: " + profilesMap.keySet()); |
| } |
| |
| /** |
| * Get requested profile plugins map. |
| * In case pxf-profiles.xml is not on the classpath, or it doesn't contains the requested profile, |
| * Fallback to pxf-profiles-default.xml occurs (@see useProfilesDefaults(String msgFormat)) |
| * |
| * @param profile The requested profile |
| * @return Plugins map of the requested profile |
| */ |
| public static Map<String, String> getProfilePluginsMap(String profile) { |
| Map<String, String> pluginsMap = INSTANCE.profilesMap.get(profile); |
| if (pluginsMap == null) { |
| throw new ProfileConfException(NO_PROFILE_DEF, profile, EXTERNAL_PROFILES); |
| } |
| return pluginsMap; |
| } |
| |
| private ClassLoader getClassLoader() { |
| ClassLoader cL = Thread.currentThread().getContextClassLoader(); |
| return (cL != null) |
| ? cL |
| : ProfilesConf.class.getClassLoader(); |
| } |
| |
| private void loadConf(String fileName, boolean isMandatory) { |
| URL url = getClassLoader().getResource(fileName); |
| if (url == null) { |
| LOG.warn(fileName + " not found in the classpath"); |
| if (isMandatory) { |
| throw new ProfileConfException(PROFILES_FILE_NOT_FOUND, fileName); |
| } |
| return; |
| } |
| try { |
| XMLConfiguration conf = new XMLConfiguration(url); |
| loadMap(conf); |
| } catch (ConfigurationException e) { |
| throw new ProfileConfException(PROFILES_FILE_LOAD_ERR, url.getFile(), String.valueOf(e.getCause())); |
| } |
| } |
| |
| private void loadMap(XMLConfiguration conf) { |
| String[] profileNames = conf.getStringArray("profile.name"); |
| if (profileNames.length == 0) { |
| LOG.warn("Profile file: " + conf.getFileName() + " is empty"); |
| return; |
| } |
| Map<String, Map<String, String>> profileMap = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); |
| for (int profileIdx = 0; profileIdx < profileNames.length; profileIdx++) { |
| String profileName = profileNames[profileIdx]; |
| if (profileMap.containsKey(profileName)) { |
| LOG.warn("Duplicate profile definition found in " + conf.getFileName() + " for: " + profileName); |
| continue; |
| } |
| Configuration profileSubset = conf.subset("profile(" + profileIdx + ").plugins"); |
| profileMap.put(profileName, getProfilePluginMap(profileSubset)); |
| } |
| profilesMap.putAll(profileMap); |
| } |
| |
| private Map<String, String> getProfilePluginMap(Configuration profileSubset) { |
| @SuppressWarnings("unchecked") //IteratorUtils doesn't yet support generics. |
| List<String> plugins = IteratorUtils.toList(profileSubset.getKeys()); |
| Map<String, String> pluginsMap = new HashMap<>(); |
| for (String plugin : plugins) { |
| String pluginValue = profileSubset.getString(plugin); |
| if (!StringUtils.isEmpty(StringUtils.trim(pluginValue))) { |
| pluginsMap.put("X-GP-" + plugin.toUpperCase(), pluginValue); |
| } |
| } |
| return pluginsMap; |
| } |
| } |