Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix AAS generation in samm-cli native executable #514

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/release-workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ jobs:
tar cfvz samm-cli-${{ github.event.inputs.release_version }}-linux-x86_64.tar.gz samm
popd
mv tools/samm-cli/target/samm-cli-${{ github.event.inputs.release_version }}-linux-x86_64.tar.gz .
mv tools/samm-cli/target/samm-cli-*.jar .
cp tools/samm-cli/target/samm-cli-*.jar .
env:
PGP_KEY_PASSWORD: ${{ secrets.PGP_KEY_PASSWORD }}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ private MigratorFactory createMigratorFactory( final Class<?> clazz ) {
}

private void loadMigratorService() {
try ( final ScanResult scanResult = new ClassGraph().enableAllInfo().whitelistPackages(
try ( final ScanResult scanResult = new ClassGraph().enableAllInfo().acceptPackages(
MigratorFactory.class.getPackageName() ).scan() ) {
final ClassInfoList migratorFactoryClasses = scanResult
.getClassesImplementing( MigratorFactory.class.getName() );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,8 +140,7 @@ private void assertPayloadIsValid( final JsonNode schema, final Aspect aspect )
@EnumSource( value = TestAspect.class, mode = EnumSource.Mode.EXCLUDE, names = {
"ASPECT_WITH_CONSTRAINED_COLLECTION", // Broken model
"ASPECT_WITH_ENUMERATION_WITHOUT_SCALAR_VARIABLE", //Invalid Aspect Model
"MODEL_WITH_CYCLES", // contains cycles
"MODEL_WITH_BROKEN_CYCLES" // also contains cycles, but all of them should be "breakable", need to be investigated
"MODEL_WITH_BROKEN_CYCLES" // contains cycles, but all of them should be "breakable", need to be investigated
} )
public void testGeneration( final TestAspect testAspect ) {
final Aspect aspect = loadAspect( testAspect, KnownVersion.getLatest() );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@ public class RdfModelCreatorVisitorTest extends MetaModelVersions {
"ASPECT_WITH_ABSTRACT_PROPERTY",
"ASPECT_WITH_MULTIPLE_ENTITIES_SAME_EXTEND",
"ASPECT_WITH_UMLAUT_DESCRIPTION",
"MODEL_WITH_CYCLES",
"MODEL_WITH_BROKEN_CYCLES",
"MODEL_WITH_BLANK_AND_ADDITIONAL_NODES"
} )
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,20 +56,14 @@ class AspectModelValidatorTest extends MetaModelVersions {
.collect( Collectors.toMap( Function.identity(), AspectModelValidator::new ) );

@Test
void testValidAspect( ) {
void testValidAspect() {
final Try<VersionedModel> validAspectModel = TestResources.getModel( TestAspect.ASPECT, KnownVersion.getLatest() );
final List<Violation> violations = service.get( KnownVersion.getLatest() ).validateModel( validAspectModel );
assertThat( violations ).isEmpty();
}

@ParameterizedTest
@EnumSource( value = TestAspect.class, mode = EnumSource.Mode.EXCLUDE, names = {
"ASPECT_WITH_FIXED_POINT",
"ASPECT_WITH_FIXED_POINT_CONSTRAINT",
"ASPECT_WITH_LANGUAGE_CONSTRAINT",
"MODEL_WITH_CYCLES",
"MODEL_WITH_BROKEN_CYCLES"// contains cycles
} )
@EnumSource( value = TestAspect.class )
void testValidateTestAspectModel( final TestAspect testAspect ) {
final KnownVersion metaModelVersion = KnownVersion.getLatest();
final Try<VersionedModel> tryModel = TestResources.getModel( testAspect, metaModelVersion );
Expand Down Expand Up @@ -222,7 +216,7 @@ void testValidationWithMultipleAspects( final KnownVersion metaModelVersion ) {
@ParameterizedTest
@MethodSource( value = "allVersions" )
void testCycleDetection( final KnownVersion metaModelVersion ) {
final Try<VersionedModel> versionedModel = TestResources.getModel( TestAspect.MODEL_WITH_CYCLES, metaModelVersion );
final Try<VersionedModel> versionedModel = TestResources.getModel( InvalidTestAspect.MODEL_WITH_CYCLES, metaModelVersion );
final List<Violation> report = service.get( metaModelVersion ).validateModel( versionedModel );
assertThat( report ).hasSize( 7 );
assertThat( report ).containsAll( cycles(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ public enum InvalidTestAspect implements TestModel {
MISSING_ASPECT_DECLARATION,
INVALID_EXAMPLE_VALUE_DATATYPE,
INVALID_PREFERRED_NAME_DATATYPE,
RANGE_CONSTRAINT_WITH_WRONG_TYPE;
RANGE_CONSTRAINT_WITH_WRONG_TYPE,
MODEL_WITH_CYCLES;

@Override
public String getName() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,6 @@ public enum TestAspect implements TestModel {
ENTITY_INSTANCE_TEST4,
ASPECT_WITH_ENUM_ONLY_ONE_SEE,

MODEL_WITH_CYCLES,
MODEL_WITH_BROKEN_CYCLES,

ASPECT_WITH_CONSTRAINED_SET,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
<logger name="org.apache.jena" level="OFF"/>
<logger name="org.apache.jena.util" level="OFF"/>
<logger name="org.apache.jena.shared" level="OFF"/>
<logger name="org.apache.jena.shared.LockMRSW" level="OFF"/>

<root level="warn">
<appender-ref ref="console"/>
Expand Down
20 changes: 20 additions & 0 deletions tools/samm-cli/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -518,6 +518,8 @@
<arg>java.desktop/sun.awt=ALL-UNNAMED</arg>
<arg>--add-exports</arg>
<arg>java.desktop/sun.font=ALL-UNNAMED</arg>
<arg>--add-exports</arg>
<arg>org.graalvm.sdk/org.graalvm.nativeimage.impl=ALL-UNNAMED</arg>
</compilerArgs>
<forceJavacCompilerUse>true</forceJavacCompilerUse>
</configuration>
Expand Down Expand Up @@ -648,10 +650,28 @@
<mainClass>${main-class}</mainClass>
<imageName>${binary-name}</imageName>
<buildArgs>
<arg>-H:Name=${binary-name}</arg>
<arg>-H:EnableURLProtocols=http,https</arg>
<arg>--enable-https</arg>
<arg>--no-fallback</arg>
<arg>--report-unsupported-elements-at-runtime</arg>
<arg>--features=org.eclipse.esmf.nativefeatures.SammCliFeatures</arg>
<arg>--language:js</arg>
<arg>-H:JNIConfigurationFiles=src/main/resources/META-INF/native-image/${project.groupId}/${project.artifactId}/jni-config.json</arg>
<arg>-H:DynamicProxyConfigurationFiles=src/main/resources/META-INF/native-image/${project.groupId}/${project.artifactId}/proxy-config.json</arg>
<arg>-H:ReflectionConfigurationFiles=src/main/resources/META-INF/native-image/${project.groupId}/${project.artifactId}/reflect-config.json</arg>
<arg>-H:ResourceConfigurationFiles=src/main/resources/META-INF/native-image/${project.groupId}/${project.artifactId}/resource-config.json</arg>
<arg>-H:-DeadlockWatchdogExitOnTimeout</arg>
<arg>-H:DeadlockWatchdogInterval=0</arg>
<arg>-H:+AddAllCharsets</arg>
<arg>-H:+ReportExceptionStackTraces</arg>
<arg>-H:+PrintClassInitialization</arg>
<arg>-J-XX:MaxRAMPercentage=90.0</arg>
<arg>-J-XX:GCTimeRatio=19</arg>
<arg>-J--add-exports=java.desktop/sun.awt=ALL-UNNAMED</arg>
<arg>-J--add-exports=java.desktop/sun.font=ALL-UNNAMED</arg>
<arg>-J--add-exports=org.graalvm.sdk/org.graalvm.nativeimage.impl=ALL-UNNAMED</arg>
<arg>-J--add-exports=org.graalvm.nativeimage.builder/com.oracle.svm.core.configure=ALL-UNNAMED</arg>
</buildArgs>
<quickBuild>true</quickBuild>
<classpath>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@

import static picocli.CommandLine.Spec.Target.MIXEE;

import org.slf4j.LoggerFactory;

import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
import ch.qos.logback.classic.filter.ThresholdFilter;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.ConsoleAppender;
import org.apache.jena.shared.LockMRSW;
import org.slf4j.LoggerFactory;
import picocli.CommandLine;

public class LoggingMixin {
Expand Down Expand Up @@ -72,6 +72,10 @@ public void configureLoggers() {
root.detachAndStopAllAppenders();
root.setLevel( level );

// In any case disable messages from this particularly spammy and unhelpful logger
final Logger lockMrsw = loggerContext.getLogger( LockMRSW.class );
lockMrsw.setLevel( Level.OFF );

if ( level == Level.OFF ) {
return;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* Copyright (c) 2024 Robert Bosch Manufacturing Solutions GmbH
*
* See the AUTHORS file(s) distributed with this work for additional
* information regarding authorship.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*
* SPDX-License-Identifier: MPL-2.0
*/

package org.eclipse.esmf.nativefeatures;

import static org.graalvm.nativeimage.hosted.RuntimeClassInitialization.initializeAtBuildTime;

import java.util.List;

import org.eclipse.digitaltwin.aas4j.v3.dataformat.core.util.ReflectionHelper;
import org.graalvm.nativeimage.Platform;
import org.graalvm.nativeimage.Platforms;
import org.graalvm.nativeimage.hosted.Feature;

/**
* Registers all classes in the AAS model and default implementation packages for reflection in native image builds.
*/
@Platforms( Platform.HOSTED_ONLY.class )
public class AasReflection extends AbstractSammCliFeature {
@Override
public void beforeAnalysis( final BeforeAnalysisAccess access ) {
initializeAtBuildTime( org.eclipse.esmf.substitution.AdminShellConfig.class );

registerClassesInPackage( ReflectionHelper.MODEL_PACKAGE_NAME );
registerClassesInPackage( ReflectionHelper.DEFAULT_IMPLEMENTATION_PACKAGE_NAME );
}

@Override
public List<Class<? extends Feature>> getRequiredFeatures() {
return List.of( ClassGraphFeature.class );
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
* Copyright (c) 2024 Robert Bosch Manufacturing Solutions GmbH
*
* See the AUTHORS file(s) distributed with this work for additional
* information regarding authorship.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*
* SPDX-License-Identifier: MPL-2.0
*/

package org.eclipse.esmf.nativefeatures;

import io.github.classgraph.ClassGraph;
import io.github.classgraph.ScanResult;
import org.graalvm.nativeimage.hosted.Feature;
import org.graalvm.nativeimage.hosted.RuntimeReflection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* Base class for native compilation features
*/
public abstract class AbstractSammCliFeature implements Feature {
private static final Logger LOG = LoggerFactory.getLogger( AbstractSammCliFeature.class );

/**
* Registers all classes in the given package for reflection.
*
* @param packageName the package name
*/
protected void registerClassesInPackage( final String packageName ) {
try ( final ScanResult scanResult = new ClassGraph().enableAllInfo().acceptPackages( packageName ).scan() ) {
scanResult.getAllClasses().loadClasses().forEach( this::register );
}
}

/**
* Registers the given class for reflection.
*
* @param cls the class
*/
protected void register( final Class<?> cls ) {
LOG.debug( "Registering {} for reflection", cls );
RuntimeReflection.register( cls );
RuntimeReflection.register( cls.getDeclaredConstructors() );
RuntimeReflection.register( cls.getDeclaredMethods() );
RuntimeReflection.register( cls.getDeclaredFields() );
}

/**
* Returns the class for the given class name.
*
* @param className the class name
* @return the class
*/
protected Class<?> getClass( final String className ) {
try {
return Class.forName( className );
} catch ( final ClassNotFoundException exception ) {
throw new RuntimeException( "Could not access class for reflection registry", exception );
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* Copyright (c) 2024 Robert Bosch Manufacturing Solutions GmbH
*
* See the AUTHORS file(s) distributed with this work for additional
* information regarding authorship.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*
* SPDX-License-Identifier: MPL-2.0
*/

package org.eclipse.esmf.nativefeatures;

import static org.graalvm.nativeimage.hosted.RuntimeClassInitialization.initializeAtBuildTime;

/**
* Makes ClassGraph available at build time
*/
public class ClassGraphFeature extends AbstractSammCliFeature {
@Override
public void beforeAnalysis( final BeforeAnalysisAccess access ) {
initializeAtBuildTime( io.github.classgraph.AnnotationInfoList.class );
initializeAtBuildTime( io.github.classgraph.AnnotationParameterValueList.class );
initializeAtBuildTime( io.github.classgraph.ClassGraph.class );
initializeAtBuildTime( io.github.classgraph.ClassInfo.class );
initializeAtBuildTime( getClass( "io.github.classgraph.ClassInfo$2" ) );
initializeAtBuildTime( io.github.classgraph.ClassInfoList.class );
initializeAtBuildTime( io.github.classgraph.FieldInfoList.class );
initializeAtBuildTime( io.github.classgraph.MethodInfoList.class );
initializeAtBuildTime( io.github.classgraph.ModulePathInfo.class );
initializeAtBuildTime( io.github.classgraph.ScanResult.class );
initializeAtBuildTime( nonapi.io.github.classgraph.classloaderhandler.ClassLoaderHandlerRegistry.class );
initializeAtBuildTime( nonapi.io.github.classgraph.classpath.ClasspathOrder.class );
initializeAtBuildTime( nonapi.io.github.classgraph.classpath.SystemJarFinder.class );
initializeAtBuildTime( getClass( "nonapi.io.github.classgraph.classpath.SystemJarFinder$1" ) );
initializeAtBuildTime( nonapi.io.github.classgraph.fastzipfilereader.LogicalZipFile.class );
initializeAtBuildTime( getClass( "nonapi.io.github.classgraph.reflection.StandardReflectionDriver" ) );
initializeAtBuildTime( nonapi.io.github.classgraph.utils.FastPathResolver.class );
initializeAtBuildTime( nonapi.io.github.classgraph.utils.JarUtils.class );
initializeAtBuildTime( nonapi.io.github.classgraph.utils.VersionFinder.class );
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* Copyright (c) 2024 Robert Bosch Manufacturing Solutions GmbH
*
* See the AUTHORS file(s) distributed with this work for additional
* information regarding authorship.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*
* SPDX-License-Identifier: MPL-2.0
*/

package org.eclipse.esmf.nativefeatures;

import static org.graalvm.nativeimage.hosted.RuntimeClassInitialization.initializeAtBuildTime;

/**
* Configuration of eagerly initialized Jena classes
*/
public class JenaFeature extends AbstractSammCliFeature {
@Override
public void beforeAnalysis( final BeforeAnalysisAccess access ) {
initializeAtBuildTime( getClass( "com.sun.org.apache.xerces.internal.impl.Constants" ) );
initializeAtBuildTime( getClass( "com.sun.org.apache.xerces.internal.impl.XMLDTDScannerImpl" ) );
initializeAtBuildTime( getClass( "com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl" ) );
initializeAtBuildTime( getClass( "com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl" ) );
initializeAtBuildTime( getClass( "com.sun.org.apache.xerces.internal.impl.XMLEntityManager" ) );
initializeAtBuildTime( getClass( "com.sun.org.apache.xerces.internal.impl.XMLEntityManager$EncodingInfo" ) );
initializeAtBuildTime( getClass( "com.sun.org.apache.xerces.internal.impl.XMLEntityScanner" ) );
initializeAtBuildTime( getClass( "com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl" ) );
initializeAtBuildTime( getClass( "com.sun.org.apache.xerces.internal.impl.XMLScanner" ) );
initializeAtBuildTime( getClass( "com.sun.org.apache.xerces.internal.impl.XMLVersionDetector" ) );
initializeAtBuildTime( getClass( "com.sun.org.apache.xerces.internal.impl.dtd.XMLDTDProcessor" ) );
initializeAtBuildTime( getClass( "com.sun.org.apache.xerces.internal.impl.dtd.XMLDTDValidator" ) );
initializeAtBuildTime( getClass( "com.sun.org.apache.xerces.internal.impl.dtd.XMLNSDTDValidator" ) );
initializeAtBuildTime( getClass( "com.sun.org.apache.xerces.internal.impl.dv.dtd.DTDDVFactoryImpl" ) );
initializeAtBuildTime( getClass( "com.sun.org.apache.xerces.internal.util.FeatureState" ) );
initializeAtBuildTime( getClass( "com.sun.org.apache.xerces.internal.util.PropertyState" ) );
initializeAtBuildTime( getClass( "com.sun.org.apache.xerces.internal.util.XMLChar" ) );
initializeAtBuildTime( getClass( "com.sun.org.apache.xerces.internal.util.XMLSymbols" ) );
initializeAtBuildTime( getClass( "com.sun.org.apache.xerces.internal.xni.NamespaceContext" ) );
initializeAtBuildTime( getClass( "com.sun.xml.internal.stream.util.ThreadLocalBufferAllocator" ) );
initializeAtBuildTime( getClass( "javax.xml.parsers.FactoryFinder" ) );
initializeAtBuildTime( getClass( "jdk.xml.internal.JdkXmlUtils" ) );
initializeAtBuildTime( getClass( "jdk.xml.internal.SecuritySupport" ) );
initializeAtBuildTime( org.apache.jena.ext.xerces.impl.dv.xs.AnyURIDV.class );
initializeAtBuildTime( org.apache.jena.ext.xerces.impl.dv.xs.BaseSchemaDVFactory.class );
initializeAtBuildTime( org.apache.jena.ext.xerces.impl.dv.xs.ExtendedSchemaDVFactoryImpl.class );
initializeAtBuildTime( org.apache.jena.ext.xerces.impl.dv.xs.QNameDV.class );
initializeAtBuildTime( org.apache.jena.ext.xerces.impl.dv.xs.SchemaDVFactoryImpl.class );
initializeAtBuildTime( org.apache.jena.ext.xerces.impl.dv.xs.XSSimpleTypeDecl.class );
initializeAtBuildTime( org.apache.jena.ext.xerces.impl.dv.xs.XSSimpleTypeDecl.class );
initializeAtBuildTime( getClass( "org.apache.jena.ext.xerces.impl.xpath.regex.Token$CharToken" ) );
initializeAtBuildTime( getClass( "org.apache.jena.ext.xerces.impl.xpath.regex.Token$ClosureToken" ) );
initializeAtBuildTime( getClass( "org.apache.jena.ext.xerces.impl.xpath.regex.Token$ParenToken" ) );
initializeAtBuildTime( getClass( "org.apache.jena.ext.xerces.impl.xpath.regex.Token$UnionToken" ) );
initializeAtBuildTime( org.apache.jena.ext.xerces.util.XercesXMLChar.class );
}
}
Loading