All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.sca4j.loader.composite.CompositeLoader Maven / Gradle / Ivy

/**
 * SCA4J
 * Copyright (c) 2009 - 2099 Service Symphony Ltd
 *
 * Licensed to you under the Apache License, Version 2.0 (the "License"); you may
 * not use this file except in compliance with the License.  A copy of the license
 * is included in this distrubtion or you may obtain a copy at
 *
 *    http://www.opensource.org/licenses/apache2.0.php
 *
 * 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.
 *
 * This project contains code licensed from the Apache Software Foundation under
 * the Apache License, Version 2.0 and original code from project contributors.
 *
 *
 * Original Codehaus Header
 *
 * Copyright (c) 2007 - 2008 fabric3 project contributors
 *
 * Licensed to you under the Apache License, Version 2.0 (the "License"); you may
 * not use this file except in compliance with the License.  A copy of the license
 * is included in this distrubtion or you may obtain a copy at
 *
 *    http://www.opensource.org/licenses/apache2.0.php
 *
 * 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.
 *
 * This project contains code licensed from the Apache Software Foundation under
 * the Apache License, Version 2.0 and original code from project contributors.
 *
 * Original Apache Header
 *
 * Copyright (c) 2005 - 2006 The Apache Software Foundation
 *
 * Apache Tuscany is an effort undergoing incubation at The Apache Software
 * Foundation (ASF), sponsored by the Apache Web Services PMC. Incubation is
 * required of all newly accepted projects until a further review indicates that
 * the infrastructure, communications, and decision making process have stabilized
 * in a manner consistent with other successful ASF projects. While incubation
 * status is not necessarily a reflection of the completeness or stability of the
 * code, it does indicate that the project has yet to be fully endorsed by the ASF.
 *
 * This product includes software developed by
 * The Apache Software Foundation (http://www.apache.org/).
 */
/*
 * 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.sca4j.loader.composite;

import static javax.xml.stream.XMLStreamConstants.END_ELEMENT;
import static javax.xml.stream.XMLStreamConstants.START_ELEMENT;
import static org.oasisopen.sca.Constants.SCA_NS;

import java.net.URI;
import java.util.HashSet;
import java.util.Set;

import javax.xml.namespace.NamespaceContext;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;

import org.oasisopen.sca.annotation.Constructor;
import org.oasisopen.sca.annotation.Destroy;
import org.oasisopen.sca.annotation.EagerInit;
import org.oasisopen.sca.annotation.Init;
import org.oasisopen.sca.annotation.Reference;
import org.sca4j.introspection.DefaultIntrospectionContext;
import org.sca4j.introspection.IntrospectionContext;
import org.sca4j.introspection.xml.Loader;
import org.sca4j.introspection.xml.LoaderHelper;
import org.sca4j.introspection.xml.LoaderRegistry;
import org.sca4j.introspection.xml.LoaderUtil;
import org.sca4j.introspection.xml.TypeLoader;
import org.sca4j.introspection.xml.UnrecognizedAttribute;
import org.sca4j.introspection.xml.UnrecognizedElement;
import org.sca4j.introspection.xml.UnrecognizedElementException;
import org.sca4j.scdl.ArtifactValidationFailure;
import org.sca4j.scdl.Autowire;
import org.sca4j.scdl.ComponentDefinition;
import org.sca4j.scdl.Composite;
import org.sca4j.scdl.CompositeReference;
import org.sca4j.scdl.CompositeService;
import org.sca4j.scdl.Include;
import org.sca4j.scdl.ModelObject;
import org.sca4j.scdl.Property;
import org.sca4j.scdl.WireDefinition;

/**
 * Loads a composite component definition from an XML-based assembly file
 *
 * @version $Rev: 5258 $ $Date: 2008-08-24 00:04:47 +0100 (Sun, 24 Aug 2008) $
 */
@EagerInit
public class CompositeLoader implements TypeLoader {
    public static final QName COMPOSITE = new QName(SCA_NS, "composite");
    public static final QName INCLUDE = new QName(SCA_NS, "include");
    public static final QName PROPERTY = new QName(SCA_NS, "property");
    public static final QName SERVICE = new QName(SCA_NS, "service");
    public static final QName REFERENCE = new QName(SCA_NS, "reference");
    public static final QName COMPONENT = new QName(SCA_NS, "component");
    public static final QName WIRE = new QName(SCA_NS, "wire");

    private static final Set ATTRIBUTES = new HashSet();

    static {
        ATTRIBUTES.add("name");
        ATTRIBUTES.add("autowire");
        ATTRIBUTES.add("targetNamespace");
        ATTRIBUTES.add("local");
        ATTRIBUTES.add("requires");
        ATTRIBUTES.add("policySets");
        ATTRIBUTES.add("constrainingType");
    }

