org.fusesource.ide.camel.editor.propertysheet.CamelComponentUtils.java Source code

Java tutorial

Introduction

Here is the source code for org.fusesource.ide.camel.editor.propertysheet.CamelComponentUtils.java

Source

/*******************************************************************************
 * Copyright (c) 2014 Red Hat, Inc.
 * Distributed under license by Red Hat, Inc. All rights reserved.
 * This program is made available under the terms of the
 * Eclipse Public License v1.0 which accompanies this distribution,
 * and is available at http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     Red Hat, Inc. - initial API and implementation
 ******************************************************************************/
package org.fusesource.ide.camel.editor.propertysheet;

import java.io.File;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;

import org.apache.maven.artifact.Artifact;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.m2e.core.MavenPlugin;
import org.eclipse.m2e.core.project.IMavenProjectFacade;
import org.fusesource.ide.camel.editor.Activator;
import org.fusesource.ide.camel.model.catalog.CamelModelFactory;
import org.fusesource.ide.camel.model.catalog.Dependency;
import org.fusesource.ide.camel.model.catalog.components.Component;
import org.fusesource.ide.camel.model.catalog.components.ComponentModel;
import org.fusesource.ide.camel.model.catalog.components.ComponentProperty;
import org.fusesource.ide.camel.model.catalog.components.UriParameter;
import org.fusesource.ide.commons.util.JsonHelper;
import org.jboss.dmr.ModelNode;

/**
 * @author lhein
 */
public final class CamelComponentUtils {

    private static final String CAMEL_COMPONENT_DESCRIPTOR_FILE_MASK = "META-INF/services/org/apache/camel/descriptors/%s.xml";
    private static HashMap<String, Component> knownComponents = new HashMap<String, Component>();

    /**
     * returns the properties model for a given protocol
     * 
     * @param protocol  the protocol to get the properties for
     * @return  the properties model or null if not available
     */
    public static Component getComponentModel(String protocol) {
        String componentClass = getComponentClass(protocol);
        if (knownComponents.containsKey(componentClass)) {
            return knownComponents.get(componentClass);
        }

        // it seems we miss a model for the given protocol...lets try creating one on the fly
        Component c = buildModelForComponent(protocol, componentClass);
        if (c != null) {
            knownComponents.put(componentClass, c);
            return getComponentModel(protocol);
        }

        return null;
    }

    public static boolean isBooleanProperty(UriParameter p) {
        return p.getJavaType().equalsIgnoreCase("boolean") || p.getJavaType().equalsIgnoreCase("java.lang.Boolean");
    }

    public static boolean isTextProperty(UriParameter p) {
        return p.getChoice() == null && (p.getJavaType().equalsIgnoreCase("String")
                || p.getJavaType().equalsIgnoreCase("java.lang.String")
                || p.getJavaType().equalsIgnoreCase("java.net.URL")
                || p.getJavaType().equalsIgnoreCase("java.net.URI") || p.getJavaType().equalsIgnoreCase("Text"));
    }

    public static boolean isNumberProperty(UriParameter p) {
        return p.getChoice() == null && (p.getJavaType().equalsIgnoreCase("int")
                || p.getJavaType().equalsIgnoreCase("Integer")
                || p.getJavaType().equalsIgnoreCase("java.lang.Integer") || p.getJavaType().equalsIgnoreCase("long")
                || p.getJavaType().equalsIgnoreCase("java.lang.Long") || p.getJavaType().equalsIgnoreCase("double")
                || p.getJavaType().equalsIgnoreCase("java.lang.Double") || p.getJavaType().equalsIgnoreCase("float")
                || p.getJavaType().equalsIgnoreCase("java.lang.Float")
                || p.getJavaType().equalsIgnoreCase("Number"));
    }

    public static boolean isChoiceProperty(UriParameter p) {
        return p.getChoice() != null && p.getChoice().trim().length() > 0;
    }

    public static boolean isFileProperty(UriParameter p) {
        return p.getJavaType().equalsIgnoreCase("file") || p.getJavaType().equalsIgnoreCase("java.io.file");
    }

    public static boolean isExpressionProperty(UriParameter p) {
        return p.getJavaType().equalsIgnoreCase("expression")
                || p.getJavaType().equalsIgnoreCase("org.apache.camel.Expression");
    }

    public static boolean isListProperty(UriParameter p) {
        return p.getJavaType().toLowerCase().startsWith("java.util.list")
                || p.getJavaType().toLowerCase().startsWith("java.util.collection");
    }

    public static boolean isMapProperty(UriParameter p) {
        return p.getJavaType().toLowerCase().startsWith("java.util.map");
    }

    public static boolean isUriPathParameter(UriParameter p) {
        return p.getKind() != null && p.getKind().equalsIgnoreCase("path");
    }

    public static boolean isUriOptionParameter(UriParameter p) {
        return p.getKind() != null && p.getKind().equalsIgnoreCase("parameter");
    }

    public static boolean isUnsupportedProperty(UriParameter p) {
        return isListProperty(p) || isMapProperty(p) || p.getJavaType().toLowerCase().startsWith("java.util.date");
    }

    public static String[] getChoices(UriParameter p) {
        String[] choices = p.getChoice().split(",");
        ArrayList<String> res = new ArrayList<String>();
        res.add(" "); // empty entry
        for (String choice : choices)
            res.add(choice);
        return res.toArray(new String[res.size()]);
    }

