blob: 6c69b110f78ba44ec4a667759209f6e231c94565 [file] [log] [blame]
<!--
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.
-->
<jqa:jqassistant-rules xmlns:jqa="http://www.buschmais.com/jqassistant/core/analysis/rules/schema/v1.0">
<concept id="serviceLoader:SPI">
<description>Labels all .spi packages as "SPI".</description>
<cypher><![CDATA[
MATCH
(package:Package)-->(type:Type:Java)
WHERE
package.name = "spi"
SET
type:SPI
RETURN
type
]]></cypher>
</concept>
<constraint id="serviceLoader:correctServiceLoaderNaming">
<requiresConcept refId="serviceLoader:SPI"/>
<description>A service provider must be contained in a service provider configuration file with the full qualified binary name of the service's type.</description>
<cypher><![CDATA[
MATCH
(sl:ServiceLoader)-[:CONTAINS]->(impl:Type)-[:IMPLEMENTS]->(spi:SPI)
WHERE
NOT split(sl.fileName, '/')[-1] = spi.fqn
RETURN
impl.fqn AS impl, spi.fqn as spi, sl.fileName AS spiConfig
]]></cypher>
</constraint>
<constraint id="serviceLoader:ServiceImplementationsMustBeListedInServiceConfigurations"
severity="info">
<requiresConcept refId="java:AnonymousInnerType"/>
<requiresConcept refId="serviceLoader:SPI"/>
<description>All property converter implementations must be declared in a service loader file.</description>
<cypher><![CDATA[
MATCH
(impl)-[:IMPLEMENTS*]->(spi:SPI)
WHERE
NOT (:ServiceLoader)-[:CONTAINS]->(impl)
AND NOT impl:Anonymous:Inner
AND (impl.abstract=false OR impl.abstract IS NULL)
// Ignore SPI implementations without a default constructor
// We assume that the developer of this class had to implement for some reason
// this interface but not intended it to be used as service provider
AND NOT (impl)-[:DECLARES]->(:Constructor)-[:HAS]->(:Parameter)
// Do not pay attention to test utilities. We rely on the name of the class
AND NOT (impl.name =~ 'Test.*' OR impl.name =~ '.*\\$Test.*'
OR impl.name =~'.*Test\\$.*')
AND NOT impl.fqn IN [// All classes of the builder MUST not use the SPI mechanism
'org.apache.tamaya.builder.ProgrammaticConfigurationContext'
// See TAMAYA-77 and TAMAYA-78, Oliver B. Fischer, 2015-04-25
// 'org.apache.tamaya.core.internal.DefaultConfigurationContextBuilder'
]
RETURN
impl.fqn AS undeclaredService
]]></cypher>
</constraint>
<constraint id="serviceLoader:serviceConfigurationsMustNotBeEmpty">
<requiresConcept refId="serviceLoader:SPI"/>
<description>Empty service configurations must not be provided.</description>
<cypher><![CDATA[
MATCH
(sc:ServiceLoader)
WHERE
NOT (sc)-[:CONTAINS]->()
RETURN
sc.fileName AS emptyServiceConfiguration
]]></cypher>
</constraint>
<constraint id="serviceLoader:serviceConfigurationsMustNotContainNonExistingClasses">
<requiresConcept refId="serviceLoader:SPI"/>
<description>Service configurations must contain only existing classes.</description>
<cypher><![CDATA[
MATCH
(sl:ServiceLoader)-[:CONTAINS]->(entry)
WHERE
NOT entry:Class
// Have to exclude these files as jQAssistant cannot handle inner classes in
// service configurations in version 1.0.0.
// I reported this problem already to the project
// Oliver B. Fischer, 15.5.5
AND NOT sl.fileName IN ['/META-INF/services/org.apache.tamaya.core.internal.DefaultServiceContextTest$MultiImplsInterface',
'/META-INF/services/org.apache.tamaya.core.internal.DefaultServiceContextTest$InvalidPriorityInterface',
'/META-INF/services/org.apache.tamaya.core.internal.DefaultServiceContextTest$InvalidPriorityInterface']
RETURN
sl.fileName AS serviceConfiguration, entry.name AS class
]]></cypher>
</constraint>
</jqa:jqassistant-rules>