Package org.grails.cxf.artefact

Source Code of org.grails.cxf.artefact.DefaultGrailsEndpointClass

package org.grails.cxf.artefact;

import groovy.lang.MetaProperty;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.codehaus.groovy.grails.commons.AbstractInjectableGrailsClass;
import org.codehaus.groovy.grails.commons.GrailsClassUtils;
import org.codehaus.groovy.grails.commons.ServiceArtefactHandler;
import org.grails.cxf.utils.EndpointType;
import org.grails.cxf.utils.GrailsCxfEndpoint;
import org.grails.cxf.utils.GrailsCxfEndpointProperty;
import org.grails.cxf.utils.GrailsCxfUtils;

import javax.xml.transform.TransformerConfigurationException;
import java.lang.reflect.Modifier;
import java.net.URL;
import java.util.*;

public class DefaultGrailsEndpointClass extends AbstractInjectableGrailsClass implements GrailsEndpointClass {

    private static final String CXFJAX = "cxfjax";
    private static final String CXFRS = "cxfrs";
    private static final String CXF = "cxf";
    protected EndpointExposureType expose;
    protected Set<String> excludes;
    protected String servletName;
    protected URL wsdl;
    protected Boolean soap12;
    protected String address;
    protected Set<String> inInterceptors;
    protected Set<String> outInterceptors;
    protected Set<String> inFaultInterceptors;
    protected Set<String> outFaultInterceptors;
    protected Map<String, Object> properties = new HashMap<String, Object>();

    private static final Log log = LogFactory.getLog(DefaultGrailsEndpointClass.class);

    public DefaultGrailsEndpointClass(Class clazz) throws TransformerConfigurationException {
        super(clazz, EndpointArtefactHandler.TYPE);
        setupExpose();
        buildExclusionSet();
        setupAddress();
        setupServletName();
        findWsdl();
        setupSoap12Binding();
        setupInterceptors();
        setupProperties();
    }

    /**
     * This can be configured in the endpoint class by setting {@code static expose = 'CXF'}. Valid strings in the
     * endpoint class are {@code CXF}, {@code JAXWS}, and {@code JAXRS}. If the {@code expose} property of the
     * class is not specified, then the default of {@code CXF} will be used.
     *
     * @return @inheritDoc
     */
    public EndpointExposureType getExpose() {
        return expose;
    }

    /**
     * Setting the property {@code static excludes = ['myPublicMethod']} on the endpoint class will allow clients to
     * add additional method names to be excluded from exposure.
     * <p/>
     * By default all of the GroovyObject methods and getters and setters for properties will be excluded and setting
     * the excludes property on the endpoint class will add to this set.
     * <p/>
     * TODO: I think this is only relevant to SIMPLE Cxf Frontends.
     *
     * @return @inheritDoc
     */
    public Set<String> getExcludes() {
        return excludes;
    }

    /**
     * Since the plugin allows us to configure and use multiple CXF servlets, this property allows us to choose which
     * servlet to use. The servlet name can be configured by using the property servletName on the endpoint class.
     * <p/>
     * By default the first alphabetically will be used.
     *
     * @return @inheritDoc
     */
    public String getServletName() {
        return servletName;
    }

    /**
     * Gets the address that will be set on the Cxf ServerFactoryBean.
     * <p/>
     * TODO Should also allow overriding and basic configuration?
     *
     * @return @inheritDoc
     */
    public String getAddress() {
        return address;
    }

    /**
     * The URL of the Wsdl that is on the classpath.
     *
     * @return @inheritDoc
     */
    public URL getWsdl() {
        return wsdl;
    }

    public Boolean hasWsdl() {
        return expose == EndpointExposureType.JAX_WS_WSDL && wsdl != null;
    }

    public String getNameNoPostfix() {
        if(getPropertyName().endsWith(ServiceArtefactHandler.TYPE)) {
            return StringUtils.removeEnd(getPropertyName(), ServiceArtefactHandler.TYPE);
        } else if(getPropertyName().endsWith(EndpointArtefactHandler.TYPE)) {
            return StringUtils.removeEnd(getPropertyName(), EndpointArtefactHandler.TYPE);
        }
        return getPropertyName();
    }

    public Boolean isSoap12() {
        return soap12;
    }

    public Set<String> getInInterceptors() {
        return inInterceptors;
    }

    public Set<String> getOutInterceptors() {
        return outInterceptors;
    }

    public Set<String> getInFaultInterceptors() {
        return inFaultInterceptors;
    }

    public Set<String> getOutFaultInterceptors() {
        return outFaultInterceptors;
    }

    public Map<String, Object> getProperties() {
        return properties;
    }

    protected void setupProperties(){
        GrailsCxfEndpoint annotation = getClazz().getAnnotation(GrailsCxfEndpoint.class);
        if(annotation != null && annotation.properties().length > 0) {
            for(GrailsCxfEndpointProperty prop : annotation.properties()){
                properties.put(prop.name(), prop.value());
            }
            log.debug("Endpoint [" + getFullName() + "] configured to use properties " + properties + ".");
        }
    }

