Package org.apache.ivyde.common.ivysettings

Source Code of org.apache.ivyde.common.ivysettings.IvySettingsModel

/*
*  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.
*
*/
package org.apache.ivyde.common.ivysettings;

import java.io.File;
import java.lang.reflect.Method;
import java.net.URLClassLoader;
import java.util.Arrays;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.ivy.Ivy;
import org.apache.ivy.plugins.conflict.ConflictManager;
import org.apache.ivy.plugins.latest.LatestStrategy;
import org.apache.ivy.plugins.lock.LockStrategy;
import org.apache.ivy.plugins.namespace.Namespace;
import org.apache.ivy.plugins.parser.ModuleDescriptorParser;
import org.apache.ivy.plugins.report.ReportOutputter;
import org.apache.ivy.plugins.resolver.DependencyResolver;
import org.apache.ivy.plugins.trigger.Trigger;
import org.apache.ivy.plugins.version.VersionMatcher;
import org.apache.ivy.util.StringUtils;
import org.apache.ivyde.common.model.IvyBooleanTagAttribute;
import org.apache.ivyde.common.model.IvyFile;
import org.apache.ivyde.common.model.IvyModel;
import org.apache.ivyde.common.model.IvyModelSettings;
import org.apache.ivyde.common.model.IvyReferenceTag;
import org.apache.ivyde.common.model.IvyTag;
import org.apache.ivyde.common.model.IvyTagAttribute;

public class IvySettingsModel extends IvyModel {
    private String loaded = null;
    private File file;
    private ClassLoader cl;
    private Map typedefClasses;

    public IvySettingsModel(IvyModelSettings settings, File file) {
        super(settings);
        this.file = file;
        this.cl = Ivy.class.getClassLoader();
        this.typedefClasses = getTypedefClasses(this.cl, IvySettingsFile.getDefaultTypedefs());
        doLoadModel();
    }

    public void refreshIfNeeded(IvyFile file) {
        String toLoad = getLoad(file);
        if (!toLoad.equals(loaded)) {
            doRefresh(file, toLoad);
        }
    }

    private String getLoad(IvyFile file) {
        IvySettingsFile sfile = (IvySettingsFile) file;
        return Arrays.asList(sfile.getClasspathUrls()) + "|" + sfile.getTypedefs();
    }

    private void doRefresh(IvyFile file, String toLoad) {
        IvySettingsFile sfile = (IvySettingsFile) file;
        clearModel();
        cl = getClassLoader(sfile);
        typedefClasses = getTypedefClasses(sfile, cl);

        doLoadModel();
        loaded = toLoad;
    }