    private final LoaderRegistry registry;
    private final Loader loader;
    private final TypeLoader includeLoader;
    private final TypeLoader propertyLoader;
    private final TypeLoader serviceLoader;
    private final TypeLoader referenceLoader;
    private final TypeLoader> componentLoader;
    private final TypeLoader wireLoader;
    private final LoaderHelper loaderHelper;

    /**
     * Constructor used during bootstrap.
     *
     * @param loader          loader for extension elements
     * @param includeLoader   loader for include elements
     * @param propertyLoader  loader for composite property elements
     * @param componentLoader loader for component elements
     * @param wireLoader      loader for wire elements
     * @param loaderHelper    helper
     */
    public CompositeLoader(Loader loader,
                           TypeLoader includeLoader,
                           TypeLoader propertyLoader,
                           TypeLoader> componentLoader,
                           TypeLoader wireLoader,
                           LoaderHelper loaderHelper) {
        this.loader = loader;
        this.includeLoader = includeLoader;
        this.propertyLoader = propertyLoader;
        this.componentLoader = componentLoader;
        this.wireLoader = wireLoader;
        this.loaderHelper = loaderHelper;

        this.registry = null;
        this.serviceLoader = null;
        this.referenceLoader = null;
    }

    /**
     * Constructor to be used when registering this component through SCDL.
     *
     * @param registry        the loader registry to register with; also used to load extension elements
     * @param includeLoader   loader for include elements
     * @param propertyLoader  loader for composite property elements
     * @param serviceLoader   loader for composite services
     * @param referenceLoader loader for composite references
     * @param componentLoader loader for component elements
     * @param wireLoader      loader for wire elements
     * @param loaderHelper    helper
     */
    @Constructor
    public CompositeLoader(@Reference LoaderRegistry registry,
                           @Reference(name = "include")TypeLoader includeLoader,
                           @Reference(name = "property")TypeLoader propertyLoader,
                           @Reference(name = "service")TypeLoader serviceLoader,
                           @Reference(name = "reference")TypeLoader referenceLoader,
                           @Reference(name = "component")TypeLoader> componentLoader,
                           @Reference(name = "wire")TypeLoader wireLoader,
                           @Reference(name = "loaderHelper")LoaderHelper loaderHelper) {
        this.registry = registry;
        this.loader = registry;
        this.includeLoader = includeLoader;
        this.propertyLoader = propertyLoader;
        this.serviceLoader = serviceLoader;
        this.referenceLoader = referenceLoader;
        this.componentLoader = componentLoader;
        this.wireLoader = wireLoader;
        this.loaderHelper = loaderHelper;
    }

    public QName getXMLType() {
        return COMPOSITE;
    }

    @Init
    public void init() {
        registry.registerLoader(COMPOSITE, this);
    }

    @Destroy
    public void destroy() {
        registry.unregisterLoader(COMPOSITE);
    }