    protected void setupInterceptors() {
        GrailsCxfEndpoint annotation = getClazz().getAnnotation(GrailsCxfEndpoint.class);
        if(annotation != null) {
            inInterceptors = setupInterceptorsViaAnnotation("inInterceptors", annotation.inInterceptors());
            outInterceptors = setupInterceptorsViaAnnotation("outInterceptors", annotation.outInterceptors());
            inFaultInterceptors = setupInterceptorsViaAnnotation("inFaultInterceptors", annotation.inFaultInterceptors());
            outFaultInterceptors = setupInterceptorsViaAnnotation("outFaultInterceptors", annotation.outFaultInterceptors());
        }
    }

    protected Set<String> setupInterceptorsViaAnnotation(String name, String[] customInterceptors) {
        Set<String> addedInterceptors = new HashSet<String>();
        if(customInterceptors.length > 0) {
            Collections.addAll(addedInterceptors, customInterceptors);
            log.debug("Endpoint [" + getFullName() + "] configured to use " + name + " " + addedInterceptors + ".");
        }
        return Collections.unmodifiableSet(addedInterceptors);
    }

    protected void setupAddress() {
        address = "/" + getNameNoPostfix();

        GrailsCxfEndpoint annotation = getClazz().getAnnotation(GrailsCxfEndpoint.class);
        if(annotation != null && !annotation.address().equals("")) {
            setupAddressViaAnnotation(annotation);
        } else {
            setupAddressViaProperty();
        }

        log.debug("Endpoint [" + getFullName() + "] configured to use address [" + address + "].");
    }

    private void setupAddressViaProperty() {
        Object propAddress = getPropertyValue(PROP_ADDRESS);
        if(propAddress != null && propAddress instanceof String) {
            address = ((((String) propAddress).startsWith("/")) ? "" : "/") + ((String) propAddress).replace("#name", getNameNoPostfix());
        }
    }

    private void setupAddressViaAnnotation(GrailsCxfEndpoint annotation) {
        String annotationAddress = annotation.address();
        address = ((annotationAddress.startsWith("/")) ? "" : "/") + annotationAddress.replace("#name", getNameNoPostfix());
    }

    protected void setupExpose() {
        expose = EndpointExposureType.JAX_WS; // Default to the most common type.

        GrailsCxfEndpoint annotation = getClazz().getAnnotation(GrailsCxfEndpoint.class);
        if(annotation != null) {
            setupExposeViaAnnotation(annotation);
        } else {
            setupExposeViaProperty();
        }

        if(expose.equals(EndpointExposureType.SIMPLE)) {
            log.warn("Simple Cxf Frontends are generally not recommended. Find out more: http://cxf.apache.org/docs/simple-frontend.html");
        }

        log.debug("Endpoint [" + getFullName() + "] configured to use [" + expose.name() + "].");
    }

    private void setupExposeViaProperty() {
        Object propExpose = getPropertyValue(PROP_EXPOSE);
        String manualExpose = getConfiguredExpose(propExpose);

        if(manualExpose != null && !manualExpose.equals("")) {
            try {
                expose = EndpointExposureType.forExpose(manualExpose);
            } catch(IllegalArgumentException e) {
                log.error("Unsupported endpoint exposure type [" + manualExpose + "] for endpoint [" + getFullName() + "].  Using default type.");
            }
        }
    }

    private void setupExposeViaAnnotation(GrailsCxfEndpoint annotation) {
        EndpointType exposes = annotation.expose();
        try {
            expose = EndpointExposureType.forExpose(exposes.toString());
        } catch(IllegalArgumentException e) {
            log.error("Unsupported endpoint exposure type [" + exposes.toString() + "] for endpoint [" + getFullName() + "].  Using default type.");
        }
    }

    private String getConfiguredExpose(Object propExpose) {
        String manualExpose = null;

        if(propExpose instanceof EndpointType) {
            manualExpose = ((EndpointType) propExpose).toString();
        } else if(propExpose instanceof String) {
            manualExpose = (String) propExpose;
        } else if(propExpose instanceof List) {
            manualExpose = getListExpose((List) propExpose);
        }
        return manualExpose;
    }

    /**
     * Support legacy static expose = [] style exposure.
     *
     * @param propExpose list of values to check
     * @return string of the service type to wire
     */
    private String getListExpose(List propExpose) {
        String manualExpose = null;
        for(Object prop : ((List) propExpose)) {
            if(prop instanceof String || prop instanceof EndpointType) {
                String stringProp = prop.toString().toLowerCase();

                //legacy variables cxf and cxfjax
                if(CXF.equals(stringProp)) {
                    return EndpointType.SIMPLE.toString();
                } else if(CXFJAX.equals(stringProp)) {
                    return EndpointType.JAX_WS.toString();
                } else if(CXFRS.equals(stringProp)) {
                    return EndpointType.JAX_RS.toString();
                }

                try {
                    EndpointExposureType type = EndpointExposureType.forExpose(stringProp);
                    manualExpose = type.toString();
                    break;
                } catch(IllegalArgumentException e) {
                    log.debug("could not identify type for " + prop);
                }
            }
        }
        return manualExpose;
    }

