/*
 * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0, which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the
 * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
 * version 2 with the GNU Classpath Exception, which is available at
 * https://www.gnu.org/software/classpath/license.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 */

package com.sun.enterprise.config.modularity;

import static com.sun.enterprise.config.util.ConfigApiLoggerInfo.*;

import com.sun.enterprise.config.modularity.annotation.CustomConfiguration;
import com.sun.enterprise.config.modularity.annotation.HasCustomizationTokens;
import com.sun.enterprise.config.modularity.customization.ConfigBeanDefaultValue;
import com.sun.enterprise.config.modularity.customization.ConfigCustomizationToken;
import com.sun.enterprise.config.modularity.parser.ConfigurationPopulator;
import com.sun.enterprise.config.modularity.parser.ModuleXMLConfigurationFileParser;
import com.sun.enterprise.config.serverbeans.Application;
import com.sun.enterprise.config.serverbeans.Applications;
import com.sun.enterprise.config.serverbeans.Config;
import com.sun.enterprise.config.serverbeans.Domain;
import com.sun.enterprise.config.serverbeans.Module;
import com.sun.enterprise.config.serverbeans.Resource;
import com.sun.enterprise.config.serverbeans.Server;
import com.sun.enterprise.config.serverbeans.SystemProperty;
import com.sun.enterprise.config.serverbeans.SystemPropertyBag;
import com.sun.enterprise.module.bootstrap.StartupContext;
import com.sun.enterprise.util.LocalStringManager;
import com.sun.enterprise.util.LocalStringManagerImpl;

import org.glassfish.api.admin.RuntimeType;
import org.glassfish.api.admin.ServerEnvironment;
import org.glassfish.api.admin.config.Named;
import org.glassfish.api.logging.LogHelper;
import org.glassfish.config.support.GlassFishConfigBean;
import org.glassfish.config.support.Singleton;
import org.glassfish.hk2.api.ActiveDescriptor;
import org.glassfish.hk2.api.ServiceLocator;
import org.glassfish.hk2.utilities.BuilderHelper;
import org.jvnet.hk2.annotations.Service;
import org.jvnet.hk2.config.Attribute;
import org.jvnet.hk2.config.ConfigBeanProxy;
import org.jvnet.hk2.config.ConfigInjector;
import org.jvnet.hk2.config.ConfigModel;
import org.jvnet.hk2.config.ConfigParser;
import org.jvnet.hk2.config.ConfigSupport;
import org.jvnet.hk2.config.ConfigView;
import org.jvnet.hk2.config.Configured;
import org.jvnet.hk2.config.Dom;
import org.jvnet.hk2.config.DomDocument;
import org.jvnet.hk2.config.DuckTyped;
import org.jvnet.hk2.config.IndentingXMLStreamWriter;
import org.jvnet.hk2.config.SingleConfigCode;
import org.jvnet.hk2.config.TransactionFailure;

import jakarta.inject.Inject;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.XMLStreamWriter;

import java.beans.PropertyVetoException;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Proxy;
import java.lang.reflect.Type;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Properties;
import java.util.StringTokenizer;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Contains utility methods for zero-config
 *
 * @author Masoud Kalali
 */
@Service
@Singleton
public final class ConfigModularityUtils {

    private static final Logger LOG = getLogger();

    @Inject
    private ServiceLocator serviceLocator;
    @Inject
    private StartupContext context;

    private boolean ignorePersisting = false;
    private boolean isCommandInvocation = false;

    public <U extends ConfigBeanProxy> URL getConfigurationFileUrl(Class<U> configBeanClass, String baseFileName, String runtimeType) {
        //TODO can be optimized a little by checking the default file...
        String fileName = runtimeType + "-" + baseFileName;
        URL fileUrl = configBeanClass.getClassLoader().getResource("META-INF/configuration/" + fileName);
        if (fileUrl == null) {
            fileUrl = configBeanClass.getClassLoader().getResource("META-INF/configuration/" + baseFileName);
        }
        return fileUrl;
    }

    /**
     * If exists, locate and return a URL to the configuration snippet for the given config bean class.
     *
     * @param configBeanClass the config bean type we want to check for its configuration snippet
     * @return A url to the file or null of not exists
     */
    public List<ConfigBeanDefaultValue> getDefaultConfigurations(Class configBeanClass, String runtimeType) {

        //Determine if it is DAS or instance
        CustomConfiguration c = (CustomConfiguration) configBeanClass.getAnnotation(CustomConfiguration.class);
        List<ConfigBeanDefaultValue> defaults = Collections.emptyList();
        if (c.usesOnTheFlyConfigGeneration()) {
            Method m = getGetDefaultValuesMethod(configBeanClass);
            if (m != null) {
                try {
                    defaults = (List<ConfigBeanDefaultValue>) m.invoke(null, runtimeType);
                } catch (Exception e) {
                    LogHelper.log(LOG, Level.INFO, cannotGetDefaultConfig, e, configBeanClass.getName());
                }
            }
        } else {
            //TODO properly handle the exceptions
            LocalStringManager localStrings = new LocalStringManagerImpl(configBeanClass);
            ModuleXMLConfigurationFileParser parser = new ModuleXMLConfigurationFileParser(localStrings);
            try {
                defaults = parser.parseServiceConfiguration(
                        getConfigurationFileUrl(configBeanClass, c.baseConfigurationFileName(), runtimeType).openStream());
            } catch (XMLStreamException e) {
                LOG.log(Level.SEVERE, cannotParseDefaultDefaultConfig, e);
            } catch (IOException e) {
                LOG.log(Level.SEVERE, cannotParseDefaultDefaultConfig, e);
            }
        }
        return defaults;
    }

    public boolean hasCustomConfig(Class configBeanClass) {
        return configBeanClass.getAnnotation(CustomConfiguration.class) != null;
    }

