Search in sources :

Example 1 with ComponentContainer

use of org.apache.felix.scrplugin.helper.ComponentContainer in project felix by apache.

the class SCRDescriptorGenerator method createComponent.

/**
 * Create the SCR objects based on the descriptions
 */
private ComponentContainer createComponent(final ClassDescription desc, final IssueLog iLog) throws SCRDescriptorException {
    final ComponentDescription componentDesc = desc.getDescription(ComponentDescription.class);
    final SpecVersion intitialComponentSpecVersion = componentDesc.getSpecVersion();
    // configuration pid in 1.2
    if (componentDesc.getConfigurationPid() != null && !componentDesc.getConfigurationPid().equals(componentDesc.getName())) {
        componentDesc.setSpecVersion(SpecVersion.VERSION_1_2);
    }
    final ComponentContainer container = new ComponentContainer(desc, componentDesc);
    // Create metatype (if required)
    final MetatypeContainer ocd;
    if (!componentDesc.isAbstract() && componentDesc.isCreateMetatype()) {
        // OCD
        ocd = new MetatypeContainer();
        container.setMetatypeContainer(ocd);
        ocd.setId(componentDesc.getName());
        if (componentDesc.getLabel() != null) {
            ocd.setName(componentDesc.getLabel());
        }
        if (componentDesc.getDescription() != null) {
            ocd.setDescription(componentDesc.getDescription());
        }
        // Factory pid
        if (componentDesc.isSetMetatypeFactoryPid()) {
            if (componentDesc.getFactory() == null) {
                ocd.setFactoryPid(componentDesc.getName());
            } else {
                iLog.addWarning("Component factory " + componentDesc.getName() + " should not set metatype factory pid.", desc.getSource());
            }
        }
    } else {
        ocd = null;
    }
    // metatype checks if metatype is not generated (FELIX-4033)
    if (!componentDesc.isAbstract() && !componentDesc.isCreateMetatype()) {
        if (componentDesc.getLabel() != null && componentDesc.getLabel().trim().length() > 0) {
            iLog.addWarning(" Component " + componentDesc.getName() + " has set a label. However metatype is set to false. This label is ignored.", desc.getSource());
        }
        if (componentDesc.getDescription() != null && componentDesc.getDescription().trim().length() > 0) {
            iLog.addWarning(" Component " + componentDesc.getName() + " has set a description. However metatype is set to false. This description is ignored.", desc.getSource());
        }
    }
    ClassDescription current = desc;
    boolean inherit;
    do {
        final ComponentDescription cd = current.getDescription(ComponentDescription.class);
        inherit = (cd == null ? true : cd.isInherit());
        if (cd != null) {
            if (current != desc) {
                iLog.addWarning(" Component " + componentDesc.getName() + " is using the " + "deprecated inheritance feature and inherits from " + current.getDescribedClass().getName() + ". This feature will be removed in future versions.", desc.getSource());
            }
            // handle enabled and immediate
            if (componentDesc.getEnabled() == null) {
                componentDesc.setEnabled(cd.getEnabled());
            }
            if (componentDesc.getImmediate() == null) {
                componentDesc.setImmediate(cd.getImmediate());
            }
            // lifecycle methods
            if (componentDesc.getActivate() == null && cd.getActivate() != null) {
                componentDesc.setActivate(cd.getActivate());
            }
            if (componentDesc.getDeactivate() == null && cd.getDeactivate() != null) {
                componentDesc.setDeactivate(cd.getDeactivate());
            }
            if (componentDesc.getModified() == null && cd.getModified() != null) {
                componentDesc.setModified(cd.getModified());
            }
            if (componentDesc.getActivate() != null || componentDesc.getDeactivate() != null || componentDesc.getModified() != null) {
                // spec version must be at least 1.1
                componentDesc.setSpecVersion(SpecVersion.VERSION_1_1);
            }
            if (componentDesc.getConfigurationPolicy() != ComponentConfigurationPolicy.OPTIONAL) {
                // policy requires 1.1
                componentDesc.setSpecVersion(SpecVersion.VERSION_1_1);
            }
        }
        // services, properties, references
        this.processServices(current, container);
        this.processProperties(current, container, ocd);
        this.processReferences(current, container);
        // go up in the class hierarchy
        if (!inherit || current.getDescribedClass().getSuperclass() == null) {
            current = null;
        } else {
            try {
                current = this.scanner.getDescription(current.getDescribedClass().getSuperclass());
            } catch (final SCRDescriptorFailureException sde) {
                this.logger.debug(sde.getMessage(), sde);
                iLog.addError(sde.getMessage(), current.getSource());
            } catch (final SCRDescriptorException sde) {
                this.logger.debug(sde.getSourceLocation() + " : " + sde.getMessage(), sde);
                iLog.addError(sde.getMessage(), sde.getSourceLocation());
            }
        }
    } while (current != null);
    // check service interfaces for properties
    if (container.getServiceDescription() != null) {
        for (final String interfaceName : container.getServiceDescription().getInterfaces()) {
            try {
                final Class<?> interfaceClass = project.getClassLoader().loadClass(interfaceName);
                final ClassDescription interfaceDesc = this.scanner.getDescription(interfaceClass);
                if (interfaceDesc != null) {
                    this.processProperties(interfaceDesc, container, ocd);
                }
            } catch (final SCRDescriptorFailureException sde) {
                this.logger.debug(sde.getMessage(), sde);
                iLog.addError(sde.getMessage(), interfaceName);
            } catch (final SCRDescriptorException sde) {
                this.logger.debug(sde.getSourceLocation() + " : " + sde.getMessage(), sde);
                iLog.addError(sde.getMessage(), sde.getSourceLocation());
            } catch (ClassNotFoundException e) {
                this.logger.debug(e.getMessage(), e);
                iLog.addError(e.getMessage(), interfaceName);
            }
        }
    }
    // global properties
    this.processGlobalProperties(desc, container.getProperties());
    // check lifecycle methods
    if (componentDesc.getActivate() == null) {
        final Validator.MethodResult result = Validator.findLifecycleMethod(project, container, "activate", true);
        if (result.method != null) {
            componentDesc.setSpecVersion(result.requiredSpecVersion);
        }
    }
    if (componentDesc.getDeactivate() == null) {
        final Validator.MethodResult result = Validator.findLifecycleMethod(project, container, "deactivate", false);
        if (result.method != null) {
            componentDesc.setSpecVersion(result.requiredSpecVersion);
        }
    }
    // check if component has spec version configured but requires a higher one
    if (intitialComponentSpecVersion != null && componentDesc.getSpecVersion().ordinal() > intitialComponentSpecVersion.ordinal()) {
        iLog.addError("Component " + container + " requires spec version " + container.getComponentDescription().getSpecVersion().name() + " but component is configured to use version " + intitialComponentSpecVersion.name(), desc.getSource());
    }
    return container;
}
Also used : ComponentDescription(org.apache.felix.scrplugin.description.ComponentDescription) MetatypeContainer(org.apache.felix.scrplugin.helper.MetatypeContainer) ClassDescription(org.apache.felix.scrplugin.description.ClassDescription) ComponentContainer(org.apache.felix.scrplugin.helper.ComponentContainer) Validator(org.apache.felix.scrplugin.helper.Validator)