    /**
     * returns the component class for the given scheme
     * 
     * @param scheme
     * @return  the class or null if not found
     */
    protected static String getComponentClass(String scheme) {
        String compClass = null;

        ArrayList<Component> components = CamelModelFactory
                .getModelForVersion(Activator.getDefault().getCamelVersion()).getComponentModel()
                .getSupportedComponents();
        for (Component c : components) {
            if (c.supportsScheme(scheme)) {
                compClass = c.getClazz();
                break;
            }
        }

        if (compClass == null) {
            // seems this scheme has no model entry -> check dependency
            try {
                IMavenProjectFacade m2facade = MavenPlugin.getMavenProjectRegistry().create(
                        Activator.getDiagramEditor().getCamelContextFile().getProject(), new NullProgressMonitor());
                Set<Artifact> deps = m2facade.getMavenProject(new NullProgressMonitor()).getArtifacts();
                ZipFile zf = null;
                ZipEntry ze = null;
                for (Artifact dep : deps) {
                    zf = new ZipFile(dep.getFile());
                    ze = zf.getEntry(String.format("META-INF/services/org/apache/camel/component/%s", scheme));
                    if (ze != null) {
                        break;
                    }
                    ze = null;
                    zf = null;
                }

                if (ze != null) {
                    // try to generate a model entry for the component class
                    Properties p = new Properties();
                    p.load(zf.getInputStream(ze));
                    compClass = p.getProperty("class");
                }
            } catch (Exception ex) {
                Activator.getLogger().error(ex);
                compClass = null;
            }
        }

        return compClass;
    }

    protected static Component buildModelForComponent(String scheme, String clazz) {
        Component resModel = null;

        // 1. take what we have in our model xml
        resModel = CamelModelFactory.getModelForVersion(Activator.getDefault().getCamelVersion())
                .getComponentModel().getComponentForScheme(scheme);

        // 2. try to generate the model from json blob
        if (resModel == null)
            resModel = buildModelFromJSON(scheme, clazz);

        return resModel;
    }

    /**
     * tries to build the model by querying the component config of the camel component
     * 
     * @param clazz the component class
     * @return
     */
    protected static Component buildModelFromJSON(String scheme, String clazz) {
        Component resModel = null;

        try {
            URLClassLoader child = getProjectClassLoader();
            Class classToLoad = child.loadClass(clazz);
            Method method = classToLoad.getMethod("createComponentConfiguration");
            Object instance = classToLoad.newInstance();
            Object compConf = method.invoke(instance);
            method = compConf.getClass().getMethod("createParameterJsonSchema");
            Object oJSONBlob = method.invoke(compConf);
            if (oJSONBlob != null && oJSONBlob instanceof String) {
                resModel = buildModelFromJSonBlob((String) oJSONBlob, clazz);
                resModel.setScheme(scheme);
                saveModel(resModel);
            }
        } catch (Exception ex) {
            Activator.getLogger().error(ex);
        }

        return resModel;
    }

    private static void saveModel(Component component) {
        try {
            // create JAXB context and instantiate marshaller
            JAXBContext context = JAXBContext.newInstance(ComponentModel.class, Component.class, Dependency.class,
                    ComponentProperty.class, UriParameter.class);
            Marshaller m = context.createMarshaller();
            m.marshal(component, new File("/var/tmp/model.xml"));
        } catch (Exception ex) {
            Activator.getLogger().error(ex);
        }
    }

    public static URLClassLoader getProjectClassLoader() {
        try {
            IProject project = Activator.getDiagramEditor().getCamelContextFile().getProject();
            IJavaProject javaProject = (IJavaProject) project.getNature(JavaCore.NATURE_ID);
            IPackageFragmentRoot[] pfroots = javaProject.getAllPackageFragmentRoots();
            ArrayList<URL> urls = new ArrayList<URL>();
            for (IPackageFragmentRoot root : pfroots) {
                URL rUrl = root.getPath().toFile().toURI().toURL();
                urls.add(rUrl);
            }
            return new URLClassLoader(urls.toArray(new URL[urls.size()]),
                    CamelComponentUtils.class.getClassLoader());
        } catch (Exception ex) {
            Activator.getLogger().error(ex);
        }
        return null;
    }

    /**
     * takes the json blob from camel configuration and makes a model from it
     * 
     * @param json
     * @return
     */
    protected static Component buildModelFromJSonBlob(String json, String clazz) {
        Component resModel = new Component();
        resModel.setClazz(clazz);

        try {
            ArrayList<UriParameter> uriParams = new ArrayList<UriParameter>();
            ModelNode model = JsonHelper.getModelNode(json);
            ModelNode propsNode = model.get("properties");
            Map<String, Object> props = JsonHelper.getAsMap(propsNode);
            Iterator<String> it = props.keySet().iterator();

            while (it.hasNext()) {
                String propName = it.next();
                ModelNode valueNode = propsNode.get(propName);
                String type = null;
                if (valueNode.has("enum")) {
                    type = "choice[";
                    List<ModelNode> vals = JsonHelper.getAsList(valueNode, "enum");
                    for (ModelNode mn : vals) {
                        if (!type.equalsIgnoreCase("choice[")) {
                            type += ",";
                        }
                        type += mn.asString();
                    }
                    type += "]";
                } else {
                    type = valueNode.get("type").asString();
                }

                UriParameter param = new UriParameter();
                param.setName(propName);
                param.setJavaType(type);
                param.setLabel(null);
                uriParams.add(param);
            }

            resModel.setUriParameters(uriParams);
        } catch (Exception ex) {
            Activator.getLogger().error(ex);
            resModel = null;
        }

        return resModel;
    }
}