    private void doLoadModel() {
        IvyTag ivyTag = new IvyTag("ivysettings", "Root tag of Ivy settings file");

        ivyTag.addChildIvyTag(new IvyTag("property"
            new IvyTagAttribute[] {
                new IvyTagAttribute("name", true),
                new IvyTagAttribute("value", true),
                new IvyBooleanTagAttribute("override"),
        }));
        ivyTag.addChildIvyTag(new IvyTag("properties"
            new IvyTagAttribute[] {
                new IvyTagAttribute("file", true),
                new IvyTagAttribute("environment"),
                new IvyBooleanTagAttribute("override"),
        }));
        ivyTag.addChildIvyTag(new IvyTag("settings"
            new IvyTagAttribute[] {
                new IvyTagAttribute("defaultResolver"),
                new IvyTagAttribute("defaultLatestStrategy"),
                new IvyTagAttribute("defaultConflictManager"),
                new IvyTagAttribute("defaultBranch"),
                new IvyTagAttribute("defaultResolveMode"),
                new IvyTagAttribute("circularDependencyStrategy"),
                new IvyBooleanTagAttribute("validate"),
                new IvyBooleanTagAttribute("useRemoteConfig"),
        }));
        ivyTag.addChildIvyTag(new IvyTag("include"
            new IvyTagAttribute[] {
                new IvyTagAttribute("url"),
                new IvyTagAttribute("file"),
        }));
        ivyTag.addChildIvyTag(new IvyTag("classpath"
            new IvyTagAttribute[] {
                new IvyTagAttribute("url"),
                new IvyTagAttribute("file"),
        }));
        ivyTag.addChildIvyTag(new IvyTag("typedef"
            new IvyTagAttribute[] {
                new IvyTagAttribute("name"),
                new IvyTagAttribute("classname"),
        }));

        IvyTag tag = new IvyTag("locking-strategies");
        addTypedefChildren(tag, getChildClasses(typedefClasses, LockStrategy.class));
        ivyTag.addChildIvyTag(tag);

        ivyTag.addChildIvyTag(new IvyTag("caches"
            new IvyTagAttribute[] {
                new IvyTagAttribute("default"),
                new IvyTagAttribute("defaultCacheDir"),
                new IvyTagAttribute("resolutionCacheDir"),
                new IvyTagAttribute("repositoryCacheDir"),
                new IvyTagAttribute("ivyPattern"),
                new IvyTagAttribute("artifactPattern"),
                new IvyBooleanTagAttribute("checkUpToDate"),
                new IvyBooleanTagAttribute("useOrigin"),
                new IvyTagAttribute("lockStrategy"),
            }).addChildIvyTag(new IvyTag("cache"
                new IvyTagAttribute[] {
                    new IvyTagAttribute("name"),
                    new IvyTagAttribute("basedir"),
                    new IvyTagAttribute("ivyPattern"),
                    new IvyTagAttribute("artifactPattern"),
                    new IvyBooleanTagAttribute("useOrigin"),
                    new IvyTagAttribute("lockStrategy"),
                    new IvyTagAttribute("defaultTTL"),
                }).addChildIvyTag(new IvyTag("ttl"
                    new IvyTagAttribute[] {
                        new IvyTagAttribute("organisation"),
                        new IvyTagAttribute("module"),
                        new IvyTagAttribute("revision"),
                        new IvyTagAttribute("matcher"),
                        new IvyTagAttribute("duration", true),
                }))));

        tag = new IvyTag("latest-strategies");
        addTypedefChildren(tag, getChildClasses(typedefClasses, LatestStrategy.class));
        ivyTag.addChildIvyTag(tag);
       
        tag = new IvyTag("parsers");
        addTypedefChildren(tag, getChildClasses(typedefClasses, ModuleDescriptorParser.class));
        ivyTag.addChildIvyTag(tag);
       
        tag = new IvyTag("namespaces");
        addTypedefChildren(tag, getChildClasses(typedefClasses, Namespace.class));
        ivyTag.addChildIvyTag(tag);

        tag = new IvyTag("macrodef", new IvyTagAttribute[] {
                new IvyTagAttribute("name"),
            }).addChildIvyTag(new IvyTag("attribute", new IvyTagAttribute[] {
                    new IvyTagAttribute("name"),
                    new IvyTagAttribute("default"),
            }));
        addTypedefChildren(tag, getChildClasses(typedefClasses, DependencyResolver.class));
        ivyTag.addChildIvyTag(tag);

        tag = new IvyTag("resolvers");
        addTypedefChildren(tag, getChildClasses(typedefClasses, DependencyResolver.class));
        tag.addChildIvyTag(new IvyReferenceTag("resolver"));
        ivyTag.addChildIvyTag(tag);
       
        tag = new IvyTag("conflict-managers");
        addTypedefChildren(tag, getChildClasses(typedefClasses, ConflictManager.class));
        ivyTag.addChildIvyTag(tag);

        ivyTag.addChildIvyTag(new IvyTag("modules")
            .addChildIvyTag(new IvyTag("module"
                new IvyTagAttribute[] {
                    new IvyTagAttribute("organisation"),
                    new IvyTagAttribute("name"),
                    new IvyTagAttribute("revision"),
                    new IvyTagAttribute("matcher"),
                    new IvyTagAttribute("resolver"),
                    new IvyTagAttribute("conflict-manager"),
                    new IvyTagAttribute("branch"),
                    new IvyTagAttribute("resolveMode"),
                })));

        tag = new IvyTag("outputters");
        addTypedefChildren(tag, getChildClasses(typedefClasses, ReportOutputter.class));
        ivyTag.addChildIvyTag(tag);

        ivyTag.addChildIvyTag(new IvyTag("statuses",
            new IvyTagAttribute[] {
                    new IvyTagAttribute("default"),
                })
            .addChildIvyTag(new IvyTag("status"
                new IvyTagAttribute[] {
                    new IvyTagAttribute("name"),
                    new IvyTagAttribute("integration"),
                })));

        tag = new IvyTag("triggers");
        addTypedefChildren(tag, getChildClasses(typedefClasses, Trigger.class));
        ivyTag.addChildIvyTag(tag);

        tag = new IvyTag("version-matchers");
        addTypedefChildren(tag, getChildClasses(typedefClasses, VersionMatcher.class));
        ivyTag.addChildIvyTag(tag);

        addTag(ivyTag);
    }

    private void addTypedefChildren(IvyTag tag, Map children) {
        for (Iterator it = children.entrySet().iterator(); it.hasNext();) {
            Entry entry = (Entry) it.next();
            Class clazz = (Class) entry.getValue();
            String childName = (String) entry.getKey();
            tag.addChildIvyTag(typedefedTag(childName, clazz));
        }
    }