Example 2 with ComponentContainer

use of org.apache.felix.scrplugin.helper.ComponentContainer in project felix by apache.

the class SCRDescriptorGenerator method execute.

/**
 * Actually generates the Declarative Services and Metatype descriptors
 * scanning the java sources provided by the {@link #setProject(Project)}
 *
 * @return A list of generated file names, relative to the output directory
 *
 * @throws SCRDescriptorException
 * @throws SCRDescriptorFailureException
 */
public Result execute() throws SCRDescriptorException, SCRDescriptorFailureException {
    this.logger.debug("Starting SCR Descriptor Generator....");
    if (this.project == null) {
        throw new SCRDescriptorFailureException("Project has not been set!");
    }
    if (this.options == null) {
        // use default options
        this.options = new Options();
    }
    if (this.options.getOutputDirectory() == null) {
        throw new SCRDescriptorFailureException("Output directory has not been set!");
    }
    this.logger.debug("..using output directory: " + this.options.getOutputDirectory());
    this.logger.debug("..strict mode: " + this.options.isStrictMode());
    this.logger.debug("..generating accessors: " + this.options.isGenerateAccessors());
    // check speck version configuration
    SpecVersion specVersion = options.getSpecVersion();
    if (specVersion == null) {
        this.logger.debug("..auto detecting spec version");
    } else {
        this.logger.debug("..using spec version " + specVersion.getName());
    }
    // create a log
    this.iLog = new IssueLog(this.options.isStrictMode());
    // create the annotation processor manager
    final AnnotationProcessor aProcessor = new AnnotationProcessorManager(this.logger, this.project.getClassLoader());
    // create the class scanner - and start scanning
    this.scanner = new ClassScanner(logger, iLog, project, aProcessor);
    final List<ClassDescription> scannedDescriptions = scanner.scanSources();
    // create the result to hold the list of processed source files
    final Result result = new Result();
    final List<ComponentContainer> processedContainers = new ArrayList<ComponentContainer>();
    for (final ClassDescription desc : scannedDescriptions) {
        this.logger.debug("Processing component class " + desc.getSource());
        result.addProcessedSourceFile(desc.getSource());
        // check if there is more than one component definition
        if (desc.getDescriptions(ComponentDescription.class).size() > 1) {
            iLog.addError("Class has more than one component definition." + " Check the annotations and merge the definitions to a single definition.", desc.getSource());
        } else {
            final ComponentContainer container = this.createComponent(desc, iLog);
            if (container.getComponentDescription().getSpecVersion() != null) {
                if (specVersion == null) {
                    specVersion = container.getComponentDescription().getSpecVersion();
                    logger.debug("Setting used spec version to " + specVersion);
                } else if (container.getComponentDescription().getSpecVersion().ordinal() > specVersion.ordinal()) {
                    if (this.options.getSpecVersion() != null) {
                        // if a spec version has been configured and a component requires a higher
                        // version, this is considered an error!
                        iLog.addError("Component " + container + " requires spec version " + container.getComponentDescription().getSpecVersion().name() + " but plugin is configured to use version " + this.options.getSpecVersion(), desc.getSource());
                    } else {
                        specVersion = container.getComponentDescription().getSpecVersion();
                        logger.debug("Setting used spec version to " + specVersion);
                    }
                }
            } else {
                if (this.options.getSpecVersion() != null) {
                    container.getComponentDescription().setSpecVersion(options.getSpecVersion());
                } else {
                    container.getComponentDescription().setSpecVersion(SpecVersion.VERSION_1_0);
                }
            }
            processedContainers.add(container);
        }
    }
    // if spec version is still not set, we're using lowest available
    if (specVersion == null) {
        specVersion = SpecVersion.VERSION_1_0;
        logger.debug("Using default spec version " + specVersion);
    }
    this.logger.debug("Generating descriptor for spec version: " + specVersion);
    options.setSpecVersion(specVersion);
    // in order to create them if possible
    if (this.options.isGenerateAccessors()) {
        for (final ComponentContainer container : processedContainers) {
            this.generateMethods(container);
        }
    }
    // now validate
    final DescriptionContainer module = new DescriptionContainer(this.options);
    for (final ComponentContainer container : processedContainers) {
        final int errorCount = iLog.getNumberOfErrors();
        final Validator validator = new Validator(container, project, options, iLog);
        validator.validate();
        // ignore component if it has errors
        if (iLog.getNumberOfErrors() == errorCount) {
            module.add(container);
        }
    }
    // log issues
    iLog.logMessages(logger);
    // after checking all classes, throw if there were any failures
    if (iLog.hasErrors()) {
        throw new SCRDescriptorFailureException("SCR Descriptor parsing had failures (see log)");
    }
    // and generate files
    result.setMetatypeFiles(MetaTypeIO.generateDescriptors(module, this.project, this.options, this.logger));
    result.setScrFiles(ComponentDescriptorIO.generateDescriptorFiles(module, this.options, logger));
    return result;
}
Also used : ArrayList(java.util.ArrayList) AnnotationProcessor(org.apache.felix.scrplugin.annotations.AnnotationProcessor) ClassDescription(org.apache.felix.scrplugin.description.ClassDescription) AnnotationProcessorManager(org.apache.felix.scrplugin.helper.AnnotationProcessorManager) IssueLog(org.apache.felix.scrplugin.helper.IssueLog) ClassScanner(org.apache.felix.scrplugin.helper.ClassScanner) DescriptionContainer(org.apache.felix.scrplugin.helper.DescriptionContainer) ComponentContainer(org.apache.felix.scrplugin.helper.ComponentContainer) Validator(org.apache.felix.scrplugin.helper.Validator)