    /**
     * Find a getter method that returns a collection of the type we want to put set.
     *
     * @param owner The class we want to search to find a method that returns a Collection typed with toSetType
     * @param typeToSet The type we want to find a matching collection fo
     * @return The Method that
     */
    public Method findSuitableCollectionGetter(Class owner, Class typeToSet) {
        Method[] methods = owner.getMethods();
        Method tm = returnException(owner, typeToSet);
        if (tm != null)
            return tm;
        for (Method m : methods) {
            if (m.getName().startsWith("get")) {
                Type t = m.getGenericReturnType();
                if (t instanceof ParameterizedType) {
                    ParameterizedType pt = (ParameterizedType) t;
                    Type actualGenericParameter = pt.getActualTypeArguments()[0];
                    if (pt.getActualTypeArguments().length == 1) {
                        if (Collection.class.isAssignableFrom(m.getReturnType())) {
                            if (actualGenericParameter instanceof Class) {
                                if (typeToSet.isAssignableFrom((Class) actualGenericParameter)) {
                                    if ((m.getAnnotation(DuckTyped.class) != null)) {
                                        return m;
                                    } else {
                                        Method deepM = findDeeperSuitableCollectionGetter(owner, typeToSet);
                                        return deepM != null ? deepM : m;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        return findDeeperSuitableCollectionGetter(owner, typeToSet);
    }

    private Method returnException(Class owner, Class typeToSet) {
        if (owner.isAssignableFrom(Applications.class) && (typeToSet.isAssignableFrom(Application.class))
                || typeToSet.isAssignableFrom(Module.class)) {
            try {
                Method m = owner.getMethod("getModules");
                return m;
            } catch (NoSuchMethodException e) {
                LogHelper.log(LOG, Level.INFO, noMethodInReturnException, e, owner.getName(), typeToSet.getName());
            }
        }
        return null;
    }

    public Method findDeeperSuitableCollectionGetter(Class owner, Class typeToSet) {
        Class[] ifs = typeToSet.getInterfaces();
        Method[] methods = owner.getMethods();
        for (Method m : methods) {
            if (m.getName().startsWith("get")) {
                Type t = m.getGenericReturnType();
                if (t instanceof ParameterizedType) {
                    ParameterizedType pt = (ParameterizedType) t;
                    Type actualGenericParameter = pt.getActualTypeArguments()[0];
                    if (pt.getActualTypeArguments().length == 1) {
                        if (Collection.class.isAssignableFrom(m.getReturnType())) {
                            if (actualGenericParameter instanceof Class) {
                                if (checkInterfaces(ifs, actualGenericParameter)) {
                                    return m;
                                }
                            }
                        }
                    }
                }
            }
        }

        return null;
    }

    public boolean checkInterfaces(Class[] ifs, Type actualGenericParameter) {
        for (Class clz : ifs) {
            if (clz.getSimpleName().equals("ConfigBeanProxy") || clz.getSimpleName().equals("Injectable")
                    || clz.getSimpleName().equals("PropertyBag")) {
                continue;
            }
            if (actualGenericParameter instanceof Class && clz.isAssignableFrom((Class) actualGenericParameter)) {
                return true;
            }
        }
        return false;
    }

    public Class getOwningClassForLocation(String location) {
        StringTokenizer tokenizer = new StringTokenizer(location, "/", false);
        if (!tokenizer.hasMoreElements())
            return null;
        if (!tokenizer.nextToken().equalsIgnoreCase("domain"))
            return null;
        String level = "domain";
        if (location.equalsIgnoreCase("domain/configs"))
            return getClassFor("domain");
        //It is a named config so we shall just return the config class
        if ((tokenizer.countTokens() == 2) && location.startsWith("domain/configs")) {
            return Config.class;
        }
        while (tokenizer.hasMoreElements()) {
            level = tokenizer.nextToken();
        }
        return getClassFor(level);
    }

    public ConfigBeanProxy getOwningObject(String location) {
        if (!location.startsWith("domain/configs")) {
            if (!location.startsWith("domain")) {
                //Sorry only know domain and below :D
                return null;
            }
            StringTokenizer tokenizer = new StringTokenizer(location, "/", false);
            //something directly inside the domain itself as we know one token is domain for sure
            if (tokenizer.countTokens() == 1) {
                return serviceLocator.getService(Domain.class);
            }
            location = location.substring(location.indexOf("/", "domain".length()) + 1);
            tokenizer = new StringTokenizer(location, "/", false);
            ConfigBeanProxy parent = serviceLocator.getService(Domain.class);

            //skipping the domain itself as a token, we know it and took it away.
            String parentElement = "domain";
            String childElement = null;
            while (tokenizer.hasMoreTokens()) {
                try {
                    childElement = tokenizer.nextToken();
                    parent = getOwner(parent, parentElement, childElement);
                    parentElement = childElement;
                } catch (Exception e) {
                    LogHelper.log(LOG, Level.INFO, cannotGetParentConfigBean, e, childElement);
                }
            }
            return parent;
        } else {
            Class typeToFindGetter = getOwningClassForLocation(location);
            if (typeToFindGetter == null) {
                return null;
            }

            //Check if config object is where the location or it goes deeper in the config layers.
            StringTokenizer tokenizer = new StringTokenizer(location, "/", false);
            //something directly inside the config itself
            if (tokenizer.countTokens() == 3) {
                String expression = location.substring(location.lastIndexOf("[") + 1, location.length() - 1);
                String configName = resolveExpression(expression);
                return serviceLocator.<Domain>getService(Domain.class).getConfigNamed(configName);
            }

            location = location.substring(location.indexOf("/", "domain/configs".length()) + 1);
            tokenizer = new StringTokenizer(location, "/", false);
            String curLevel = tokenizer.nextToken();
            String expression;
            if (curLevel.contains("[")) {
                expression = curLevel.substring(curLevel.lastIndexOf("[") + 1, curLevel.length() - 1);
            } else {
                expression = curLevel;
            }

            String configName = resolveExpression(expression);
            ConfigBeanProxy parent = serviceLocator.<Domain>getService(Domain.class).getConfigNamed(configName);

            String childElement;
            String parentElement = "Config";
            while (tokenizer.hasMoreTokens()) {
                try {
                    childElement = tokenizer.nextToken();
                    parent = getOwner(parent, parentElement, childElement);
                    parentElement = childElement;
                } catch (Exception e) {
                    LogHelper.log(LOG, Level.INFO, cannotGetParentConfigBean, e, configName);
                }
            }
            return parent;
        }
    }

    public ConfigBeanProxy getOwner(ConfigBeanProxy parent, String parentElement, String childElement)
            throws InvocationTargetException, IllegalAccessException {

        if (childElement.contains("CURRENT_INSTANCE_CONFIG_NAME")) {
            return serviceLocator.<Config>getService(Config.class, ServerEnvironment.DEFAULT_INSTANCE_NAME);
        }
        if (childElement.contains("CURRENT_INSTANCE_SERVER_NAME")) {
            return serviceLocator.<Server>getService(Server.class, ServerEnvironment.DEFAULT_INSTANCE_NAME);
        }
        if (childElement.endsWith("]")) {
            String componentName;
            String elementName;
            elementName = childElement.substring(childElement.lastIndexOf("/") + 1, childElement.indexOf("["));
            componentName = childElement.substring(childElement.lastIndexOf("[") + 1, childElement.indexOf("]"));
            Class childClass = getClassFor(elementName);
            Class parentClass = getClassFor(parentElement);
            Method m = findSuitableCollectionGetter(parentClass, childClass);
            if (m != null) {
                try {
                    Collection col = (Collection) m.invoke(parent);
                    componentName = resolveExpression(componentName);
                    return getNamedConfigBeanFromCollection(col, componentName, childClass);
                } catch (Exception e) {
                    LogHelper.log(LOG, Level.INFO, invalidPath, e, childElement, componentName);
                }
            }
            return null;
        } else {
            Class clz = getClassFor(childElement);
            if (parent == null)
                return null;
            Method m = getMatchingGetterMethod(parent.getClass(), clz);
            if (m != null) {
                return (ConfigBeanProxy) m.invoke(parent);
            } else {

                try {
                    m = parent.getClass().getMethod("getExtensionByType", java.lang.Class.class);
                } catch (NoSuchMethodException e) {
                    if (LOG.isLoggable(Level.FINE)) {
                        LOG.log(Level.FINE, "Cannot find getExtensionByType", e);
                    }
                }
                if (m != null) {
                    return (ConfigBeanProxy) m.invoke(parent, clz);
                }
                return null;
            }
        }
    }

    public <U extends ConfigBeanProxy> List<U> getExtensions(ConfigBeanProxy parent) {

        Method m = null;
        try {
            if (parent != null) {
                m = parent.getClass().getMethod("getExtensions");
            }
        } catch (NoSuchMethodException e) {
        }
        if (m != null) {
            try {
                return (List<U>) m.invoke(parent);
            } catch (Exception e) {

            }
        }
        return Collections.emptyList();
    }

    public <T extends ConfigBeanProxy> T setConfigBean(T finalConfigBean, ConfigBeanDefaultValue configBeanDefaultValue,
            ConfigBeanProxy parent) {
        Class owningClassForLocation = getOwningClassForLocation(configBeanDefaultValue.getLocation());
        Class configBeanClass = getClassForFullName(configBeanDefaultValue.getConfigBeanClassName());

        try {
            ConfigBeanProxy configBeanInstance = null;
            if (getNameForConfigBean(finalConfigBean, configBeanClass) == null) {
                List<ConfigBeanProxy> extensions = getExtensions(parent);
                for (ConfigBeanProxy extension : extensions) {
                    try {
                        configBeanInstance = (ConfigBeanProxy) configBeanClass.cast(extension);
                        break;
                    } catch (Exception e) {
                        // ignore, not the right type.
                    }
                }
                if (!configBeanDefaultValue.replaceCurrentIfExists() || !stackPositionHigher(finalConfigBean, configBeanInstance)) {
                    if (configBeanInstance != null)
                        return (T) configBeanInstance;
                }
                if (configBeanInstance != null) {
                    extensions.remove(configBeanInstance);
                }
            }

        } catch (InvocationTargetException e) {
            LOG.log(Level.INFO, cannotSetConfigBean, e);
        } catch (IllegalAccessException e) {
            LOG.log(Level.INFO, cannotSetConfigBean, e);
        }

        Method m = getMatchingSetterMethod(owningClassForLocation, configBeanClass);
        if (m != null) {
            try {
                if (configBeanClass.getAnnotation(HasCustomizationTokens.class) != null) {
                    applyCustomTokens(configBeanDefaultValue, finalConfigBean, parent);
                }
                m.invoke(parent, finalConfigBean);
            } catch (Exception e) {
                LogHelper.log(LOG, Level.INFO, cannotSetConfigBeanFor, e, finalConfigBean.getClass().getName());
            }
            return finalConfigBean;
        }

        m = findSuitableCollectionGetter(owningClassForLocation, configBeanClass);
        if (m != null) {
            try {
                Collection col = (Collection) m.invoke(parent);
                String name = getNameForConfigBean(finalConfigBean, configBeanClass);
                ConfigBeanProxy itemToRemove = getNamedConfigBeanFromCollection(col, name, configBeanClass);
                if (configBeanDefaultValue.replaceCurrentIfExists()) {
                    try {
                        if (itemToRemove != null) {
                            if (stackPositionHigher(finalConfigBean, itemToRemove)) {
                                col.remove(itemToRemove);
                            }
                        }
                    } catch (Exception ex) {
                        LogHelper.log(LOG, Level.INFO, cannotRemoveConfigBean, ex, finalConfigBean.getClass().getName());
                    }
                }
                if (configBeanClass.getAnnotation(HasCustomizationTokens.class) != null) {
                    applyCustomTokens(configBeanDefaultValue, finalConfigBean, parent);
                }
                if (itemToRemove != null && !configBeanDefaultValue.replaceCurrentIfExists()) {
                    //Check for duplication here.
                    if (((ConfigView) Proxy.getInvocationHandler(itemToRemove)).getProxyType().isAssignableFrom(configBeanClass)) {
                        return finalConfigBean;
                    }
                }
                col.add(finalConfigBean);
                return finalConfigBean;
            } catch (Exception e) {
                LogHelper.log(LOG, Level.INFO, cannotSetConfigBeanFor, e, finalConfigBean.getClass().getName());
            }
        }
        return null;
    }

    public <T extends ConfigBeanProxy> boolean stackPositionHigher(T finalConfigBean, ConfigBeanProxy itemToRemove) {
        if (itemToRemove == null || finalConfigBean == null)
            return true;
        if (RankedConfigBeanProxy.class.isAssignableFrom(finalConfigBean.getClass())
                && RankedConfigBeanProxy.class.isAssignableFrom(itemToRemove.getClass())) {
            int itemToRemoveRank = Integer.parseInt(((RankedConfigBeanProxy) itemToRemove).getRank());
            int finalConfigBeanRank = Integer.parseInt(((RankedConfigBeanProxy) finalConfigBean).getRank());
            return finalConfigBeanRank > itemToRemoveRank;
        } else {
            return true;
        }

    }

    public synchronized <T extends ConfigBeanProxy> void applyCustomTokens(final ConfigBeanDefaultValue configBeanDefaultValue,
            T finalConfigBean, ConfigBeanProxy parent) throws TransactionFailure, PropertyVetoException {
        //go up in the parents tree till meet someone ImplementingSystemProperty
        //then that is the freaking parent, get it and set the SystemProperty :D
        if (parent instanceof SystemPropertyBag) {
            addSystemPropertyForToken(configBeanDefaultValue.getCustomizationTokens(), (SystemPropertyBag) parent);
        } else {
            ConfigBeanProxy curParent = finalConfigBean;
            while (!(curParent instanceof SystemPropertyBag)) {
                curParent = curParent.getParent();
            }
            if (configBeanDefaultValue.getCustomizationTokens().size() != 0) {
                final boolean oldIP = isIgnorePersisting();
                try {
                    setIgnorePersisting(true);
                    final SystemPropertyBag bag = (SystemPropertyBag) curParent;
                    final List<ConfigCustomizationToken> tokens = configBeanDefaultValue.getCustomizationTokens();
                    ConfigSupport.apply(new SingleConfigCode<SystemPropertyBag>() {
                        public Object run(SystemPropertyBag param) throws PropertyVetoException, TransactionFailure {
                            addSystemPropertyForToken(tokens, bag);
                            return param;
                        }
                    }, bag);
                } finally {
                    setIgnorePersisting(oldIP);
                }
            }
        }
    }

    public void addSystemPropertyForToken(List<ConfigCustomizationToken> tokens, SystemPropertyBag bag)
            throws TransactionFailure, PropertyVetoException {
        for (ConfigCustomizationToken token : tokens) {
            if (!bag.containsProperty(token.getName())) {
                SystemProperty prop = bag.createChild(SystemProperty.class);
                prop.setName(token.getName());
                prop.setDescription(token.getDescription());
                prop.setValue(token.getValue());
                bag.getSystemProperty().add(prop);
            }
        }
    }

    public <T extends ConfigBeanProxy> T getCurrentConfigBeanForDefaultValue(ConfigBeanDefaultValue defaultValue)
            throws InvocationTargetException, IllegalAccessException {
        //TODO make this method target aware!
        Class parentClass = getOwningClassForLocation(defaultValue.getLocation());
        Class configBeanClass = getClassForFullName(defaultValue.getConfigBeanClassName());
        Method m = findSuitableCollectionGetter(parentClass, configBeanClass);
        if (m != null) {
            ConfigParser configParser = new ConfigParser(serviceLocator);
            // I don't use the GlassFish document here as I don't need persistence
            final DomDocument doc = new DomDocument<GlassFishConfigBean>(serviceLocator) {
                @Override
                public Dom make(final ServiceLocator serviceLocator, XMLStreamReader xmlStreamReader, GlassFishConfigBean dom,
                        ConfigModel configModel) {
                    // by default, people get the translated view.
                    return new GlassFishConfigBean(serviceLocator, this, dom, configModel, xmlStreamReader);
                }
            };

            ConfigBeanProxy parent = getOwningObject(defaultValue.getLocation());
            ConfigurationPopulator populator = new ConfigurationPopulator(defaultValue.getXmlConfiguration(), doc, parent);
            populator.run(configParser);
            ConfigBeanProxy configBean = doc.getRoot().createProxy(configBeanClass);
            Collection col = (Collection) m.invoke(parent);
            return (T) getConfigBeanFromCollection(col, configBean, configBeanClass);

        }
        return null;
    }

    public <T extends ConfigBeanProxy> T getConfigBeanFromCollection(Collection<T> col, T configBeanObject, Class typeOfObjects)
            throws InvocationTargetException, IllegalAccessException {
        String nameToLookFor = getNameForConfigBean(configBeanObject, typeOfObjects);
        if (nameToLookFor != null) {
            T returnee = getNamedConfigBeanFromCollection(col, nameToLookFor, typeOfObjects);
            if (returnee != null)
                return returnee;
        } else {
            for (T configBean : col) {
                try {
                    typeOfObjects.cast(configBean);
                    return configBean;
                } catch (Exception ex) {
                    //ignore it
                }
            }
        }
        return null;
    }

    public <T extends ConfigBeanProxy> T getNamedConfigBeanFromCollection(Collection<T> col, String nameToLookFor, Class typeOfObjects)
            throws InvocationTargetException, IllegalAccessException {
        if (nameToLookFor == null)
            return null;
        for (Object item : col) {
            if (!((ConfigView) Proxy.getInvocationHandler(item)).getProxyType().isAssignableFrom(typeOfObjects)) {
                continue;
            }
            String name = getNameForConfigBean(item, typeOfObjects);
            if (nameToLookFor.equalsIgnoreCase(name)) {
                return (T) item;
            }
        }
        return null;
    }

    public String getNameForConfigBean(Object configBean, Class configBeanType) throws InvocationTargetException, IllegalAccessException {
        if (configBean instanceof Named) {
            Named nme = (Named) configBean;
            return nme.getName();
        }
        if (configBean instanceof Resource) {
            Resource res = (Resource) configBean;
            return res.getIdentity();
        }
        Method[] methods = configBeanType.getMethods();
        for (Method method : methods) {
            Attribute attributeAnnotation = method.getAnnotation(Attribute.class);
            if ((attributeAnnotation != null) && attributeAnnotation.key()) {
                return (String) method.invoke(configBean);
            }
        }
        return null;
    }

    /**
     * convert a configuration element name to representing class name
     *
     * @param name the configuration element name we want to convert to class name
     * @return the class name which the configuration element represent.
     */
    public String convertConfigElementNameToClassName(String name) {
        // first, trim off the prefix
        StringTokenizer tokenizer = new StringTokenizer(name, "-", false);
        StringBuilder className = new StringBuilder();

        while (tokenizer.hasMoreTokens()) {
            String part = tokenizer.nextToken();
            Locale loc = Locale.getDefault();
            part = part.replaceFirst(part.substring(0, 1), part.substring(0, 1).toUpperCase(loc));
            className.append(part);

        }
        return className.toString();
    }

    public Class getClassFor(String serviceName) {
        serviceName = getServiceTypeNameIfNamedComponent(serviceName);
        ConfigInjector injector = serviceLocator.getService(ConfigInjector.class, serviceName.toLowerCase(Locale.getDefault()));
        return getClassFromInjector(injector);
    }

    public Class getClassFromInjector(ConfigInjector injector) {
        if (injector != null) {
            String clzName = injector.getClass().getName().substring(0, injector.getClass().getName().length() - 8);
            try {
                return injector.getClass().getClassLoader().loadClass(clzName);
            } catch (ClassNotFoundException e) {
                return null;
            }
        }
        return null;
    }

    public String getServiceTypeNameIfNamedComponent(String serviceName) {
        if (serviceName.endsWith("]")) {
            serviceName = serviceName.substring(0, serviceName.indexOf("["));
        }
        return serviceName;
    }

    public String resolveExpression(String expression) {
        if (expression.startsWith("$")) {
            String name = expression.substring(1, expression.length());
            if (name.equalsIgnoreCase("CURRENT_INSTANCE_CONFIG_NAME")) {
                expression = serviceLocator.<Config>getService(Config.class, ServerEnvironment.DEFAULT_INSTANCE_NAME).getName();
            }
            if (name.equalsIgnoreCase("CURRENT_INSTANCE_SERVER_NAME")) {
                expression = serviceLocator.<Server>getService(Server.class, ServerEnvironment.DEFAULT_INSTANCE_NAME).getName();
            }
        }
        return expression;
    }

    public String serializeConfigBeanByType(Class configBeanType) {
        ConfigBeanProxy configBeanProxy = getConfigBeanInstanceFor(configBeanType);
        return serializeConfigBean(configBeanProxy);
    }

    public ConfigBeanProxy getConfigBeanInstanceFor(Class configBeanType) {
        return (ConfigBeanProxy) serviceLocator.getService(configBeanType);
    }

    public String serializeConfigBean(ConfigBeanProxy configBean) {
        if (configBean == null)
            return null;
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        XMLOutputFactory xmlFactory = XMLOutputFactory.newInstance();
        XMLStreamWriter writer = null;
        IndentingXMLStreamWriter indentingXMLStreamWriter = null;
        String s = null;
        try {
            writer = xmlFactory.createXMLStreamWriter(new BufferedOutputStream(bos));
            indentingXMLStreamWriter = new IndentingXMLStreamWriter(writer);
            Dom configBeanDom = Dom.unwrap(configBean);
            configBeanDom.writeTo(configBeanDom.model.getTagName(), indentingXMLStreamWriter);
            indentingXMLStreamWriter.flush();
            s = bos.toString();
        } catch (XMLStreamException e) {
            if (LOG.isLoggable(Level.FINE)) {
                LOG.log(Level.FINE, "Cannot serialize the configbean: " + configBean.toString(), e);
            }
            return null;
        } finally {
            try {
                bos.close();
                if (writer != null)
                    writer.close();
                if (indentingXMLStreamWriter != null)
                    indentingXMLStreamWriter.close();
            } catch (IOException e) {
                if (LOG.isLoggable(Level.FINE)) {
                    LOG.log(Level.FINE, "Cannot serialize the configbean: " + configBean.toString(), e);
                }
            } catch (XMLStreamException e) {
                if (LOG.isLoggable(Level.FINE)) {
                    LOG.log(Level.FINE, "Cannot serialize the configbean: " + configBean.toString(), e);
                }
            }

        }
        return s;
    }

    /**
     * Find a suitable getter method in the given class. the returned method represent a method that will return back a type
     * of methodReturnType.
     *
     * @param classToQuery The class we want to find the getter in
     * @param methodReturnType the type we want to find the getter for
     * @return A Method object for a getter method in the classToQuery which returns the methodReturnType
     */
    public Method getMatchingGetterMethod(Class classToQuery, Class methodReturnType) {
        Method[] methods = classToQuery.getMethods();
        for (Method method : methods) {
            Class<?> rt = method.getReturnType();
            if (rt != null && methodReturnType != null) {
                if (rt.getSimpleName().equals(methodReturnType.getSimpleName())) {
                    return method;
                }
            }
        }
        return null;
    }

    /**
     * Finds and return the setter method matching the class identified by typeToSet
     *
     * @param classToQuery The ConfigLoader we want to inspect for presence of a setter method accepting class of type fqcn.
     * @param typeToSet the type we want to find a setter for
     * @return the matching Method object or null if not present.
     */
    public Method getMatchingSetterMethod(Class classToQuery, Class typeToSet) {
        String className = typeToSet.getName().substring(typeToSet.getName().lastIndexOf(".") + 1, typeToSet.getName().length());
        String setterName = "set" + className;
        Method[] methods = classToQuery.getClass().getMethods();
        for (Method method : methods) {
            if (method.getName().equalsIgnoreCase(setterName)) {
                return method;
            }
        }
        return null;
    }

    public Class getDuckClass(Class configBeanType) {
        Class duck;
        final Class[] clz = configBeanType.getDeclaredClasses();
        for (Class aClz : clz) {
            duck = aClz;
            if (duck.getSimpleName().equals("Duck")) {
                return duck;
            }
        }
        return null;
    }

    public Method getGetDefaultValuesMethod(Class configBeanType) {
        Class duck = getDuckClass(configBeanType);
        if (duck == null) {
            return null;
        }
        Method m;
        try {
            m = duck.getMethod("getDefaultValues", String.class);
        } catch (Exception ex) {
            return null;
        }
        return m;
    }

    public boolean deleteConfigurationForConfigBean(ConfigBeanProxy configBean, Collection col, ConfigBeanDefaultValue defaultValue) {
        String name;
        ConfigBeanProxy itemToRemove;
        try {
            Class configBeanClass = getClassForFullName(defaultValue.getConfigBeanClassName());
            name = getNameForConfigBean(configBean, configBeanClass);
            itemToRemove = getNamedConfigBeanFromCollection(col, name, configBeanClass);
            if (itemToRemove != null) {
                col.remove(itemToRemove);
                return true;
            }
            if (name == null) {
                col.remove(configBean);
                return true;
            }
        } catch (Exception ex) {
            return false;
        }
        return false;
    }

    public Class getClassForFullName(String configBeanClassName) {
        ActiveDescriptor<?> descriptor = serviceLocator.getBestDescriptor(BuilderHelper.createContractFilter(configBeanClassName));
        if (descriptor != null) {
            if (!descriptor.isReified()) {
                descriptor = serviceLocator.reifyDescriptor(descriptor);
            }
            return getClassFromDescriptor(descriptor);
        } else {
            descriptor = serviceLocator.getBestDescriptor(BuilderHelper.createContractFilter(configBeanClassName + "Injector"));
            if (!descriptor.isReified()) {
                descriptor = serviceLocator.reifyDescriptor(descriptor);
            }
            ConfigInjector injector = (ConfigInjector) serviceLocator.getServiceHandle(descriptor).getService();
            return getClassFromInjector(injector);
        }
    }

    public Class getClassFromDescriptor(ActiveDescriptor<?> descriptor) {

        Class<?> defaultReturnValue = descriptor.getImplementationClass();

        String name = descriptor.getName();
        if (name == null)
            return defaultReturnValue;

        Class<?> foundContract = null;
        for (Type contract : descriptor.getContractTypes()) {
            if (!(contract instanceof Class))
                continue;

            Class<?> cc = (Class<?>) contract;
            if (cc.getName().equals(name)) {
                foundContract = cc;
                break;
            }
        }

        if (foundContract == null)
            return defaultReturnValue;
        return foundContract;
    }

    public String replacePropertiesWithCurrentValue(String xmlConfiguration, ConfigBeanDefaultValue value)
            throws InvocationTargetException, IllegalAccessException {
        for (ConfigCustomizationToken token : value.getCustomizationTokens()) {
            String toReplace = "${" + token.getName() + "}";
            ConfigBeanProxy current = getCurrentConfigBeanForDefaultValue(value);
            String propertyValue = getPropertyValue(token, current);
            if (propertyValue != null) {
                xmlConfiguration = xmlConfiguration.replace(toReplace, propertyValue);
            }
        }
        return xmlConfiguration;
    }

    public String getPropertyValue(ConfigCustomizationToken token, ConfigBeanProxy finalConfigBean) {
        if (finalConfigBean != null) {
            ConfigBeanProxy parent = finalConfigBean.getParent();
            while (!(parent instanceof SystemPropertyBag)) {
                parent = parent.getParent();
                if (parent == null)
                    return null;
            }
            if (((SystemPropertyBag) parent).getSystemProperty(token.getName()) != null) {
                return ((SystemPropertyBag) parent).getSystemProperty(token.getName()).getValue();
            }
            return null;
        } else
            return token.getValue();
    }

    public String getRuntimeTypePrefix(StartupContext startupContext) {
        Properties args = startupContext.getArguments();
        RuntimeType serverType = RuntimeType.getDefault();
        String typeString = args.getProperty("-type");
        if (typeString != null)
            serverType = RuntimeType.valueOf(typeString);
        if (LOG.isLoggable(Level.FINE)) {
            LOG.fine("server type is: " + serverType.name());
        }
        if (serverType.isEmbedded())
            return "embedded";
        if (serverType.isSingleInstance() || serverType.isDas())
            return "admin";
        if (serverType.isInstance())
            return "instance";
        return "";
    }

    public List<Class> getAnnotatedConfigBeans(Class annotationType) {
        List<Class> prox = new ArrayList<Class>();
        List<ActiveDescriptor<?>> descriptor = serviceLocator
                .getDescriptors(BuilderHelper.createContractFilter(ConfigInjector.class.getName()));
        Class<?> clz = null;
        for (ActiveDescriptor desc : descriptor) {
            if (desc.getName() == null) {
                continue;
            }
            ConfigInjector injector = serviceLocator.getService(ConfigInjector.class, desc.getName());
            if (injector != null) {
                String clzName = injector.getClass().getName().substring(0, injector.getClass().getName().length() - 8);
                try {
                    clz = injector.getClass().getClassLoader().loadClass(clzName);
                    if (clz == null) {
                        if (LOG.isLoggable(Level.FINE)) {
                            LOG.log(Level.FINE, "Cannot find the class mapping to:  " + clzName);
                        }
                        continue;
                    }
                } catch (Throwable e) {
                    if (LOG.isLoggable(Level.FINE)) {
                        LOG.log(Level.FINE, "Cannot load the class", e);
                    }
                    continue;
                }
            }
            if (clz != null) {
                if (clz.isAnnotationPresent(annotationType)) {
                    prox.add(clz);
                }
            }
        }
        return prox;
    }

    public boolean isIgnorePersisting() {
        return ignorePersisting;
    }

    public void setIgnorePersisting(boolean ignorePersisting) {
        this.ignorePersisting = ignorePersisting;
    }

    public boolean isCommandInvocation() {
        return isCommandInvocation;
    }

    public void setCommandInvocation(boolean commandInvocation) {
        isCommandInvocation = commandInvocation;
    }

    public List<Class> getInstalledExtensions(Class extensionType) {
        List<Class> extensions = new ArrayList();
        List<Class> cbeans = getAnnotatedConfigBeans(Configured.class);

        for (Class c : cbeans) {
            try {
                if (c != extensionType) {
                    extensions.add(c);
                }
            } catch (ClassCastException e) {
                continue;
            }
        }
        return extensions;
    }
}