    private IvyTag typedefedTag(String tagName, final Class clazz) {
        IvyTag child = new IvyTag(tagName) {
            // we lazy load children, since we may have a loop in children (chain can contain chain)
            // causing a stack overflow if we try to recursively add typedefed children
            private boolean init = false;
            public List getAttributes() {
                init();
                return super.getAttributes();
            }
           
            public List getChilds() {
                init();
                return super.getChilds();
            }
           
            public boolean hasChild() {
                init();
                return super.hasChild();
            }
           
            private void init() {
                if (!init) {
                    try {
                        Method[] methods = clazz.getMethods();
                        for (int i = 0; i < methods.length; i++) {
                            Method m = methods[i];
                            if (m.getName().startsWith("create")
                                    && m.getParameterTypes().length == 0
                                    && isSupportedChildType(m.getReturnType())) {
                                String name = StringUtils
                                .uncapitalize(m.getName().substring("create".length()));
                                if (name.length() == 0) {
                                    continue;
                                }
                                addChildIvyTag(typedefedTag(name, m.getReturnType()));
                            } else if (m.getName().startsWith("add")
                                    && m.getParameterTypes().length == 1
                                    && isSupportedChildType(m.getParameterTypes()[0])
                                    && Void.TYPE.equals(m.getReturnType())) {
                                String name = StringUtils.uncapitalize(m.getName().substring(
                                    m.getName().startsWith("addConfigured") ? "addConfigured"
                                            .length() : "add".length()));
                                if (name.length() == 0) {
                                    addTypedefChildren(this, getChildClasses(typedefClasses, m
                                            .getParameterTypes()[0]));
                                } else {
                                    addChildIvyTag(typedefedTag(name, m.getParameterTypes()[0]));
                                }
                            } else if (m.getName().startsWith("set")
                                    && Void.TYPE.equals(m.getReturnType())
                                    && m.getParameterTypes().length == 1
                                    && isSupportedAttributeType(m.getParameterTypes()[0])) {
                                IvyTagAttribute att = new IvyTagAttribute(StringUtils
                                        .uncapitalize(m.getName().substring("set".length())));
                                if (m.getParameterTypes()[0] == boolean.class) {
                                    att.setValueProvider(IvyBooleanTagAttribute.VALUE_PROVIDER);
                                }
                                addAttribute(att);
                            }
                        }
                    } catch (NoClassDefFoundError e) {
                        // we catch this because listing methods may raise a NoClassDefFoundError
                        // if the class relies on a dependency which is not available in classpath
                        getSettings().logError(
                            "impossible to init tag for " + clazz + ": " + e,
                            null);
                    } catch (Exception e) {
                        getSettings().logError(
                            "error occured while initializing tag for " + clazz + ": " + e,
                            e);
                    }
                    init = true;
                }
            }
        };
        return child;
    }

    protected boolean isSupportedChildType(Class type) {
        return !Void.TYPE.equals(type)
                && !String.class.equals(type)
                && !Character.class.equals(type) && !char.class.equals(type)
                && !Boolean.class.equals(type) && !boolean.class.equals(type)
                && !Integer.class.equals(type) && !int.class.equals(type)
                && !Short.class.equals(type) && !short.class.equals(type)
                && !Long.class.equals(type) && !long.class.equals(type)
                && !Class.class.equals(type);
    }

    private boolean isSupportedAttributeType(Class type) {
        if (String.class.isAssignableFrom(type)
                || Character.class.equals(type) || char.class.equals(type)
                || Boolean.class.equals(type) || boolean.class.equals(type)
                || Short.class.equals(type) || short.class.equals(type)
                || Integer.class.equals(type) || int.class.equals(type)
                || Long.class.equals(type) || long.class.equals(type)
                || Class.class.equals(type)
                ) {
            return true;
        }
        try {
            type.getConstructor(new Class[] {String.class});
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    private ClassLoader getClassLoader(IvySettingsFile sfile) {
        if (sfile.getClasspathUrls().length > 0) {
            return new URLClassLoader(sfile.getClasspathUrls(), Ivy.class.getClassLoader());
        } else {
            return Ivy.class.getClassLoader();
        }
    }

    private Map/*<String,Class>*/ getTypedefClasses(IvySettingsFile file, ClassLoader cl) {
        Map typedefs = file.getTypedefs();
        return getTypedefClasses(cl, typedefs);
    }

    private Map getTypedefClasses(ClassLoader cl, Map typedefs) {
        Map/*<String,Class>*/ classes = new LinkedHashMap();
        for (Iterator it = typedefs.entrySet().iterator(); it.hasNext();) {
            Entry entry = (Entry) it.next();
            try {
                classes.put(entry.getKey(), cl.loadClass((String) entry.getValue()));
            } catch (ClassNotFoundException e) {
                // ignored
            }
        }
        return classes;
    }

    private Map/*<String,Class>*/ getChildClasses(Map/*<String,Class>*/ classes, Class type) {
        Map/*<String,Class>*/ childClasses = new LinkedHashMap();
        for (Iterator it = classes.entrySet().iterator(); it.hasNext();) {
            Entry entry = (Entry) it.next();
            if (type.isAssignableFrom((Class) entry.getValue())) {
                childClasses.put(entry.getKey(), entry.getValue());
            }
        }
        return childClasses;
    }

    protected String getRootIvyTagName() {
        return "ivysettings";
    }

    public IvyFile newIvyFile(String name, String content, int documentOffset) {
        return new IvySettingsFile(getSettings(), file, name, content, documentOffset);
    }

}
TOP

Related Classes of org.apache.ivyde.common.ivysettings.IvySettingsModel

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.