Example 3 with ComponentContainer

use of org.apache.felix.scrplugin.helper.ComponentContainer in project felix by apache.

the class ComponentDescriptorIO method generateXML.

/**
 * Generate the xml top level element and start streaming
 * the components.
 *
 * @param components
 * @param contentHandler
 * @throws SAXException
 */
private static void generateXML(final DescriptionContainer module, final List<ComponentContainer> components, final File descriptorFile, final Log logger) throws SAXException, IOException, TransformerException {
    logger.info("Writing " + components.size() + " Service Component Descriptors to " + descriptorFile);
    FileOutputStream fos = new FileOutputStream(descriptorFile);
    try {
        final ContentHandler contentHandler = IOUtils.getSerializer(fos);
        // detect namespace to use
        final String namespace = module.getOptions().getSpecVersion().getNamespaceUrl();
        contentHandler.startDocument();
        contentHandler.startPrefixMapping(PREFIX, namespace);
        IOUtils.newline(contentHandler);
        // wrapper element to generate well formed xml if 0 or more than 1 component
        int startIndent = 0;
        if (components.size() != 1) {
            contentHandler.startElement("", ComponentDescriptorIO.COMPONENTS, ComponentDescriptorIO.COMPONENTS, new AttributesImpl());
            IOUtils.newline(contentHandler);
            startIndent = 1;
        }
        for (final ComponentContainer component : components) {
            generateXML(namespace, module, component, contentHandler, startIndent);
        }
        // end wrapper element
        if (components.size() != 1) {
            contentHandler.endElement("", ComponentDescriptorIO.COMPONENTS, ComponentDescriptorIO.COMPONENTS);
            IOUtils.newline(contentHandler);
        }
        contentHandler.endPrefixMapping(PREFIX);
        contentHandler.endDocument();
    } finally {
        fos.close();
    }
}
Also used : AttributesImpl(org.xml.sax.helpers.AttributesImpl) FileOutputStream(java.io.FileOutputStream) ComponentContainer(org.apache.felix.scrplugin.helper.ComponentContainer) ContentHandler(org.xml.sax.ContentHandler)

Example 4 with ComponentContainer

use of org.apache.felix.scrplugin.helper.ComponentContainer in project felix by apache.

the class MetaTypeIO method write.

/**
 * Generate the xml top level element and start streaming
 * the meta data.
 * @param metaData
 * @param contentHandler
 * @throws SAXException
 */
private static void write(final DescriptionContainer metaData, final List<ComponentContainer> components, final File file, final String localization) throws SCRDescriptorException {
    final String namespace = detectMetatypeVersion(metaData);
    try {
        FileOutputStream fos = new FileOutputStream(file);
        try {
            final ContentHandler contentHandler = IOUtils.getSerializer(fos);
            contentHandler.startDocument();
            contentHandler.startPrefixMapping(PREFIX, namespace);
            final AttributesImpl ai = new AttributesImpl();
            IOUtils.addAttribute(ai, "localization", localization);
            contentHandler.startElement(namespace, METADATA_ELEMENT, METADATA_ELEMENT_QNAME, ai);
            IOUtils.newline(contentHandler);
            for (final ComponentContainer comp : components) {
                if (comp.getMetatypeContainer() != null) {
                    generateOCDXML(comp.getMetatypeContainer(), contentHandler);
                    generateDesignateXML(comp.getMetatypeContainer(), contentHandler);
                }
            }
            // end wrapper element
            contentHandler.endElement(namespace, METADATA_ELEMENT, METADATA_ELEMENT_QNAME);
            IOUtils.newline(contentHandler);
            contentHandler.endPrefixMapping(PREFIX);
            contentHandler.endDocument();
        } finally {
            fos.close();
        }
    } catch (final IOException e) {
        throw new SCRDescriptorException("Unable to generate xml", file.toString(), e);
    } catch (final TransformerException e) {
        throw new SCRDescriptorException("Unable to generate xml", file.toString(), e);
    } catch (final SAXException e) {
        throw new SCRDescriptorException("Unable to generate xml", file.toString(), e);
    }
}
Also used : AttributesImpl(org.xml.sax.helpers.AttributesImpl) FileOutputStream(java.io.FileOutputStream) ComponentContainer(org.apache.felix.scrplugin.helper.ComponentContainer) IOException(java.io.IOException) ContentHandler(org.xml.sax.ContentHandler) SCRDescriptorException(org.apache.felix.scrplugin.SCRDescriptorException) TransformerException(javax.xml.transform.TransformerException) SAXException(org.xml.sax.SAXException)

Example 5 with ComponentContainer

use of org.apache.felix.scrplugin.helper.ComponentContainer in project felix by apache.

the class ComponentDescriptorIO method generateDescriptorFiles.

/**
 * Generate descriptor file(s)
 */
public static List<String> generateDescriptorFiles(final DescriptionContainer module, final Options options, final Log logger) throws SCRDescriptorException, SCRDescriptorFailureException {
    // get the list of all relevant containers
    final List<ComponentContainer> components = new ArrayList<ComponentContainer>();
    for (final ComponentContainer container : module.getComponents()) {
        if (!container.getComponentDescription().isCreateDs()) {
            logger.debug("Ignoring descriptor for DS : " + container);
        } else if (!container.getComponentDescription().isAbstract()) {
            logger.debug("Adding descriptor for DS : " + container);
            components.add(container);
        }
    }
    // check descriptor file
    final File descriptorDir = options.getComponentDescriptorDirectory();
    // terminate if there is nothing else to write
    if (components.isEmpty()) {
        logger.debug("No Service Component Descriptors found in project.");
        // remove files if it exists
        if (descriptorDir.exists() && !options.isIncremental()) {
            for (final File f : descriptorDir.listFiles()) {
                if (f.isFile()) {
                    logger.debug("Removing obsolete service descriptor " + f);
                    f.delete();
                }
            }
        }
        return null;
    }
    // finally the descriptors have to be written ....
    // ensure parent dir
    descriptorDir.mkdirs();
    final List<String> fileNames = new ArrayList<String>();
    final List<ComponentContainerContainer> containers = ComponentContainerUtil.split(components);
    for (final ComponentContainerContainer ccc : containers) {
        final SpecVersion globalVersion = module.getOptions().getSpecVersion();
        SpecVersion sv = null;
        for (final ComponentContainer cc : ccc.components) {
            if (sv == null || sv.ordinal() < cc.getComponentDescription().getSpecVersion().ordinal()) {
                sv = cc.getComponentDescription().getSpecVersion();
            }
        }
        module.getOptions().setSpecVersion(sv);
        final File useFile = new File(descriptorDir, ccc.className + ".xml");
        try {
            ComponentDescriptorIO.generateXML(module, ccc.components, useFile, logger);
        } catch (final IOException e) {
            throw new SCRDescriptorException("Unable to generate xml", useFile.toString(), e);
        } catch (final TransformerException e) {
            throw new SCRDescriptorException("Unable to generate xml", useFile.toString(), e);
        } catch (final SAXException e) {
            throw new SCRDescriptorException("Unable to generate xml", useFile.toString(), e);
        }
        fileNames.add(PARENT_NAME + '/' + useFile.getName());
        module.getOptions().setSpecVersion(globalVersion);
    }
    return fileNames;
}
Also used : ArrayList(java.util.ArrayList) IOException(java.io.IOException) SAXException(org.xml.sax.SAXException) ComponentContainerContainer(org.apache.felix.scrplugin.helper.ComponentContainerUtil.ComponentContainerContainer) SpecVersion(org.apache.felix.scrplugin.SpecVersion) ComponentContainer(org.apache.felix.scrplugin.helper.ComponentContainer) File(java.io.File) SCRDescriptorException(org.apache.felix.scrplugin.SCRDescriptorException) TransformerException(javax.xml.transform.TransformerException)

Aggregations

ComponentContainer (org.apache.felix.scrplugin.helper.ComponentContainer)6 FileOutputStream (java.io.FileOutputStream)3 IOException (java.io.IOException)3 ArrayList (java.util.ArrayList)3 SCRDescriptorException (org.apache.felix.scrplugin.SCRDescriptorException)3 File (java.io.File)2 TransformerException (javax.xml.transform.TransformerException)2 ClassDescription (org.apache.felix.scrplugin.description.ClassDescription)2 ComponentContainerContainer (org.apache.felix.scrplugin.helper.ComponentContainerUtil.ComponentContainerContainer)2 MetatypeContainer (org.apache.felix.scrplugin.helper.MetatypeContainer)2 Validator (org.apache.felix.scrplugin.helper.Validator)2 ContentHandler (org.xml.sax.ContentHandler)2 SAXException (org.xml.sax.SAXException)2 AttributesImpl (org.xml.sax.helpers.AttributesImpl)2 Properties (java.util.Properties)1 SpecVersion (org.apache.felix.scrplugin.SpecVersion)1 AnnotationProcessor (org.apache.felix.scrplugin.annotations.AnnotationProcessor)1 ComponentDescription (org.apache.felix.scrplugin.description.ComponentDescription)1 AnnotationProcessorManager (org.apache.felix.scrplugin.helper.AnnotationProcessorManager)1 ClassScanner (org.apache.felix.scrplugin.helper.ClassScanner)1