    protected void buildExclusionSet() {
        final Set<String> groovyExcludes = DEFAULT_GROOVY_EXCLUDES;
        GrailsCxfEndpoint annotation = getClazz().getAnnotation(GrailsCxfEndpoint.class);
        Set<String> aggExcludes = new HashSet<String>();

        List<String> automaticExcludes = buildAutomaticExcludes();

        aggExcludes.addAll(groovyExcludes);
        aggExcludes.addAll(automaticExcludes);

        if(annotation != null && annotation.excludes().length > 0) {
            buildExclusionSetFromAnnotation(aggExcludes, annotation);
        } else {
            buildExclusionSetFromProperty(aggExcludes);
        }

        excludes = Collections.unmodifiableSet(aggExcludes);

        log.debug("Endpoint [" + getFullName() + "] configured to exclude methods " + excludes + ".");
    }

    private List<String> buildAutomaticExcludes() {
        List<String> automaticExcludes = new ArrayList<String>();
        for(MetaProperty prop : getMetaClass().getProperties()) {
            int modifiers = prop.getModifiers();
            if(Modifier.isPublic(modifiers) && !Modifier.isStatic(modifiers)) {
                automaticExcludes.add(GrailsClassUtils.getGetterName(prop.getName()));
                automaticExcludes.add(GrailsClassUtils.getSetterName(prop.getName()));
            }
        }
        return automaticExcludes;
    }

    private void buildExclusionSetFromAnnotation(Set<String> aggExcludes, GrailsCxfEndpoint annotation) {
        Collections.addAll(aggExcludes, annotation.excludes());
    }

    private void buildExclusionSetFromProperty(Set<String> aggExcludes) {
        // Get the the methods that are specified for manual exclusion.
        Collection<String> manualExcludes = (Collection<String>) getPropertyOrStaticPropertyOrFieldValue(PROP_EXCLUDES, Collection.class);

        if(manualExcludes != null && !manualExcludes.isEmpty()) {
            manualExcludes.remove("");
            aggExcludes.addAll(manualExcludes);
        }
    }

    protected void setupServletName() {
        String manualServletName = (String) getPropertyOrStaticPropertyOrFieldValue(PROP_SERVLET_NAME, String.class);

        if(manualServletName != null && !manualServletName.equals("") && GrailsCxfUtils.getServletsMappings().containsKey(manualServletName)) {
            servletName = manualServletName;
        } else {
            servletName = GrailsCxfUtils.getDefaultServletName();
        }

        log.debug("Endpoint [" + getFullName() + "] configured to servlet [" + servletName + "].");
    }

    protected void findWsdl() {
        String wsdlLocation = null;
        GrailsCxfEndpoint annotation = getClazz().getAnnotation(GrailsCxfEndpoint.class);

        if(annotation != null && !annotation.wsdl().equals("")) {
            wsdlLocation = annotation.wsdl();
        } else {
            wsdlLocation = (String) getPropertyOrStaticPropertyOrFieldValue(PROP_WSDL, String.class);
        }

        if(wsdlLocation != null && !wsdlLocation.equals("")) {
            wsdl = getClass().getClassLoader().getResource(wsdlLocation);
            if(wsdl == null) {
                log.error("Endpoint [" + getFullName() + "] as WSDL at [" + wsdlLocation + "] but it couldn't be found. Will try to generate the Cxf Service from the endpoint class.");
            }
        }

        log.debug("Endpoint [" + getFullName() + "] configured to use WSDL [" + wsdl + "].");
    }

    protected void setupSoap12Binding() {
        soap12 = GrailsCxfUtils.getDefaultSoap12Binding();

        GrailsCxfEndpoint annotation = getClazz().getAnnotation(GrailsCxfEndpoint.class);

        if(annotation != null) {
            setupSoap12BindingViaAnnotation(annotation);
        } else {
            setupSoap12BindingViaProperty();
        }

        log.debug("Endpoint [" + getFullName() + "] configured to use soap 1.2 [" + soap12 + "].");
    }

    private void setupSoap12BindingViaProperty() {
        Boolean soap12setting = (Boolean) getPropertyOrStaticPropertyOrFieldValue(PROP_SOAP12, Boolean.class);
        if(soap12setting != null) {
            soap12 = soap12setting;
        }
    }

    private void setupSoap12BindingViaAnnotation(GrailsCxfEndpoint annotation) {
        soap12 = annotation.soap12();
    }
}
TOP

Related Classes of org.grails.cxf.artefact.DefaultGrailsEndpointClass

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.