    public Composite load(XMLStreamReader reader, IntrospectionContext introspectionContext) throws XMLStreamException {
        
        validateAttributes(reader, introspectionContext);
        String name = reader.getAttributeValue(null, "name");
        String targetNamespace = reader.getAttributeValue(null, "targetNamespace");
        boolean local = Boolean.valueOf(reader.getAttributeValue(null, "local"));
        IntrospectionContext childContext = new DefaultIntrospectionContext(introspectionContext, targetNamespace);
        QName compositeName = new QName(targetNamespace, name);
        NamespaceContext namespace = reader.getNamespaceContext();
        String constrainingTypeAttrbute = reader.getAttributeValue(null, "constrainingType");
        QName constrainingType = LoaderUtil.getQName(constrainingTypeAttrbute, targetNamespace, namespace);
        
        Composite type = new Composite(compositeName);
        type.setLocal(local);
        type.setAutowire(Autowire.fromString(reader.getAttributeValue(null, "autowire")));
        type.setConstrainingType(constrainingType);
        loaderHelper.loadPolicySetsAndIntents(type, reader, childContext);
        
        while (true) {
            switch (reader.next()) {
            case START_ELEMENT:
                QName qname = reader.getName();
                if (INCLUDE.equals(qname)) {
                    Include include = includeLoader.load(reader, childContext);
                    if (include == null) {
                        // error encountered loading the include
                        continue;
                    }
                    QName includeName = include.getName();
                    if (type.getIncludes().containsKey(includeName)) {
                        String identifier = includeName.toString();
                        DuplicateInclude failure = new DuplicateInclude(identifier, reader);
                        childContext.addError(failure);
                        continue;
                    }
                    if (childContext.hasErrors()) {
                        continue;
                    }
                    for (ComponentDefinition definition : include.getIncluded().getComponents().values()) {
                        String key = definition.getName();
                        if (type.getComponents().containsKey(key)) {
                            DuplicateComponentName failure = new DuplicateComponentName(key, reader);
                            childContext.addError(failure);
                        } else {
                            type.add(definition);
                        }
                    }
                    type.add(include);
                    // TODO do the same for services,references, wires and properties
                } else if (PROPERTY.equals(qname)) {
                    Property property = propertyLoader.load(reader, childContext);
                    if (property == null) {
                        // error encountered loading the property
                        continue;
                    }
                    String key = property.getName();
                    if (type.getProperties().containsKey(key)) {
                        DuplicateProperty failure = new DuplicateProperty(key, reader);
                        childContext.addError(failure);
                    } else {
                        type.add(property);
                    }
                } else if (SERVICE.equals(qname)) {
                    CompositeService service = serviceLoader.load(reader, childContext);
                    if (service == null) {
                        // errror encountered loading the service
                        continue;
                    }
                    if (type.getServices().containsKey(service.getName())) {
                        String key = service.getName();
                        DuplicateService failure = new DuplicateService(key, reader);
                        childContext.addError(failure);
                    } else {
                        type.add(service);
                    }
                } else if (REFERENCE.equals(qname)) {
                    CompositeReference reference = referenceLoader.load(reader, childContext);
                    if (reference == null) {
                        // errror encountered loading the reference
                        continue;
                    }
                    if (type.getReferences().containsKey(reference.getName())) {
                        String key = reference.getName();
                        DuplicatePromotedReferenceName failure = new DuplicatePromotedReferenceName(key, reader);
                        childContext.addError(failure);
                    } else {
                        type.add(reference);
                    }
                } else if (COMPONENT.equals(qname)) {
                    ComponentDefinition componentDefinition = componentLoader.load(reader, childContext);
                    if (componentDefinition == null) {
                        // errror encountered loading the componentDefinition
                        continue;
                    }
                    String key = componentDefinition.getName();
                    if (type.getComponents().containsKey(key)) {
                        DuplicateComponentName failure = new DuplicateComponentName(key, reader);
                        childContext.addError(failure);
                        continue;
                    }
                    if (type.getAutowire() != Autowire.INHERITED && componentDefinition.getAutowire() == Autowire.INHERITED) {
                        componentDefinition.setAutowire(type.getAutowire());
                    }
                    type.add(componentDefinition);
                    if (componentDefinition.isPromoted()) {
                        // Implicitly promote
                        for (String serviceName : componentDefinition.getImplementation().getServiceNames()) {
                            URI promotedUri = URI.create(key + "#" + serviceName);
                            if (type.getServices().containsKey(serviceName)) {
                                DuplicateService failure = new DuplicateService(key, reader);
                                childContext.addError(failure);
                            } else {
                                type.add(new CompositeService(serviceName, null, promotedUri));
                            }
                        }
                    }
                } else if (WIRE.equals(qname)) {
                    WireDefinition wire = wireLoader.load(reader, childContext);
                    if (wire == null) {
                        // errror encountered loading the wire
                        continue;
                    }
                    type.add(wire);
                } else {
                    // Extension element - for now try to load and see if we can handle it
                    ModelObject modelObject;
                    try {
                        modelObject = loader.load(reader, ModelObject.class, childContext);
                        // TODO when the loader registry is replaced this try..catch must be replaced with a check for a loader and an
                        // UnrecognizedElement added to the context if none is found
                    } catch (UnrecognizedElementException e) {
                        UnrecognizedElement failure = new UnrecognizedElement(reader);
                        childContext.addError(failure);
                        continue;
                    }
                    if (modelObject instanceof Property) {
                        type.add((Property) modelObject);
                    } else if (modelObject instanceof CompositeService) {
                        type.add((CompositeService) modelObject);
                    } else if (modelObject instanceof CompositeReference) {
                        type.add((CompositeReference) modelObject);
                    } else if (modelObject instanceof ComponentDefinition) {
                        type.add((ComponentDefinition) modelObject);
                    } else if (type == null) {
                        // there was an error loading the element, ingore it as the errors will have been reported
                        continue;
                    } else {
                        childContext.addError(new UnrecognizedElement(reader));
                        continue;
                    }
                }
                break;
            case END_ELEMENT:
                if (childContext.hasErrors() || childContext.hasWarnings()) {
                    if (childContext.hasErrors()) {
                        ArtifactValidationFailure artifactFailure = new ArtifactValidationFailure(compositeName.toString());
                        artifactFailure.addFailures(childContext.getErrors());
                        introspectionContext.addError(artifactFailure);
                    }
                    if (childContext.hasWarnings()) {
                        ArtifactValidationFailure artifactFailure = new ArtifactValidationFailure(compositeName.toString());
                        artifactFailure.addFailures(childContext.getWarnings());
                        introspectionContext.addWarning(artifactFailure);
                    }
                }
                return type;
            }
        }
    }

    private void validateAttributes(XMLStreamReader reader, IntrospectionContext context) {
        for (int i = 0; i < reader.getAttributeCount(); i++) {
            String name = reader.getAttributeLocalName(i);
            if (!ATTRIBUTES.contains(name)) {
                context.addError(new UnrecognizedAttribute(name, reader));
            }
        }
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy