diff --git a/.github/workflows/validation.yml b/.github/workflows/validation.yml index 650e326308..fe2e1f9c53 100644 --- a/.github/workflows/validation.yml +++ b/.github/workflows/validation.yml @@ -35,7 +35,7 @@ jobs: distribution: 'temurin' java-version: 17 - name: Build DSLs - uses: GabrielBB/xvfb-action@v1 + uses: coactions/setup-xvfb@v1 with: working-directory: ./dsls run: > @@ -94,7 +94,7 @@ jobs: distribution: 'temurin' java-version: 17 - name: Build and Verify Case Studies - uses: GabrielBB/xvfb-action@v1 + uses: coactions/setup-xvfb@v1 with: working-directory: ./casestudies run: > @@ -144,7 +144,7 @@ jobs: distribution: 'temurin' java-version: 17 - name: Build and Verify Tools Adapters - uses: GabrielBB/xvfb-action@v1 + uses: coactions/setup-xvfb@v1 with: working-directory: ./tool_adapters run: > diff --git a/.gitignore b/.gitignore index ea8d7021e7..f742606ec1 100644 --- a/.gitignore +++ b/.gitignore @@ -24,6 +24,11 @@ xtend-gen/ target/ .polyglot.build.properties .mvn/wrapper/maven-wrapper.jar +*.polyglot* # Custom EvaluationData + +#IntelliJ +.idea/ +*.iml diff --git a/.mvn/extensions.xml b/.mvn/extensions.xml index f5bf8ddd25..754e258708 100644 --- a/.mvn/extensions.xml +++ b/.mvn/extensions.xml @@ -3,6 +3,6 @@ org.eclipse.tycho tycho-build - 3.0.1 + 3.0.4 \ No newline at end of file diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties index dc3affce3d..d8b2495a1e 100644 --- a/.mvn/wrapper/maven-wrapper.properties +++ b/.mvn/wrapper/maven-wrapper.properties @@ -6,7 +6,7 @@ # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # -# https://www.apache.org/licenses/LICENSE-2.0 +# 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 @@ -14,5 +14,5 @@ # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. -distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.6/apache-maven-3.8.6-bin.zip -wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.1/apache-maven-3.9.1-bin.zip +wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar diff --git a/README.md b/README.md index e5166727a4..55b3d62e55 100644 --- a/README.md +++ b/README.md @@ -4,17 +4,17 @@ [![Issues](https://img.shields.io/github/issues/vitruv-tools/Vitruv.svg)](https://github.com/vitruv-tools/Vitruv/issues) [![License](https://img.shields.io/github/license/vitruv-tools/Vitruv.svg)](https://raw.githubusercontent.com/vitruv-tools/Vitruv/main/LICENSE) -[Vitruv](https://vitruv.tools) is a framework for view-based software development. It assumes different models to be used for describing a software system, -which are automatically kept consistent by the framework and its applications. For general information on Vitruv, see our [GitHub Organisation](https://github.com/vitruv-tools) and our [Wiki](https://github.com/vitruv-tools/.github/wiki). +[Vitruvius](https://vitruv.tools) is a framework for view-based software development. It assumes different models to be used for describing a software system, +which are automatically kept consistent by the framework and its applications. For general information on Vitruvius, see our [GitHub Organisation](https://github.com/vitruv-tools) and our [Wiki](https://github.com/vitruv-tools/.github/wiki). This project contains the central definition of a V-SUM (Virtual Single Underlying Model) containing development artifacts to be kept consistent and to be accessed and modified via views. ## Installation -Vitruv can be installed in Eclipse via the [nightly update site](https://vitruv.tools/updatesite/nightly). A wiki page provides [detailed instructions for using or extending Vitruv](https://github.com/vitruv-tools/.github/wiki/Getting-Started). +Vitruvius can be installed in Eclipse via the [nightly update site](https://vitruv.tools/updatesite/nightly). A wiki page provides [detailed instructions for using or extending Vitruvius](https://github.com/vitruv-tools/.github/wiki/Getting-Started). ## Project Development -Vitruv is realized as Eclipse Plug-ins and depends on the following Eclipse tools: +Vitruvius is realized as Eclipse plug-ins and depends on the following Eclipse tools: - Eclipse Modeling Framework (EMF) _as the modelling environment_ - Xtend _for code_ diff --git a/bundles/tools.vitruv.framework.remote/.classpath b/bundles/tools.vitruv.framework.remote/.classpath index de88a448b7..4ee5a00db4 100644 --- a/bundles/tools.vitruv.framework.remote/.classpath +++ b/bundles/tools.vitruv.framework.remote/.classpath @@ -1,15 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + + + + + diff --git a/bundles/tools.vitruv.framework.remote/.settings/org.eclipse.jdt.core.prefs b/bundles/tools.vitruv.framework.remote/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000000..a9efc66a58 --- /dev/null +++ b/bundles/tools.vitruv.framework.remote/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,104 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.builder.annotationPath.allLocations=disabled +org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=disabled +org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore +org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull +org.eclipse.jdt.core.compiler.annotation.nonnull.secondary= +org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault +org.eclipse.jdt.core.compiler.annotation.nonnullbydefault.secondary= +org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable +org.eclipse.jdt.core.compiler.annotation.nullable.secondary= +org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled +org.eclipse.jdt.core.compiler.problem.APILeak=warning +org.eclipse.jdt.core.compiler.problem.annotatedTypeArgumentToUnannotated=info +org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning +org.eclipse.jdt.core.compiler.problem.autoboxing=ignore +org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning +org.eclipse.jdt.core.compiler.problem.deadCode=warning +org.eclipse.jdt.core.compiler.problem.deprecation=warning +org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled +org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled +org.eclipse.jdt.core.compiler.problem.discouragedReference=warning +org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore +org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore +org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore +org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled +org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore +org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning +org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning +org.eclipse.jdt.core.compiler.problem.forbiddenReference=error +org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning +org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled +org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning +org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning +org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore +org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore +org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning +org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore +org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore +org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled +org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled +org.eclipse.jdt.core.compiler.problem.missingSerialVersion=ignore +org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore +org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning +org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning +org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore +org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning +org.eclipse.jdt.core.compiler.problem.nonnullTypeVariableFromLegacyInvocation=warning +org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error +org.eclipse.jdt.core.compiler.problem.nullReference=warning +org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error +org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning +org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning +org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore +org.eclipse.jdt.core.compiler.problem.pessimisticNullAnalysisForFreeTypeVariables=warning +org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore +org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore +org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore +org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning +org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning +org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore +org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore +org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore +org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore +org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore +org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled +org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning +org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled +org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled +org.eclipse.jdt.core.compiler.problem.suppressWarningsNotFullyAnalysed=info +org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=disabled +org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore +org.eclipse.jdt.core.compiler.problem.terminalDeprecation=warning +org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning +org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled +org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning +org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning +org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore +org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning +org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentType=warning +org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentTypeStrict=disabled +org.eclipse.jdt.core.compiler.problem.unlikelyEqualsArgumentType=info +org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore +org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore +org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore +org.eclipse.jdt.core.compiler.problem.unstableAutoModuleName=warning +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled +org.eclipse.jdt.core.compiler.problem.unusedExceptionParameter=ignore +org.eclipse.jdt.core.compiler.problem.unusedImport=warning +org.eclipse.jdt.core.compiler.problem.unusedLabel=warning +org.eclipse.jdt.core.compiler.problem.unusedLocal=warning +org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore +org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore +org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled +org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning +org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore +org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning +org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning diff --git a/bundles/tools.vitruv.framework.remote/META-INF/MANIFEST.MF b/bundles/tools.vitruv.framework.remote/META-INF/MANIFEST.MF index d40e2f2230..54205e5626 100644 --- a/bundles/tools.vitruv.framework.remote/META-INF/MANIFEST.MF +++ b/bundles/tools.vitruv.framework.remote/META-INF/MANIFEST.MF @@ -3,12 +3,37 @@ Bundle-ManifestVersion: 2 Bundle-Name: Vitruv Framework Remote Bundle-SymbolicName: tools.vitruv.framework.remote;singleton:=true Automatic-Module-Name: tools.vitruv.framework.remote +Bundle-ClassPath: ., + target/dependency/jackson-annotations.jar, + target/dependency/jackson-core.jar, + target/dependency/jackson-databind.jar, + target/dependency/javax.servlet-api.jar, + target/dependency/jetty-client.jar, + target/dependency/jetty-http.jar, + target/dependency/jetty-io.jar, + target/dependency/jetty-security.jar, + target/dependency/jetty-server.jar, + target/dependency/jetty-servlet.jar, + target/dependency/jetty-util.jar, + target/dependency/jetty-util-ajax.jar, + target/dependency/jetty-webapp.jar, + target/dependency/jetty-xml.jar, + target/dependency/spark-core.jar, + target/dependency/websocket-api.jar, + target/dependency/websocket-client.jar, + target/dependency/websocket-common.jar, + target/dependency/websocket-server.jar, + target/dependency/websocket-servlet.jar, + target/dependency/slf4j-api.jar, + target/dependency/log4j.jar, + target/dependency/slf4j-log4j12.jar Bundle-Version: 3.0.1.qualifier Bundle-RequiredExecutionEnvironment: JavaSE-17 Require-Bundle: tools.vitruv.framework.views, tools.vitruv.change.composite, tools.vitruv.framework.vsum, - org.eclipse.emf.ecore.xmi + org.eclipse.emf.ecore.xmi, + com.google.guava Export-Package: tools.vitruv.framework.remote.client, tools.vitruv.framework.remote.client.exception, tools.vitruv.framework.remote.server diff --git a/bundles/tools.vitruv.framework.remote/build.properties b/bundles/tools.vitruv.framework.remote/build.properties index e977c868ae..431d7b208e 100644 --- a/bundles/tools.vitruv.framework.remote/build.properties +++ b/bundles/tools.vitruv.framework.remote/build.properties @@ -1,4 +1,29 @@ -source.. = src/ +source.. = src/,\ + res/ output.. = target/classes/ bin.includes = META-INF/,\ - . \ No newline at end of file + .,\ + target/dependency/jackson-annotations.jar,\ + target/dependency/jackson-core.jar,\ + target/dependency/jackson-databind.jar,\ + target/dependency/javax.servlet-api.jar,\ + target/dependency/jetty-client.jar,\ + target/dependency/jetty-http.jar,\ + target/dependency/jetty-io.jar,\ + target/dependency/jetty-security.jar,\ + target/dependency/jetty-server.jar,\ + target/dependency/jetty-servlet.jar,\ + target/dependency/jetty-util.jar,\ + target/dependency/jetty-util-ajax.jar,\ + target/dependency/jetty-webapp.jar,\ + target/dependency/jetty-xml.jar,\ + target/dependency/spark-core.jar,\ + target/dependency/websocket-api.jar,\ + target/dependency/websocket-client.jar,\ + target/dependency/websocket-common.jar,\ + target/dependency/websocket-server.jar,\ + target/dependency/websocket-servlet.jar,\ + target/dependency/slf4j-api.jar,\ + target/dependency/log4j.jar,\ + target/dependency/slf4j-log4j12.jar + diff --git a/bundles/tools.vitruv.framework.remote/lib/spark-core-2.9.4.jar b/bundles/tools.vitruv.framework.remote/lib/spark-core-2.9.4.jar deleted file mode 100644 index de106ac2c9..0000000000 Binary files a/bundles/tools.vitruv.framework.remote/lib/spark-core-2.9.4.jar and /dev/null differ diff --git a/bundles/tools.vitruv.framework.remote/res/log4j.properties b/bundles/tools.vitruv.framework.remote/res/log4j.properties new file mode 100644 index 0000000000..bf94e7b8e8 --- /dev/null +++ b/bundles/tools.vitruv.framework.remote/res/log4j.properties @@ -0,0 +1,8 @@ +# Root logger option +log4j.rootLogger=INFO, stdout + +# Direct log messages to stdout +log4j.appender.stdout=org.apache.log4j.ConsoleAppender +log4j.appender.stdout.Target=System.out +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout +log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n \ No newline at end of file diff --git a/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/client/ChangeDerivingRemoteView.java b/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/client/ChangeDerivingRemoteView.java deleted file mode 100644 index 13f845ac4c..0000000000 --- a/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/client/ChangeDerivingRemoteView.java +++ /dev/null @@ -1,136 +0,0 @@ -package tools.vitruv.framework.remote.client; - -import java.util.Collection; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.Map; - -import org.eclipse.emf.common.util.URI; -import org.eclipse.emf.ecore.EObject; -import org.eclipse.emf.ecore.resource.Resource; -import org.eclipse.emf.ecore.resource.ResourceSet; - -import tools.vitruv.change.composite.description.VitruviusChange; -import tools.vitruv.change.composite.description.VitruviusChangeFactory; -import tools.vitruv.framework.views.CommittableView; -import tools.vitruv.framework.views.ViewSelection; -import tools.vitruv.framework.views.ViewSelector; -import tools.vitruv.framework.views.ViewType; -import tools.vitruv.framework.views.changederivation.StateBasedChangeResolutionStrategy; -import tools.vitruv.framework.remote.common.util.ResourceUtils; - -/** - * A {@link RemoteView} that derives changes based on the changed state of its resources and allows to propagate them - * back to the vitruv server using the {@link #commitChanges} method. - */ -public class ChangeDerivingRemoteView implements CommittableView { - - private final RemoteView base; - private final StateBasedChangeResolutionStrategy resolutionStrategy; - - private Map originalResourceMapping; - - ChangeDerivingRemoteView(RemoteView base, StateBasedChangeResolutionStrategy resolutionStrategy) { - this.base = base; - this.resolutionStrategy = resolutionStrategy;; - - initializeResourceMapping(base.viewSource); - } - - private void initializeResourceMapping(ResourceSet source) { - originalResourceMapping = new HashMap<>(); - source.getResources().forEach(it -> originalResourceMapping.put(it, ResourceUtils.copyResource(it))); - } - - @Override - public void close() { - base.close(); - } - - @Override - public Collection getRootObjects() { - return base.getRootObjects(); - } - - @Override - public boolean isModified() { - return base.isModified(); - } - - @Override - public boolean isOutdated() { - return base.isOutdated(); - } - - @Override - public void update() { - base.update(); - initializeResourceMapping(base.viewSource); - } - - @Override - public boolean isClosed() { - return base.isClosed(); - } - - @Override - public void registerRoot(EObject object, URI persistAt) { - base.registerRoot(object, persistAt); - } - - @Override - public void moveRoot(EObject object, URI newLocation) { - base.moveRoot(object, newLocation); - } - - @Override - public ViewSelection getSelection() { - return base.getSelection(); - } - - @Override - public ViewType getViewType() { - return base.getViewType(); - } - - @Override - public CommittableView withChangeRecordingTrait() { - return base.withChangeRecordingTrait(); - } - - @Override - public CommittableView withChangeDerivingTrait(StateBasedChangeResolutionStrategy changeResolutionStrategy) { - return base.withChangeDerivingTrait(changeResolutionStrategy); - } - - /** - * Commits the changes made to the view and its containing elements. - * - * @throws IllegalStateException if called on a closed view - * @see #isClosed() - * @see #commitChangesAndUpdate() - */ - @Override - public void commitChanges() { - base.checkNotClosed(); - var allChanges = new LinkedList(); - base.viewSource.getResources().forEach(it -> { - var changes = findChanges(originalResourceMapping.get(it), it); - if (changes.getEChanges().size() > 0) { - allChanges.add(changes); - } - }); - base.remoteConnection.propagateChanges(base.uuid, VitruviusChangeFactory.getInstance().createCompositeChange(allChanges)); - base.modified = false; - } - - private VitruviusChange findChanges(Resource oldState, Resource newState) { - if (oldState == null) { - return resolutionStrategy.getChangeSequenceForCreated(newState); - } else if (newState == null) { - return resolutionStrategy.getChangeSequenceForDeleted(oldState); - } else { - return resolutionStrategy.getChangeSequenceBetween(newState, oldState); - } - } -} diff --git a/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/client/VitruvClient.java b/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/client/VitruvClient.java new file mode 100644 index 0000000000..69da0cc3e6 --- /dev/null +++ b/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/client/VitruvClient.java @@ -0,0 +1,31 @@ +package tools.vitruv.framework.remote.client; + +import tools.vitruv.framework.remote.client.exception.BadServerResponseException; +import tools.vitruv.framework.views.View; + +import java.util.List; + +/** + * A vitruv client can connect to a vitruv server and query view type names and views from this server. + */ +public interface VitruvClient { + + /** + * Queries the vitruvius server to gain a list of all available view type names. + * + * @return A {@link List} of view type names. + * @throws BadServerResponseException if the server answered with a bad response or a connection error occurred. + */ + List queryViewTypes() throws BadServerResponseException; + + /** + * Queries the vitruvius server to obtain the view described through the view type with the given name. + * The {@link View views} returned from this method are responsible to synchronize changes with + * the vitruv server themselves. + * + * @param typeName the name of the view type + * @return A {@link View} of the given view type. + * @throws BadServerResponseException if the server answered with a bad response or a connection error occurred. + */ + View queryView(String typeName) throws BadServerResponseException; +} diff --git a/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/client/VitruvClientFactory.java b/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/client/VitruvClientFactory.java new file mode 100644 index 0000000000..917842ecc3 --- /dev/null +++ b/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/client/VitruvClientFactory.java @@ -0,0 +1,30 @@ +package tools.vitruv.framework.remote.client; + +import tools.vitruv.framework.remote.client.impl.VitruvRemoteConnection; + +public class VitruvClientFactory { + + public static final int STD_PORT = 8080; + + /** + * Creates a new {@link VitruvClient} using the given url and the standard port of 8080. + * + * @param url of the vitruv server + * @return a {@link VitruvClient} + */ + public static VitruvClient create(String url) { + return create(url, STD_PORT); + } + + /** + * Creates a new {@link VitruvClient} using the given url and port. + * + * @param url of the vitruv server + * @param port of the vitruv server + * @return a {@link VitruvClient} + */ + public static VitruvClient create(String url, int port) { + return new VitruvRemoteConnection(url, port); + } + +} diff --git a/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/client/impl/ChangeDerivingRemoteView.java b/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/client/impl/ChangeDerivingRemoteView.java new file mode 100644 index 0000000000..bd35f8189e --- /dev/null +++ b/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/client/impl/ChangeDerivingRemoteView.java @@ -0,0 +1,143 @@ +package tools.vitruv.framework.remote.client.impl; + +import java.util.Collection; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.Map; + +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.emf.ecore.resource.ResourceSet; + +import tools.vitruv.change.composite.description.VitruviusChange; +import tools.vitruv.change.composite.description.VitruviusChangeFactory; +import tools.vitruv.framework.views.CommittableView; +import tools.vitruv.framework.views.ViewSelection; +import tools.vitruv.framework.views.ViewSelector; +import tools.vitruv.framework.views.ViewType; +import tools.vitruv.framework.views.changederivation.StateBasedChangeResolutionStrategy; +import tools.vitruv.framework.remote.common.util.ResourceUtils; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkState; + +/** + * A {@link RemoteView} that derives changes based on the changed state of its resources and allows to propagate them + * back to the vitruv server using the {@link #commitChanges} method. + */ +public class ChangeDerivingRemoteView implements CommittableView { + + private final RemoteView base; + private final StateBasedChangeResolutionStrategy resolutionStrategy; + + private Map originalResourceMapping; + + ChangeDerivingRemoteView(RemoteView base, StateBasedChangeResolutionStrategy resolutionStrategy) { + checkArgument(base != null, "base must not be null"); + checkState(!base.isModified(), "view must not be modified"); + checkState(!base.isOutdated(), "view must not be outdated"); + checkArgument(resolutionStrategy != null, "resolution strategy must not be null"); + this.base = base; + this.resolutionStrategy = resolutionStrategy; + + initializeResourceMapping(base.viewSource); + } + + private void initializeResourceMapping(ResourceSet source) { + originalResourceMapping = new HashMap<>(); + source.getResources().forEach(it -> originalResourceMapping.put(it, ResourceUtils.copyResource(it))); + } + + @Override + public void close() { + base.close(); + } + + @Override + public Collection getRootObjects() { + return base.getRootObjects(); + } + + @Override + public boolean isModified() { + return base.isModified(); + } + + @Override + public boolean isOutdated() { + return base.isOutdated(); + } + + @Override + public void update() { + base.update(); + initializeResourceMapping(base.viewSource); + } + + @Override + public boolean isClosed() { + return base.isClosed(); + } + + @Override + public void registerRoot(EObject object, URI persistAt) { + base.registerRoot(object, persistAt); + } + + @Override + public void moveRoot(EObject object, URI newLocation) { + base.moveRoot(object, newLocation); + } + + @Override + public ViewSelection getSelection() { + return base.getSelection(); + } + + @Override + public ViewType getViewType() { + return base.getViewType(); + } + + @Override + public CommittableView withChangeRecordingTrait() { + return base.withChangeRecordingTrait(); + } + + @Override + public CommittableView withChangeDerivingTrait(StateBasedChangeResolutionStrategy changeResolutionStrategy) { + return base.withChangeDerivingTrait(changeResolutionStrategy); + } + + /** + * Commits the changes made to the view and its containing elements. + * + * @throws IllegalStateException if called on a closed view + * @see #isClosed() + * @see #commitChangesAndUpdate() + */ + @Override + public void commitChanges() { + base.checkNotClosed(); + var allChanges = new LinkedList(); + base.viewSource.getResources().forEach(it -> { + var changes = findChanges(originalResourceMapping.get(it), it); + if (changes.getEChanges().size() > 0) { + allChanges.add(changes); + } + }); + base.remoteConnection.propagateChanges(base.uuid, VitruviusChangeFactory.getInstance().createCompositeChange(allChanges)); + base.modified = false; + } + + private VitruviusChange findChanges(Resource oldState, Resource newState) { + if (oldState == null) { + return resolutionStrategy.getChangeSequenceForCreated(newState); + } else if (newState == null) { + return resolutionStrategy.getChangeSequenceForDeleted(oldState); + } else { + return resolutionStrategy.getChangeSequenceBetween(newState, oldState); + } + } +} diff --git a/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/client/ChangeRecordingRemoteView.java b/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/client/impl/ChangeRecordingRemoteView.java similarity index 91% rename from bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/client/ChangeRecordingRemoteView.java rename to bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/client/impl/ChangeRecordingRemoteView.java index 4c51a3d38e..3c2df772a5 100644 --- a/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/client/ChangeRecordingRemoteView.java +++ b/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/client/impl/ChangeRecordingRemoteView.java @@ -1,4 +1,4 @@ -package tools.vitruv.framework.remote.client; +package tools.vitruv.framework.remote.client.impl; import java.util.Collection; @@ -12,6 +12,10 @@ import tools.vitruv.framework.views.ViewType; import tools.vitruv.framework.views.changederivation.StateBasedChangeResolutionStrategy; +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkState; + + /** * A {@link RemoteView} that records changes to its resources and allows to propagate them * back to the vitruv server using the {@link #commitChanges} method. @@ -22,6 +26,8 @@ public class ChangeRecordingRemoteView implements CommittableView { private ChangeRecorder changeRecorder; public ChangeRecordingRemoteView(RemoteView base) { + checkArgument(base != null, "base must not be null"); + checkState(!base.isModified(), "view must not be modified"); this.base = base; setupChangeRecorder(); } diff --git a/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/client/RemoteView.java b/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/client/impl/RemoteView.java similarity index 88% rename from bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/client/RemoteView.java rename to bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/client/impl/RemoteView.java index a23b9c4f92..86abe7a498 100644 --- a/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/client/RemoteView.java +++ b/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/client/impl/RemoteView.java @@ -1,4 +1,4 @@ -package tools.vitruv.framework.remote.client; +package tools.vitruv.framework.remote.client.impl; import java.util.Collection; @@ -17,6 +17,9 @@ import tools.vitruv.framework.views.ViewType; import tools.vitruv.framework.views.changederivation.StateBasedChangeResolutionStrategy; +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkState; + /** * A {@link View} which is a copy of a {@link View} from the VSUM of a vitruv server. *

@@ -32,6 +35,9 @@ public class RemoteView implements View { protected boolean modified = false; RemoteView(String uuid, ResourceSet viewSource, VitruvRemoteConnection remoteConnection) { + checkArgument(uuid != null, "uuid must not be null"); + checkArgument(viewSource != null, "view source must not be null"); + checkArgument(remoteConnection != null, "remote connection must not be null"); this.uuid = uuid; this.remoteConnection = remoteConnection; this.viewSource = viewSource; @@ -126,7 +132,7 @@ public void registerRoot(EObject object, URI persistAt) { public void moveRoot(EObject object, URI newLocation) { checkNotClosed(); checkArgument(object != null, "object to move must not be null"); - checkState(getRootObjects().contains(object), "view must contain element to move"); + checkState(getRootObjects().contains(object), "view must contain element %s to move", object); checkArgument(newLocation != null, "URI for new location of root must not be null"); viewSource.getResources().stream().filter(it -> it.getContents().contains(object)).findFirst().get().setURI(newLocation); } @@ -185,19 +191,7 @@ public CommittableView withChangeDerivingTrait(StateBasedChangeResolutionStrateg } void checkNotClosed() { - checkState(!isClosed(), "View is already closed"); - } - - void checkState(boolean state, String msg) { - if (!state) { - throw new IllegalStateException(msg); - } - } - - void checkArgument(boolean arg, String msg) { - if (!arg) { - throw new IllegalArgumentException(msg); - } + checkState(!isClosed(), "view is already closed"); } private void addChangeListeners(Notifier notifier) { @@ -208,12 +202,12 @@ public void notifyChanged(Notification message) { } }); - if (notifier instanceof ResourceSet n) { - n.getResources().forEach(this::addChangeListeners); - } else if (notifier instanceof Resource n) { - n.getContents().forEach(this::addChangeListeners); - } else if (notifier instanceof EObject n) { - n.eContents().forEach(this::addChangeListeners); + if (notifier instanceof ResourceSet resourceSet) { + resourceSet.getResources().forEach(this::addChangeListeners); + } else if (notifier instanceof Resource resource) { + resource.getContents().forEach(this::addChangeListeners); + } else if (notifier instanceof EObject eObject) { + eObject.eContents().forEach(this::addChangeListeners); } } diff --git a/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/client/VitruvRemoteConnection.java b/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/client/impl/VitruvRemoteConnection.java similarity index 64% rename from bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/client/VitruvRemoteConnection.java rename to bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/client/impl/VitruvRemoteConnection.java index 9e3436b003..438c26c2bd 100644 --- a/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/client/VitruvRemoteConnection.java +++ b/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/client/impl/VitruvRemoteConnection.java @@ -1,4 +1,4 @@ -package tools.vitruv.framework.remote.client; +package tools.vitruv.framework.remote.client.impl; import java.io.IOException; import java.net.URI; @@ -7,42 +7,29 @@ import java.net.http.HttpRequest.BodyPublishers; import java.net.http.HttpResponse.BodyHandlers; import java.util.List; +import java.util.Objects; import org.eclipse.emf.ecore.resource.ResourceSet; import tools.vitruv.change.composite.description.VitruviusChange; +import tools.vitruv.framework.remote.client.VitruvClient; import tools.vitruv.framework.remote.client.exception.BadServerResponseException; import tools.vitruv.framework.remote.common.util.ContentTypes; +import tools.vitruv.framework.remote.common.util.EndpointPaths; import tools.vitruv.framework.remote.common.util.Headers; import tools.vitruv.framework.remote.common.util.JsonMapper; +import tools.vitruv.framework.views.View; /** - * A {@link VitruvRemoteConnection} acts as a {@link HttpClient} to forward requests to a vitruvius server, where a vitruvius instance is hosted. + * A {@link VitruvRemoteConnection} acts as a {@link HttpClient} to forward requests to a vitruvius server. * This enables the ability to perform actions on this remote vitruvius instance. */ -public class VitruvRemoteConnection { - - private static final int STD_PORT = 8080; - private static final String VIEW_TYPES = "vsum/viewtypes"; - private static final String VIEW = "vsum/view"; - private static final String VIEW_OUTDATED = "vsum/view/outdated"; - private static final String VIEW_CLOSED = "vsum/view/closed"; - private static final String VIEW_UPDATE = "vsum/view/update"; - private static final String CHANGE_PROPAGATION = "vsum/change"; +public class VitruvRemoteConnection implements VitruvClient { private final int port; private final String url; private final HttpClient client; - /** - * Creates a new {@link VitruvRemoteConnection} using the given URL and the standard port 8080 to connect to the vitruvius server. - * - * @param url of the vitruvius server - */ - public VitruvRemoteConnection(String url) { - this(url, STD_PORT); - } - /** * Creates a new {@link VitruvRemoteConnection} using the given URL and port to connect to the vitruvius server. * @@ -56,32 +43,25 @@ public VitruvRemoteConnection(String url, int port) { } /** - * Queries the vitruvius server to gain a list of all available view type names. - * - * @return A {@link List} of view type names. - * @throws BadServerResponseException if the server answered with a bad response or a connection error occurred. + * @inheritDoc */ - public List getViewTypes() throws BadServerResponseException { + public List queryViewTypes() throws BadServerResponseException { var request = HttpRequest.newBuilder() - .uri(URI.create(String.format("http://%s:%d/%s", url, port, VIEW_TYPES))).GET().build(); + .uri(createURIFrom(url, port, EndpointPaths.VIEW_TYPES)).GET().build(); try { var response = client.send(request, BodyHandlers.ofString()); - return JsonMapper.deserializeListOf(response.body(), String.class); + return JsonMapper.deserializeArrayOf(response.body(), String.class); } catch (IOException | InterruptedException e) { throw new BadServerResponseException(e); } } /** - * Queries the vitruvius server to obtain the view described through the view type with the given name. - * - * @param typeName the name of the view type - * @return A {@link RemoteView} of the given view type. - * @throws BadServerResponseException if the server answered with a bad response or a connection error occurred. + * @inheritDoc */ - public RemoteView getView(String typeName) throws BadServerResponseException { + public View queryView(String typeName) throws BadServerResponseException { var request = HttpRequest.newBuilder() - .uri(URI.create(String.format("http://%s:%d/%s", url, port, VIEW))) + .uri(createURIFrom(url, port, EndpointPaths.VIEW)) .header(Headers.VIEW_TYPE, typeName) .GET() .build(); @@ -107,14 +87,15 @@ public RemoteView getView(String typeName) throws BadServerResponseException { * @throws BadServerResponseException if the server answered with a bad response or a connection error occurred. */ void propagateChanges(String uuid, VitruviusChange change) throws BadServerResponseException { - var jsonBody = JsonMapper.serialize(change); - var request = HttpRequest.newBuilder() - .uri(URI.create(String.format("http://%s:%d/%s", url, port, CHANGE_PROPAGATION))) - .header(Headers.CONTENT_TYPE, ContentTypes.APPLICATION_JSON) - .header(Headers.VIEW_UUID, uuid) - .POST(BodyPublishers.ofString(jsonBody)) - .build(); try { + var jsonBody = JsonMapper.serialize(change); + var request = HttpRequest.newBuilder() + .uri(createURIFrom(url, port, EndpointPaths.VIEW)) + .header(Headers.CONTENT_TYPE, ContentTypes.APPLICATION_JSON) + .header(Headers.VIEW_UUID, uuid) + .POST(BodyPublishers.ofString(jsonBody)) + .build(); + client.send(request, BodyHandlers.discarding()); } catch (IOException | InterruptedException e) { throw new BadServerResponseException(e); @@ -122,43 +103,38 @@ void propagateChanges(String uuid, VitruviusChange change) throws BadServerRespo } /** - * Queries the vitruvius serve to check if the view with the given id is closed. + * Queries the vitruvius server to close the view with the given. * * @param uuid of the view - * @return {@code true} if the view is closed, {@code false} otherwise. * @throws BadServerResponseException if the server answered with a bad response or a connection error occurred. */ - boolean isViewClosed(String uuid) throws BadServerResponseException { + void closeView(String uuid) throws BadServerResponseException { var request = HttpRequest.newBuilder() - .uri(URI.create(String.format("http://%s:%d/%s", url, port, VIEW_CLOSED))) + .uri(createURIFrom(url, port, EndpointPaths.VIEW)) .header(Headers.VIEW_UUID, uuid) - .GET() + .DELETE() .build(); try { - var response = client.send(request, BodyHandlers.ofString()); - return response.body().equals(Boolean.TRUE.toString()); + client.send(request, BodyHandlers.discarding()); } catch (IOException | InterruptedException e) { throw new BadServerResponseException(e); } } /** - * Queries the vitruvius server to close the view with the given. + * Queries the vitruvius serve to check if the view with the given id is closed. * * @param uuid of the view + * @return {@code true} if the view is closed, {@code false} otherwise. * @throws BadServerResponseException if the server answered with a bad response or a connection error occurred. */ - void closeView(String uuid) throws BadServerResponseException { + boolean isViewClosed(String uuid) throws BadServerResponseException { var request = HttpRequest.newBuilder() - .uri(URI.create(String.format("http://%s:%d/%s", url, port, VIEW_CLOSED))) + .uri(createURIFrom(url, port, EndpointPaths.IS_VIEW_CLOSED)) .header(Headers.VIEW_UUID, uuid) - .POST(BodyPublishers.noBody()) + .GET() .build(); - try { - client.send(request, BodyHandlers.discarding()); - } catch (IOException | InterruptedException e) { - throw new BadServerResponseException(e); - } + return sendRequestAndCheckResult(request); } /** @@ -169,13 +145,21 @@ void closeView(String uuid) throws BadServerResponseException { */ boolean isViewOutdated(String uuid) { var request = HttpRequest.newBuilder() - .uri(URI.create(String.format("http://%s:%d/%s", url, port, VIEW_OUTDATED))) + .uri(createURIFrom(url, port, EndpointPaths.IS_VIEW_OUTDATED)) .header(Headers.VIEW_UUID, uuid) .GET() .build(); + return sendRequestAndCheckResult(request); + } + + private boolean sendRequestAndCheckResult(HttpRequest request) { try { var response = client.send(request, BodyHandlers.ofString()); - return response.body().equals(Boolean.TRUE.toString()); + var value = response.body(); + if (!Objects.equals(value, Boolean.TRUE.toString()) && !Objects.equals(value, Boolean.FALSE.toString())) { + throw new BadServerResponseException("Expected response to be true or false! Actual: " + value); + } + return value.equals(Boolean.TRUE.toString()); } catch (IOException | InterruptedException e) { throw new BadServerResponseException(e); } @@ -190,9 +174,9 @@ boolean isViewOutdated(String uuid) { */ ResourceSet updateView(String uuid) throws BadServerResponseException { var request = HttpRequest.newBuilder() - .uri(URI.create(String.format("http://%s:%d/%s", url, port, VIEW_UPDATE))) + .uri(createURIFrom(url, port, EndpointPaths.VIEW)) .header(Headers.VIEW_UUID, uuid) - .GET() + .method("PATCH", HttpRequest.BodyPublishers.noBody()) .build(); try { var response = client.send(request, BodyHandlers.ofString()); @@ -204,4 +188,8 @@ ResourceSet updateView(String uuid) throws BadServerResponseException { throw new BadServerResponseException(e); } } + + private static URI createURIFrom(String url, int port, String path) { + return URI.create(String.format("http://%s:%d%s", url, port, path)); + } } diff --git a/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/common/deserializer/ResourceDeserializer.java b/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/common/deserializer/ResourceDeserializer.java index 711cc4fbe9..d67c2e14c8 100644 --- a/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/common/deserializer/ResourceDeserializer.java +++ b/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/common/deserializer/ResourceDeserializer.java @@ -5,22 +5,22 @@ import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.resource.Resource; -import com.fasterxml.jackson.core.JacksonException; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonDeserializer; import com.fasterxml.jackson.databind.node.TextNode; import tools.vitruv.framework.remote.common.util.ResourceUtils; +import tools.vitruv.framework.remote.common.util.SerializationConstants; public class ResourceDeserializer extends JsonDeserializer { @Override - public Resource deserialize(JsonParser p, DeserializationContext c) throws IOException, JacksonException { - var rootNode = p.getCodec().readTree(p); + public Resource deserialize(JsonParser parser, DeserializationContext context) throws IOException { + var rootNode = parser.getCodec().readTree(parser); - var uri = ((TextNode)rootNode.get("uri")).asText(); - var content = ((TextNode)rootNode.get("content")).asText(); + var uri = ((TextNode)rootNode.get(SerializationConstants.URI)).asText(); + var content = ((TextNode)rootNode.get(SerializationConstants.CONTENT)).asText(); return ResourceUtils.deserialize(URI.createURI(uri), content); } diff --git a/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/common/deserializer/ResourceSetDeserializer.java b/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/common/deserializer/ResourceSetDeserializer.java index 5cdbce7ec7..1feb318977 100644 --- a/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/common/deserializer/ResourceSetDeserializer.java +++ b/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/common/deserializer/ResourceSetDeserializer.java @@ -7,7 +7,6 @@ import org.eclipse.emf.ecore.resource.ResourceSet; import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl; -import com.fasterxml.jackson.core.JacksonException; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonDeserializer; @@ -16,12 +15,12 @@ public class ResourceSetDeserializer extends JsonDeserializer { @Override - public ResourceSet deserialize(JsonParser p, DeserializationContext c) throws IOException, JacksonException { - var rootNode = (ArrayNode) p.getCodec().readTree(p); + public ResourceSet deserialize(JsonParser parser, DeserializationContext context) throws IOException { + var rootNode = (ArrayNode) parser.getCodec().readTree(parser); var resources = new LinkedList(); for (var e : rootNode) { - resources.add(c.readTreeAsValue(e, Resource.class)); + resources.add(context.readTreeAsValue(e, Resource.class)); } var resourceSet = new ResourceSetImpl(); diff --git a/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/common/deserializer/VitruviusChangeDeserializer.java b/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/common/deserializer/VitruviusChangeDeserializer.java index 9e472f1295..59e68f063f 100644 --- a/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/common/deserializer/VitruviusChangeDeserializer.java +++ b/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/common/deserializer/VitruviusChangeDeserializer.java @@ -5,7 +5,6 @@ import org.eclipse.emf.common.util.URI; -import com.fasterxml.jackson.core.JacksonException; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonDeserializer; @@ -15,35 +14,35 @@ import tools.vitruv.change.atomic.EChange; import tools.vitruv.change.composite.description.VitruviusChange; import tools.vitruv.change.composite.description.VitruviusChangeFactory; +import tools.vitruv.framework.remote.common.util.SerializationConstants; import tools.vitruv.framework.remote.common.util.ChangeType; import tools.vitruv.framework.remote.common.util.IdTransformation; import tools.vitruv.framework.remote.common.util.ResourceUtils; public class VitruviusChangeDeserializer extends JsonDeserializer { - @Override - public VitruviusChange deserialize(JsonParser p, DeserializationContext c) throws IOException, JacksonException { - var rootNode = p.getCodec().readTree(p); - var type = c.readTreeAsValue((TextNode) rootNode.get("changeType"), ChangeType.class); + @Override + public VitruviusChange deserialize(JsonParser parser, DeserializationContext context) throws IOException { + var rootNode = parser.getCodec().readTree(parser); + var type = context.readTreeAsValue((TextNode) rootNode.get(SerializationConstants.CHANGE_TYPE), ChangeType.class); - VitruviusChange change = null; - if (type == ChangeType.TRANSACTIONAL) { - var json = ((TextNode)rootNode.get("eChanges")).asText(); - var changesResource = ResourceUtils.deserialize(URI.createURI("temp"), json); - var eChanges = changesResource.getContents().stream().map(e -> (EChange) e).toList(); - IdTransformation.allToGlobal(eChanges); - change = VitruviusChangeFactory.getInstance().createTransactionalChange(eChanges); - } else if (type == ChangeType.COMPOSITE) { - var changesNode = (ArrayNode) rootNode.get("vChanges"); - var changes = new LinkedList(); - for (var e : changesNode) { - changes.add(c.readTreeAsValue(e, VitruviusChange.class)); - } - change = VitruviusChangeFactory.getInstance().createCompositeChange(changes); - } - else { - throw new UnsupportedOperationException("Change deserialization for type" + type + " not implemented!"); - } - return change; - } + VitruviusChange change; + if (type == ChangeType.TRANSACTIONAL) { + var jsonString = ((TextNode) rootNode.get(SerializationConstants.E_CHANGES)).asText(); + var changesResource = ResourceUtils.deserialize(URI.createURI(SerializationConstants.TEMP), jsonString); + var eChanges = changesResource.getContents().stream().map(e -> (EChange) e).toList(); + IdTransformation.allToGlobal(eChanges); + change = VitruviusChangeFactory.getInstance().createTransactionalChange(eChanges); + } else if (type == ChangeType.COMPOSITE) { + var changesNode = (ArrayNode) rootNode.get(SerializationConstants.V_CHANGES); + var changes = new LinkedList(); + for (var e : changesNode) { + changes.add(context.readTreeAsValue(e, VitruviusChange.class)); + } + change = VitruviusChangeFactory.getInstance().createCompositeChange(changes); + } else { + throw new UnsupportedOperationException("Change deserialization for type" + type + " not implemented!"); + } + return change; + } } diff --git a/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/common/serializer/ResourceSerializer.java b/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/common/serializer/ResourceSerializer.java index 866651f722..089f3b8de6 100644 --- a/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/common/serializer/ResourceSerializer.java +++ b/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/common/serializer/ResourceSerializer.java @@ -10,14 +10,15 @@ import tools.vitruv.framework.remote.common.util.IdTransformation; import tools.vitruv.framework.remote.common.util.ResourceUtils; +import tools.vitruv.framework.remote.common.util.SerializationConstants; -public class ResourceSerializer extends JsonSerializer{ +public class ResourceSerializer extends JsonSerializer { - @Override - public void serialize(Resource r, JsonGenerator g, SerializerProvider p) throws IOException { - g.writeStartObject(); - g.writeStringField("uri", IdTransformation.toLocal(r.getURI().toString())); - g.writeStringField("content", ResourceUtils.serialize(r)); - g.writeEndObject(); - } + @Override + public void serialize(Resource resource, JsonGenerator generator, SerializerProvider provider) throws IOException { + generator.writeStartObject(); + generator.writeStringField(SerializationConstants.URI, IdTransformation.toLocal(resource.getURI().toString())); + generator.writeStringField(SerializationConstants.CONTENT, ResourceUtils.serialize(resource)); + generator.writeEndObject(); + } } diff --git a/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/common/serializer/ResourceSetSerializer.java b/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/common/serializer/ResourceSetSerializer.java index 68e07547e9..31d23fdb94 100644 --- a/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/common/serializer/ResourceSetSerializer.java +++ b/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/common/serializer/ResourceSetSerializer.java @@ -10,13 +10,13 @@ public class ResourceSetSerializer extends JsonSerializer { - @Override - public void serialize(ResourceSet rs, JsonGenerator g, SerializerProvider p) throws IOException { - g.writeStartArray(); - var resources = rs.getResources(); - for (var r : resources) { - g.writeObject(r); - } - g.writeEndArray(); - } + @Override + public void serialize(ResourceSet resourceSet, JsonGenerator generator, SerializerProvider provider) throws IOException { + generator.writeStartArray(); + var resources = resourceSet.getResources(); + for (var r : resources) { + generator.writeObject(r); + } + generator.writeEndArray(); + } } diff --git a/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/common/serializer/VitruviusChangeSerializer.java b/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/common/serializer/VitruviusChangeSerializer.java index 7a74115038..a564f16b28 100644 --- a/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/common/serializer/VitruviusChangeSerializer.java +++ b/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/common/serializer/VitruviusChangeSerializer.java @@ -11,30 +11,30 @@ import tools.vitruv.change.composite.description.CompositeChange; import tools.vitruv.change.composite.description.TransactionalChange; import tools.vitruv.change.composite.description.VitruviusChange; +import tools.vitruv.framework.remote.common.util.SerializationConstants; import tools.vitruv.framework.remote.common.util.ChangeType; import tools.vitruv.framework.remote.common.util.ResourceUtils; public class VitruviusChangeSerializer extends JsonSerializer { - - @Override - public void serialize(VitruviusChange v, JsonGenerator g, SerializerProvider p) throws IOException { - g.writeStartObject(); - g.writeStringField("changeType", ChangeType.getChangeTypeOf(v).toString()); - if (v instanceof TransactionalChange tc) { - var changesResource = ResourceUtils.createResourceWith(URI.createURI("temp"), tc.getEChanges()); - g.writeFieldName("eChanges"); - g.writeObject(ResourceUtils.serialize(changesResource)); - } else if (v instanceof CompositeChange cc) { - var changes = cc.getChanges(); - g.writeArrayFieldStart("vChanges"); - for(var change : changes) { - g.writeObject(change); - } - g.writeEndArray(); - } - else { - throw new UnsupportedOperationException("Change serialization of type " + v.getClass().getName() + " not implemented!"); - } - g.writeEndObject(); - } + + @Override + public void serialize(VitruviusChange vitruviusChange, JsonGenerator generator, SerializerProvider provider) throws IOException { + generator.writeStartObject(); + generator.writeStringField(SerializationConstants.CHANGE_TYPE, ChangeType.getChangeTypeOf(vitruviusChange).toString()); + if (vitruviusChange instanceof TransactionalChange tc) { + var changesResource = ResourceUtils.createResourceWith(URI.createURI(SerializationConstants.TEMP), tc.getEChanges()); + generator.writeFieldName(SerializationConstants.E_CHANGES); + generator.writeObject(ResourceUtils.serialize(changesResource)); + } else if (vitruviusChange instanceof CompositeChange cc) { + var changes = cc.getChanges(); + generator.writeArrayFieldStart(SerializationConstants.V_CHANGES); + for (var change : changes) { + generator.writeObject(change); + } + generator.writeEndArray(); + } else { + throw new UnsupportedOperationException("Change serialization of type " + vitruviusChange.getClass().getName() + " not implemented!"); + } + generator.writeEndObject(); + } } diff --git a/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/common/util/ContentTypes.java b/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/common/util/ContentTypes.java index 490c3043e1..b40a7e3f94 100644 --- a/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/common/util/ContentTypes.java +++ b/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/common/util/ContentTypes.java @@ -7,5 +7,4 @@ public final class ContentTypes { private ContentTypes() throws InstantiationException { throw new InstantiationException("Cannot be instantiated"); } - } diff --git a/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/common/util/EndpointPaths.java b/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/common/util/EndpointPaths.java new file mode 100644 index 0000000000..7794d7d726 --- /dev/null +++ b/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/common/util/EndpointPaths.java @@ -0,0 +1,13 @@ +package tools.vitruv.framework.remote.common.util; + +public class EndpointPaths { + public static final String HEALTH = "/health"; + public static final String VIEW_TYPES = "/vsum/viewtypes"; + public static final String VIEW = "/vsum/view"; + public static final String IS_VIEW_CLOSED = "/vsum/view/closed"; + public static final String IS_VIEW_OUTDATED = "/vsum/view/outdated"; + + private EndpointPaths() throws InstantiationException { + throw new InstantiationException("Cannot be instantiated"); + } +} diff --git a/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/common/util/Headers.java b/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/common/util/Headers.java index c50eaad11b..66df1f434e 100644 --- a/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/common/util/Headers.java +++ b/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/common/util/Headers.java @@ -1,12 +1,11 @@ package tools.vitruv.framework.remote.common.util; public final class Headers { - public static final String CONTENT_TYPE = "Content-Type"; - public static final String VIEW_UUID = "View-UUID"; - public static final String VIEW_TYPE = "View-Type"; - - private Headers() throws InstantiationException { + public static final String CONTENT_TYPE = "Content-Type"; + public static final String VIEW_UUID = "View-UUID"; + public static final String VIEW_TYPE = "View-Type"; + + private Headers() throws InstantiationException { throw new InstantiationException("Cannot be instantiated"); } - } diff --git a/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/common/util/IdTransformation.java b/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/common/util/IdTransformation.java index bacb794ebb..32c92aa09b 100644 --- a/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/common/util/IdTransformation.java +++ b/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/common/util/IdTransformation.java @@ -60,20 +60,20 @@ private static String prepareId(String id) { */ public static void allToGlobal(List changes) { for (var eChange : changes) { - if (eChange instanceof EObjectExistenceEChange c) { - c.setAffectedEObjectID(toGlobal(c.getAffectedEObjectID())); + if (eChange instanceof EObjectExistenceEChange change) { + change.setAffectedEObjectID(toGlobal(change.getAffectedEObjectID())); } - if (eChange instanceof EObjectAddedEChange c) { - c.setNewValueID(toGlobal(c.getNewValueID())); + if (eChange instanceof EObjectAddedEChange change) { + change.setNewValueID(toGlobal(change.getNewValueID())); } - if (eChange instanceof EObjectSubtractedEChange c) { - c.setOldValueID(toGlobal(c.getOldValueID())); + if (eChange instanceof EObjectSubtractedEChange change) { + change.setOldValueID(toGlobal(change.getOldValueID())); } - if (eChange instanceof FeatureEChange c) { - c.setAffectedEObjectID(toGlobal(c.getAffectedEObjectID())); + if (eChange instanceof FeatureEChange change) { + change.setAffectedEObjectID(toGlobal(change.getAffectedEObjectID())); } - if (eChange instanceof RootEChange c) { - c.setUri(toGlobal(c.getUri())); + if (eChange instanceof RootEChange change) { + change.setUri(toGlobal(change.getUri())); } } } diff --git a/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/common/util/JsonMapper.java b/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/common/util/JsonMapper.java index d6ba87bff7..d1dd9ad109 100644 --- a/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/common/util/JsonMapper.java +++ b/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/common/util/JsonMapper.java @@ -49,47 +49,35 @@ private JsonMapper() throws InstantiationException { } /** - * Serialize the given object. + * Serializes the given object. * * @param obj the object to serialize * @return the json or {@code null}, if an {@link JsonProcessingException} occurred. */ - public static String serialize(Object obj) { - try { - return mapper.writeValueAsString(obj); - } catch (JsonProcessingException e) { - return null; - } + public static String serialize(Object obj) throws JsonProcessingException { + return mapper.writeValueAsString(obj); } /** - * Deserializes the given json. + * Deserializes the given json string. * * @param json the json to deserialize * @param clazz the class of the jsons type. * @return the object or {@code null}, if an {@link JsonProcessingException} occurred. */ - public static T deserialize(String json, Class clazz) { - try { - return mapper.readValue(json, clazz); - } catch (JsonProcessingException e) { - return null; - } + public static T deserialize(String json, Class clazz) throws JsonProcessingException { + return mapper.readValue(json, clazz); } /** - * Deserializes the given json array. + * Deserializes the given json array to a list. * * @param json the json array to deserialize - * @param clazz the class of the json type of the objects in the array + * @param clazz the class representing the json type of the objects in the json array * @return the list of objects or {@code null}, if an {@link JsonProcessingException} occurred. */ - public static List deserializeListOf(String json, Class clazz) { - try { + public static List deserializeArrayOf(String json, Class clazz) throws JsonProcessingException { var javaType = mapper.getTypeFactory().constructCollectionType(List.class, clazz); return mapper.readValue(json, javaType); - } catch (JsonProcessingException e) { - return null; - } } } diff --git a/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/common/util/ResourceUtils.java b/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/common/util/ResourceUtils.java index 0c99bfd53d..831cb809dd 100644 --- a/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/common/util/ResourceUtils.java +++ b/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/common/util/ResourceUtils.java @@ -16,6 +16,8 @@ import org.eclipse.emf.ecore.util.EcoreUtil; import org.eclipse.emf.ecore.xmi.XMLResource; +import static com.google.common.base.Preconditions.checkArgument; + /** * Contains utility functions to work with {@link Resource}s. */ @@ -40,20 +42,17 @@ public static String serialize(Resource resource) throws IOException { /** * Deserializes a {@link Resource}. * - * @param uri the uri of the resource - * @param res the string representation of the resource - * @param parentSet the parent {@link ResourceSet} of the resource + * @param uri the uri of the resource + * @param resourceString the string representation of the resource + * @param parentSet the parent {@link ResourceSet} of the resource * @return the deserialized {@link Resource}. */ - public static Resource deserialize(URI uri, String res, ResourceSet parentSet) throws IOException { - if (res == null) { - throw new IllegalArgumentException("The xmi string must not be null!"); - } - if (parentSet == null) { - throw new IllegalArgumentException("The resource set must not be null!"); - } + public static Resource deserialize(URI uri, String resourceString, ResourceSet parentSet) throws IOException { + checkArgument(resourceString != null, "xmi resource string must not be null"); + checkArgument(parentSet != null, "parent resource set must not be null"); + var resource = parentSet.createResource(uri); - var inputStream = new ByteArrayInputStream(res.getBytes(StandardCharsets.UTF_8)); + var inputStream = new ByteArrayInputStream(resourceString.getBytes(StandardCharsets.UTF_8)); resource.load(inputStream, Collections.EMPTY_MAP); return resource; } diff --git a/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/common/util/SerializationConstants.java b/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/common/util/SerializationConstants.java new file mode 100644 index 0000000000..35fad78aa8 --- /dev/null +++ b/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/common/util/SerializationConstants.java @@ -0,0 +1,14 @@ +package tools.vitruv.framework.remote.common.util; + +public class SerializationConstants { + public static final String CHANGE_TYPE = "changeType"; + public static final String E_CHANGES = "eChanges"; + public static final String V_CHANGES = "vChanges"; + public static final String TEMP = "temp"; + public static final String CONTENT = "content"; + public static final String URI = "uri"; + + private SerializationConstants() throws InstantiationException { + throw new InstantiationException("Cannot be instantiated"); + } +} diff --git a/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/server/ViewCache.java b/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/server/ViewCache.java index 2af3b2e867..df7562cbb1 100644 --- a/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/server/ViewCache.java +++ b/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/server/ViewCache.java @@ -15,7 +15,7 @@ private ViewCache() throws InstantiationException { private static final HashMap cache = new HashMap<>(); - public static void addView(String uuid, View view) { + public static void addView(String uuid, View view) { cache.put(uuid, view); } diff --git a/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/server/endpoint/DeleteEndpoint.java b/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/server/endpoint/DeleteEndpoint.java new file mode 100644 index 0000000000..f55a03a4d3 --- /dev/null +++ b/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/server/endpoint/DeleteEndpoint.java @@ -0,0 +1,22 @@ +package tools.vitruv.framework.remote.server.endpoint; + +import spark.Spark; + +/** + * Represents a DELETE endpoint. Provides a standard implementation for the init() method. + */ +public abstract class DeleteEndpoint extends Endpoint { + + public DeleteEndpoint(String path) { + super(path); + } + + public DeleteEndpoint(String path, String acceptType) { + super(path, acceptType); + } + + @Override + public void init() { + Spark.delete(path, acceptType, this::handleRequest); + } +} diff --git a/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/server/endpoint/Endpoint.java b/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/server/endpoint/Endpoint.java index 343ddcc09b..7707be4bb6 100644 --- a/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/server/endpoint/Endpoint.java +++ b/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/server/endpoint/Endpoint.java @@ -47,8 +47,8 @@ public Endpoint(String path) { * * @param msg A message containing the reason of halting the execution. */ - protected void notFound(String msg) { - throw new ServerHaltingException(404, msg); + protected ServerHaltingException notFound(String msg) { + return new ServerHaltingException(404, msg); } /** @@ -56,7 +56,7 @@ protected void notFound(String msg) { * * @param msg A message containing the reason of halting the execution. */ - protected void internalServerError(String msg) { - throw new ServerHaltingException(500, msg); + protected ServerHaltingException internalServerError(String msg) { + return new ServerHaltingException(500, msg); } } diff --git a/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/server/endpoint/PatchEndpoint.java b/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/server/endpoint/PatchEndpoint.java new file mode 100644 index 0000000000..9d62adf0b6 --- /dev/null +++ b/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/server/endpoint/PatchEndpoint.java @@ -0,0 +1,22 @@ +package tools.vitruv.framework.remote.server.endpoint; + +import spark.Spark; + +/** + * Represents a PATCH endpoint. Provides a standard implementation for the init() method. + */ +public abstract class PatchEndpoint extends Endpoint { + + public PatchEndpoint(String path) { + super(path); + } + + public PatchEndpoint(String path, String acceptType) { + super(path, acceptType); + } + + @Override + public void init() { + Spark.patch(path, acceptType, this::handleRequest); + } +} diff --git a/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/server/endpoint/impl/ChangePropagationEndpoint.java b/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/server/endpoint/impl/ChangePropagationEndpoint.java index 5a63520bfb..a5ab5c0a48 100644 --- a/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/server/endpoint/impl/ChangePropagationEndpoint.java +++ b/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/server/endpoint/impl/ChangePropagationEndpoint.java @@ -1,9 +1,11 @@ package tools.vitruv.framework.remote.server.endpoint.impl; +import com.fasterxml.jackson.core.JsonProcessingException; import spark.Request; import spark.Response; import tools.vitruv.change.composite.description.VitruviusChange; +import tools.vitruv.framework.remote.common.util.EndpointPaths; import tools.vitruv.framework.vsum.internal.InternalVirtualModel; import tools.vitruv.framework.remote.common.util.ContentTypes; import tools.vitruv.framework.remote.common.util.JsonMapper; @@ -13,18 +15,23 @@ * This endpoint applies given {@link VitruviusChange}s to the VSUM. */ public class ChangePropagationEndpoint extends PostEndpoint { - - InternalVirtualModel model; - public ChangePropagationEndpoint(InternalVirtualModel model) { - super("/vsum/change", ContentTypes.APPLICATION_JSON); - this.model = model; - } + InternalVirtualModel model; - @Override - public Void handleRequest(Request request, Response response) { - var change = JsonMapper.deserialize(request.body(), VitruviusChange.class); - model.propagateChange(change); - return null; - } + public ChangePropagationEndpoint(InternalVirtualModel model) { + super(EndpointPaths.VIEW, ContentTypes.APPLICATION_JSON); + this.model = model; + } + + @Override + public Void handleRequest(Request request, Response response) { + try { + var change = JsonMapper.deserialize(request.body(), VitruviusChange.class); + model.propagateChange(change); + } catch (JsonProcessingException e) { + throw internalServerError(e.getMessage()); + } + + return null; + } } diff --git a/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/server/endpoint/impl/CloseViewEndpoint.java b/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/server/endpoint/impl/CloseViewEndpoint.java index 418783a38c..00d898c3ee 100644 --- a/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/server/endpoint/impl/CloseViewEndpoint.java +++ b/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/server/endpoint/impl/CloseViewEndpoint.java @@ -2,29 +2,30 @@ import spark.Request; import spark.Response; +import tools.vitruv.framework.remote.common.util.EndpointPaths; import tools.vitruv.framework.remote.common.util.Headers; import tools.vitruv.framework.remote.server.ViewCache; -import tools.vitruv.framework.remote.server.endpoint.PostEndpoint; +import tools.vitruv.framework.remote.server.endpoint.DeleteEndpoint; /** * This endpoint closes a {@link tools.vitruv.framework.views.View View}. */ -public class CloseViewEndpoint extends PostEndpoint { +public class CloseViewEndpoint extends DeleteEndpoint { public CloseViewEndpoint() { - super("/vsum/view/closed"); + super(EndpointPaths.VIEW); } @Override public Void handleRequest(Request request, Response response) { var view = ViewCache.removeView(request.headers(Headers.VIEW_UUID)); if (view == null) { - notFound("View with given id not found!"); + throw notFound("View with given id not found!"); } try { view.close(); } catch (Exception e) { - internalServerError(e.getMessage()); + throw internalServerError(e.getMessage()); } return null; } diff --git a/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/server/endpoint/impl/HealthEndpoint.java b/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/server/endpoint/impl/HealthEndpoint.java index 1f44ae08a7..e8dea7b5f9 100644 --- a/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/server/endpoint/impl/HealthEndpoint.java +++ b/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/server/endpoint/impl/HealthEndpoint.java @@ -2,6 +2,7 @@ import spark.Request; import spark.Response; +import tools.vitruv.framework.remote.common.util.EndpointPaths; import tools.vitruv.framework.remote.server.endpoint.GetEndpoint; /** @@ -9,12 +10,12 @@ */ public class HealthEndpoint extends GetEndpoint { - public HealthEndpoint() { - super("/health"); - } + public HealthEndpoint() { + super(EndpointPaths.HEALTH); + } - @Override - public Object handleRequest(Request request, Response response) { - return "Vitruv Server is up and running!"; - } + @Override + public Object handleRequest(Request request, Response response) { + return "Vitruv Server is up and running!"; + } } diff --git a/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/server/endpoint/impl/IsViewClosedEndpoint.java b/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/server/endpoint/impl/IsViewClosedEndpoint.java index 384b0b415a..7c9c938643 100644 --- a/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/server/endpoint/impl/IsViewClosedEndpoint.java +++ b/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/server/endpoint/impl/IsViewClosedEndpoint.java @@ -3,6 +3,7 @@ import spark.Request; import spark.Response; import tools.vitruv.framework.remote.common.util.ContentTypes; +import tools.vitruv.framework.remote.common.util.EndpointPaths; import tools.vitruv.framework.remote.common.util.Headers; import tools.vitruv.framework.remote.server.ViewCache; import tools.vitruv.framework.remote.server.endpoint.GetEndpoint; @@ -13,7 +14,7 @@ public class IsViewClosedEndpoint extends GetEndpoint { public IsViewClosedEndpoint() { - super("/vsum/view/closed"); + super(EndpointPaths.IS_VIEW_CLOSED); } @Override diff --git a/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/server/endpoint/impl/IsViewOutdatedEndpoint.java b/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/server/endpoint/impl/IsViewOutdatedEndpoint.java index 6e52412fac..14ff92a280 100644 --- a/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/server/endpoint/impl/IsViewOutdatedEndpoint.java +++ b/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/server/endpoint/impl/IsViewOutdatedEndpoint.java @@ -3,6 +3,7 @@ import spark.Request; import spark.Response; import tools.vitruv.framework.remote.common.util.ContentTypes; +import tools.vitruv.framework.remote.common.util.EndpointPaths; import tools.vitruv.framework.remote.common.util.Headers; import tools.vitruv.framework.remote.server.ViewCache; import tools.vitruv.framework.remote.server.endpoint.GetEndpoint; @@ -13,14 +14,14 @@ public class IsViewOutdatedEndpoint extends GetEndpoint { public IsViewOutdatedEndpoint() { - super("/vsum/view/outdated"); + super(EndpointPaths.IS_VIEW_OUTDATED); } @Override public String handleRequest(Request request, Response response) { var view = ViewCache.getView(request.headers(Headers.VIEW_UUID)); if (view == null) { - notFound("View with given id not found!"); + throw notFound("View with given id not found!"); } response.type(ContentTypes.TEXT_PLAIN); return view.isOutdated() ? Boolean.TRUE.toString() : Boolean.FALSE.toString(); diff --git a/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/server/endpoint/impl/UpdateViewEndpoint.java b/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/server/endpoint/impl/UpdateViewEndpoint.java index ccadd50129..3a9070468d 100644 --- a/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/server/endpoint/impl/UpdateViewEndpoint.java +++ b/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/server/endpoint/impl/UpdateViewEndpoint.java @@ -1,30 +1,32 @@ package tools.vitruv.framework.remote.server.endpoint.impl; +import com.fasterxml.jackson.core.JsonProcessingException; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl; import spark.Request; import spark.Response; import tools.vitruv.framework.remote.common.util.ContentTypes; +import tools.vitruv.framework.remote.common.util.EndpointPaths; import tools.vitruv.framework.remote.common.util.Headers; import tools.vitruv.framework.remote.common.util.JsonMapper; import tools.vitruv.framework.remote.server.ViewCache; -import tools.vitruv.framework.remote.server.endpoint.GetEndpoint; +import tools.vitruv.framework.remote.server.endpoint.PatchEndpoint; /** * This endpoint updates a {@link tools.vitruv.framework.views.View View} and returns the * updated {@link org.eclipse.emf.ecore.resource.Resource Resources}. */ -public class UpdateViewEndpoint extends GetEndpoint { +public class UpdateViewEndpoint extends PatchEndpoint { public UpdateViewEndpoint() { - super("/vsum/view/update"); + super(EndpointPaths.VIEW); } @Override public Object handleRequest(Request request, Response response) { var view = ViewCache.getView(request.headers(Headers.VIEW_UUID)); if (view == null) { - notFound("View with given id not found!"); + throw notFound("View with given id not found!"); } view.update(); @@ -35,6 +37,11 @@ public Object handleRequest(Request request, Response response) { rSet.getResources().addAll(resources); response.type(ContentTypes.APPLICATION_JSON); - return JsonMapper.serialize(rSet); + + try { + return JsonMapper.serialize(rSet); + } catch (JsonProcessingException e) { + throw internalServerError(e.getMessage()); + } } } diff --git a/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/server/endpoint/impl/ViewEndpoint.java b/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/server/endpoint/impl/ViewEndpoint.java index d6918cb782..74e0351bd5 100644 --- a/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/server/endpoint/impl/ViewEndpoint.java +++ b/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/server/endpoint/impl/ViewEndpoint.java @@ -2,16 +2,14 @@ import java.util.UUID; +import com.fasterxml.jackson.core.JsonProcessingException; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl; import spark.Request; import spark.Response; +import tools.vitruv.framework.remote.common.util.*; import tools.vitruv.framework.vsum.internal.InternalVirtualModel; -import tools.vitruv.framework.remote.common.util.ContentTypes; -import tools.vitruv.framework.remote.common.util.Headers; -import tools.vitruv.framework.remote.common.util.JsonMapper; -import tools.vitruv.framework.remote.common.util.ResourceUtils; import tools.vitruv.framework.remote.server.ViewCache; import tools.vitruv.framework.remote.server.endpoint.GetEndpoint; @@ -24,7 +22,7 @@ public class ViewEndpoint extends GetEndpoint { private final InternalVirtualModel model; public ViewEndpoint(InternalVirtualModel model) { - super("/vsum/view"); + super(EndpointPaths.VIEW); this.model = model; } @@ -35,7 +33,7 @@ public String handleRequest(Request request, Response response) { //Check if view type exists if (types.stream().noneMatch(it -> it.getName().equals(viewTypeName))) { - notFound("View Type with name " + viewTypeName + " not found!"); + throw notFound("View Type with name " + viewTypeName + " not found!"); } //Get selector and select every element @@ -54,6 +52,10 @@ public String handleRequest(Request request, Response response) { response.type(ContentTypes.APPLICATION_JSON); response.header(Headers.VIEW_UUID, uuid); - return JsonMapper.serialize(rSet); + try { + return JsonMapper.serialize(rSet); + } catch (JsonProcessingException e) { + throw internalServerError(e.getMessage()); + } } } diff --git a/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/server/endpoint/impl/ViewTypesEndpoint.java b/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/server/endpoint/impl/ViewTypesEndpoint.java index 25fb0b8667..6e8db787f9 100644 --- a/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/server/endpoint/impl/ViewTypesEndpoint.java +++ b/bundles/tools.vitruv.framework.remote/src/tools/vitruv/framework/remote/server/endpoint/impl/ViewTypesEndpoint.java @@ -3,8 +3,10 @@ import java.util.Collection; import java.util.List; +import com.fasterxml.jackson.core.JsonProcessingException; import spark.Request; import spark.Response; +import tools.vitruv.framework.remote.common.util.EndpointPaths; import tools.vitruv.framework.views.ViewType; import tools.vitruv.framework.vsum.internal.InternalVirtualModel; import tools.vitruv.framework.remote.common.util.JsonMapper; @@ -14,20 +16,24 @@ * This endpoint returns a list of names of all registered {@link ViewType}s in the VSUM. */ public class ViewTypesEndpoint extends GetEndpoint { - - private final InternalVirtualModel model; - public ViewTypesEndpoint(InternalVirtualModel model) { - super("/vsum/viewtypes"); - this.model = model; - } + private final InternalVirtualModel model; - @Override - public String handleRequest(Request request, Response response) { - Collection> types = model.getViewTypes(); - List names = types.stream().map(ViewType::getName).toList(); - - response.type("application/json"); - return JsonMapper.serialize(names); - } + public ViewTypesEndpoint(InternalVirtualModel model) { + super(EndpointPaths.VIEW_TYPES); + this.model = model; + } + + @Override + public String handleRequest(Request request, Response response) { + Collection> types = model.getViewTypes(); + List names = types.stream().map(ViewType::getName).toList(); + + response.type("application/json"); + try { + return JsonMapper.serialize(names); + } catch (JsonProcessingException e) { + throw internalServerError(e.getMessage()); + } + } } diff --git a/bundles/tools.vitruv.framework.vsum/src/tools/vitruv/framework/vsum/VirtualModelBuilder.xtend b/bundles/tools.vitruv.framework.vsum/src/tools/vitruv/framework/vsum/VirtualModelBuilder.xtend index 88aad23275..3b16eb0373 100644 --- a/bundles/tools.vitruv.framework.vsum/src/tools/vitruv/framework/vsum/VirtualModelBuilder.xtend +++ b/bundles/tools.vitruv.framework.vsum/src/tools/vitruv/framework/vsum/VirtualModelBuilder.xtend @@ -15,6 +15,7 @@ import tools.vitruv.framework.views.ViewTypeRepository import tools.vitruv.framework.vsum.helper.VsumFileSystemLayout import tools.vitruv.framework.vsum.internal.InternalVirtualModel import tools.vitruv.framework.vsum.internal.VirtualModelImpl +import tools.vitruv.change.propagation.ProjectMarker import static com.google.common.base.Preconditions.checkState @@ -96,6 +97,11 @@ class VirtualModelBuilder { fileSystemLayout.prepare() val vsum = new VirtualModelImpl(fileSystemLayout, userInteractor, viewTypeRepository, changeSpecificationRepository) vsum.loadExistingModels() + try { + ProjectMarker.getProjectRootFolder(storageFolder) + } catch (IllegalStateException exception) { + ProjectMarker.markAsProjectRootFolder(storageFolder) + } return vsum } } \ No newline at end of file diff --git a/mvnw b/mvnw index b7f064624f..8d937f4c14 100755 --- a/mvnw +++ b/mvnw @@ -19,7 +19,7 @@ # ---------------------------------------------------------------------------- # ---------------------------------------------------------------------------- -# Apache Maven Wrapper startup batch script, version 3.1.1 +# Apache Maven Wrapper startup batch script, version 3.2.0 # # Required ENV vars: # ------------------ @@ -53,7 +53,7 @@ fi cygwin=false; darwin=false; mingw=false -case "`uname`" in +case "$(uname)" in CYGWIN*) cygwin=true ;; MINGW*) mingw=true;; Darwin*) darwin=true @@ -61,7 +61,7 @@ case "`uname`" in # See https://developer.apple.com/library/mac/qa/qa1170/_index.html if [ -z "$JAVA_HOME" ]; then if [ -x "/usr/libexec/java_home" ]; then - JAVA_HOME="`/usr/libexec/java_home`"; export JAVA_HOME + JAVA_HOME="$(/usr/libexec/java_home)"; export JAVA_HOME else JAVA_HOME="/Library/Java/Home"; export JAVA_HOME fi @@ -71,38 +71,38 @@ esac if [ -z "$JAVA_HOME" ] ; then if [ -r /etc/gentoo-release ] ; then - JAVA_HOME=`java-config --jre-home` + JAVA_HOME=$(java-config --jre-home) fi fi # For Cygwin, ensure paths are in UNIX format before anything is touched if $cygwin ; then [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --unix "$JAVA_HOME"` + JAVA_HOME=$(cygpath --unix "$JAVA_HOME") [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --unix "$CLASSPATH"` + CLASSPATH=$(cygpath --path --unix "$CLASSPATH") fi # For Mingw, ensure paths are in UNIX format before anything is touched if $mingw ; then - [ -n "$JAVA_HOME" ] && - JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" + [ -n "$JAVA_HOME" ] && [ -d "$JAVA_HOME" ] && + JAVA_HOME="$(cd "$JAVA_HOME" || (echo "cannot cd into $JAVA_HOME."; exit 1); pwd)" fi if [ -z "$JAVA_HOME" ]; then - javaExecutable="`which javac`" - if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then + javaExecutable="$(which javac)" + if [ -n "$javaExecutable" ] && ! [ "$(expr "\"$javaExecutable\"" : '\([^ ]*\)')" = "no" ]; then # readlink(1) is not available as standard on Solaris 10. - readLink=`which readlink` - if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then + readLink=$(which readlink) + if [ ! "$(expr "$readLink" : '\([^ ]*\)')" = "no" ]; then if $darwin ; then - javaHome="`dirname \"$javaExecutable\"`" - javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" + javaHome="$(dirname "\"$javaExecutable\"")" + javaExecutable="$(cd "\"$javaHome\"" && pwd -P)/javac" else - javaExecutable="`readlink -f \"$javaExecutable\"`" + javaExecutable="$(readlink -f "\"$javaExecutable\"")" fi - javaHome="`dirname \"$javaExecutable\"`" - javaHome=`expr "$javaHome" : '\(.*\)/bin'` + javaHome="$(dirname "\"$javaExecutable\"")" + javaHome=$(expr "$javaHome" : '\(.*\)/bin') JAVA_HOME="$javaHome" export JAVA_HOME fi @@ -118,7 +118,7 @@ if [ -z "$JAVACMD" ] ; then JAVACMD="$JAVA_HOME/bin/java" fi else - JAVACMD="`\\unset -f command; \\command -v java`" + JAVACMD="$(\unset -f command 2>/dev/null; \command -v java)" fi fi @@ -150,108 +150,99 @@ find_maven_basedir() { fi # workaround for JBEAP-8937 (on Solaris 10/Sparc) if [ -d "${wdir}" ]; then - wdir=`cd "$wdir/.."; pwd` + wdir=$(cd "$wdir/.." || exit 1; pwd) fi # end of workaround done - printf '%s' "$(cd "$basedir"; pwd)" + printf '%s' "$(cd "$basedir" || exit 1; pwd)" } # concatenates all lines of a file concat_lines() { if [ -f "$1" ]; then - echo "$(tr -s '\n' ' ' < "$1")" + # Remove \r in case we run on Windows within Git Bash + # and check out the repository with auto CRLF management + # enabled. Otherwise, we may read lines that are delimited with + # \r\n and produce $'-Xarg\r' rather than -Xarg due to word + # splitting rules. + tr -s '\r\n' ' ' < "$1" fi } -BASE_DIR=$(find_maven_basedir "$(dirname $0)") +log() { + if [ "$MVNW_VERBOSE" = true ]; then + printf '%s\n' "$1" + fi +} + +BASE_DIR=$(find_maven_basedir "$(dirname "$0")") if [ -z "$BASE_DIR" ]; then exit 1; fi MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}; export MAVEN_PROJECTBASEDIR -if [ "$MVNW_VERBOSE" = true ]; then - echo $MAVEN_PROJECTBASEDIR -fi +log "$MAVEN_PROJECTBASEDIR" ########################################################################################## # Extension to allow automatically downloading the maven-wrapper.jar from Maven-central # This allows using the maven wrapper in projects that prohibit checking in binary data. ########################################################################################## -if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found .mvn/wrapper/maven-wrapper.jar" - fi +wrapperJarPath="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" +if [ -r "$wrapperJarPath" ]; then + log "Found $wrapperJarPath" else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." - fi + log "Couldn't find $wrapperJarPath, downloading it ..." + if [ -n "$MVNW_REPOURL" ]; then - wrapperUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar" + wrapperUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" else - wrapperUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar" + wrapperUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" fi - while IFS="=" read key value; do - case "$key" in (wrapperUrl) wrapperUrl="$value"; break ;; + while IFS="=" read -r key value; do + # Remove '\r' from value to allow usage on windows as IFS does not consider '\r' as a separator ( considers space, tab, new line ('\n'), and custom '=' ) + safeValue=$(echo "$value" | tr -d '\r') + case "$key" in (wrapperUrl) wrapperUrl="$safeValue"; break ;; esac - done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" - if [ "$MVNW_VERBOSE" = true ]; then - echo "Downloading from: $wrapperUrl" - fi - wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" + done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties" + log "Downloading from: $wrapperUrl" + if $cygwin; then - wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` + wrapperJarPath=$(cygpath --path --windows "$wrapperJarPath") fi if command -v wget > /dev/null; then - QUIET="--quiet" - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found wget ... using wget" - QUIET="" - fi + log "Found wget ... using wget" + [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--quiet" if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then - wget $QUIET "$wrapperUrl" -O "$wrapperJarPath" + wget $QUIET "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" else - wget $QUIET --http-user="$MVNW_USERNAME" --http-password="$MVNW_PASSWORD" "$wrapperUrl" -O "$wrapperJarPath" + wget $QUIET --http-user="$MVNW_USERNAME" --http-password="$MVNW_PASSWORD" "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" fi - [ $? -eq 0 ] || rm -f "$wrapperJarPath" elif command -v curl > /dev/null; then - QUIET="--silent" - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found curl ... using curl" - QUIET="" - fi + log "Found curl ... using curl" + [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--silent" if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then - curl $QUIET -o "$wrapperJarPath" "$wrapperUrl" -f -L + curl $QUIET -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath" else - curl $QUIET --user "$MVNW_USERNAME:$MVNW_PASSWORD" -o "$wrapperJarPath" "$wrapperUrl" -f -L + curl $QUIET --user "$MVNW_USERNAME:$MVNW_PASSWORD" -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath" fi - [ $? -eq 0 ] || rm -f "$wrapperJarPath" else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Falling back to using Java to download" - fi - javaSource="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" - javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" + log "Falling back to using Java to download" + javaSource="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.java" + javaClass="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.class" # For Cygwin, switch paths to Windows format before running javac if $cygwin; then - javaSource=`cygpath --path --windows "$javaSource"` - javaClass=`cygpath --path --windows "$javaClass"` + javaSource=$(cygpath --path --windows "$javaSource") + javaClass=$(cygpath --path --windows "$javaClass") fi if [ -e "$javaSource" ]; then if [ ! -e "$javaClass" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Compiling MavenWrapperDownloader.java ..." - fi - # Compiling the Java class + log " - Compiling MavenWrapperDownloader.java ..." ("$JAVA_HOME/bin/javac" "$javaSource") fi if [ -e "$javaClass" ]; then - # Running the downloader - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Running MavenWrapperDownloader.java ..." - fi - ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") + log " - Running MavenWrapperDownloader.java ..." + ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$wrapperUrl" "$wrapperJarPath") || rm -f "$wrapperJarPath" fi fi fi @@ -260,25 +251,55 @@ fi # End of extension ########################################################################################## +# If specified, validate the SHA-256 sum of the Maven wrapper jar file +wrapperSha256Sum="" +while IFS="=" read -r key value; do + case "$key" in (wrapperSha256Sum) wrapperSha256Sum=$value; break ;; + esac +done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties" +if [ -n "$wrapperSha256Sum" ]; then + wrapperSha256Result=false + if command -v sha256sum > /dev/null; then + if echo "$wrapperSha256Sum $wrapperJarPath" | sha256sum -c > /dev/null 2>&1; then + wrapperSha256Result=true + fi + elif command -v shasum > /dev/null; then + if echo "$wrapperSha256Sum $wrapperJarPath" | shasum -a 256 -c > /dev/null 2>&1; then + wrapperSha256Result=true + fi + else + echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." + echo "Please install either command, or disable validation by removing 'wrapperSha256Sum' from your maven-wrapper.properties." + exit 1 + fi + if [ $wrapperSha256Result = false ]; then + echo "Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised." >&2 + echo "Investigate or delete $wrapperJarPath to attempt a clean download." >&2 + echo "If you updated your Maven version, you need to update the specified wrapperSha256Sum property." >&2 + exit 1 + fi +fi + MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" # For Cygwin, switch paths to Windows format before running java if $cygwin; then [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` + JAVA_HOME=$(cygpath --path --windows "$JAVA_HOME") [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --windows "$CLASSPATH"` + CLASSPATH=$(cygpath --path --windows "$CLASSPATH") [ -n "$MAVEN_PROJECTBASEDIR" ] && - MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` + MAVEN_PROJECTBASEDIR=$(cygpath --path --windows "$MAVEN_PROJECTBASEDIR") fi # Provide a "standardized" way to retrieve the CLI args that will # work with both Windows and non-Windows executions. -MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" +MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $*" export MAVEN_CMD_LINE_ARGS WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain +# shellcheck disable=SC2086 # safe args exec "$JAVACMD" \ $MAVEN_OPTS \ $MAVEN_DEBUG_OPTS \ diff --git a/mvnw.cmd b/mvnw.cmd index 474c9d6b74..c4586b564e 100644 --- a/mvnw.cmd +++ b/mvnw.cmd @@ -18,7 +18,7 @@ @REM ---------------------------------------------------------------------------- @REM ---------------------------------------------------------------------------- -@REM Apache Maven Wrapper startup batch script, version 3.1.1 +@REM Apache Maven Wrapper startup batch script, version 3.2.0 @REM @REM Required ENV vars: @REM JAVA_HOME - location of a JDK home dir @@ -119,7 +119,7 @@ SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain -set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar" +set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( IF "%%A"=="wrapperUrl" SET WRAPPER_URL=%%B @@ -133,7 +133,7 @@ if exist %WRAPPER_JAR% ( ) ) else ( if not "%MVNW_REPOURL%" == "" ( - SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar" + SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" ) if "%MVNW_VERBOSE%" == "true" ( echo Couldn't find %WRAPPER_JAR%, downloading it ... @@ -153,6 +153,24 @@ if exist %WRAPPER_JAR% ( ) @REM End of extension +@REM If specified, validate the SHA-256 sum of the Maven wrapper jar file +SET WRAPPER_SHA_256_SUM="" +FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( + IF "%%A"=="wrapperSha256Sum" SET WRAPPER_SHA_256_SUM=%%B +) +IF NOT %WRAPPER_SHA_256_SUM%=="" ( + powershell -Command "&{"^ + "$hash = (Get-FileHash \"%WRAPPER_JAR%\" -Algorithm SHA256).Hash.ToLower();"^ + "If('%WRAPPER_SHA_256_SUM%' -ne $hash){"^ + " Write-Output 'Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised.';"^ + " Write-Output 'Investigate or delete %WRAPPER_JAR% to attempt a clean download.';"^ + " Write-Output 'If you updated your Maven version, you need to update the specified wrapperSha256Sum property.';"^ + " exit 1;"^ + "}"^ + "}" + if ERRORLEVEL 1 goto error +) + @REM Provide a "standardized" way to retrieve the CLI args that will @REM work with both Windows and non-Windows executions. set MAVEN_CMD_LINE_ARGS=%* diff --git a/pom.xml b/pom.xml index d6396948b2..b2201661f1 100644 --- a/pom.xml +++ b/pom.xml @@ -20,6 +20,12 @@ + + + com.sparkjava + spark-core + 2.9.4 + com.fasterxml.jackson.core @@ -38,24 +44,11 @@ jackson-core 2.14.2 - - - ch.qos.logback - logback-classic - 1.4.6 - test - - - - ch.qos.logback - logback-core - 1.4.6 - - - - org.slf4j - slf4j-api - 2.0.7 + + + org.slf4j + slf4j-log4j12 + 1.7.25 @@ -82,5 +75,4 @@ - diff --git a/releng/tools.vitruv.parent/pom.xml b/releng/tools.vitruv.parent/pom.xml index 2260e6cf89..a9116a6225 100644 --- a/releng/tools.vitruv.parent/pom.xml +++ b/releng/tools.vitruv.parent/pom.xml @@ -6,7 +6,7 @@ tools.vitruv parent - 2.1.1 + 2.1.3 framework-parent 3.0.1-SNAPSHOT