Commit 61a3b966 authored by Daniel Bluhm's avatar Daniel Bluhm

Merge branch 'next' into dataelement-imports

parents c997180b 0f5a65d0
/target/
/bin/
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" output="target/classes" path="src/main/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="target/classes"/>
</classpath>
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>org.eclipse.ice.build</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.m2e.core.maven2Nature</nature>
</natures>
</projectDescription>
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.eclipse.ice</groupId>
<artifactId>org.eclipse.ice.parent</artifactId>
<version>2.2.1-SNAPSHOT</version>
<relativePath>../org.eclipse.ice.parent/pom.xml</relativePath>
</parent>
<groupId>org.eclipse.ice</groupId>
<artifactId>org.eclipse.ice.build</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<name>org.eclipse.ice.build</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<modules>
<module>../org.eclipse.ice.parent</module>
<module>../org.eclipse.ice.dev</module>
<module>../org.eclipse.ice.archetypes</module>
<module>../org.eclipse.ice.commands</module>
</modules>
</project>
......@@ -102,6 +102,11 @@
<version>3.0.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.cosium.logging</groupId>
<artifactId>annotation-processor-logger</artifactId>
<version>1.0</version>
</dependency>
</dependencies>
<parent>
......
......@@ -10,7 +10,6 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.Messager;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.Processor;
......@@ -28,6 +27,7 @@ import javax.tools.StandardLocation;
import org.eclipse.ice.dev.annotations.DataElement;
import org.eclipse.ice.dev.annotations.Persisted;
import com.cosium.logging.annotation_processor.AbstractLoggingProcessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.auto.service.AutoService;
......@@ -46,7 +46,7 @@ import com.google.auto.service.AutoService;
})
@SupportedSourceVersion(SourceVersion.RELEASE_11)
@AutoService(Processor.class)
public class DataElementProcessor extends AbstractProcessor {
public class DataElementProcessor extends AbstractLoggingProcessor {
/**
* Return stack trace as string.
* @param e subject exception
......@@ -73,7 +73,7 @@ public class DataElementProcessor extends AbstractProcessor {
}
@Override
public boolean process(final Set<? extends TypeElement> annotations, final RoundEnvironment roundEnv) {
public boolean doProcess(final Set<? extends TypeElement> annotations, final RoundEnvironment roundEnv) {
// Iterate over all elements with DataElement Annotation
for (final Element elem : roundEnv.getElementsAnnotatedWith(DataElement.class)) {
try {
......
......@@ -11,62 +11,55 @@
package org.eclipse.ice.dev.annotations.processors;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Properties used to initialize Velocity.
*/
enum VelocityProperties {
// Set up Velocity using the Singleton approach; ClasspathResourceLoader allows
// us to load templates from src/main/resources
LIBRARY_PATH("velocimacro.library.path", "templates/common.vm"),
RESOURCE_LOADER("resource.loader", "class"),
CLASS_RESOURCE_LOADER(
"class.resource.loader.class",
"org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader"
);
class VelocityProperties extends Properties {
/**
* Property key.
* Serial Version ID.
*/
private String key;
private static final long serialVersionUID = 1L;
/**
* Property value.
* Logger.
*/
private String value;
VelocityProperties(String key, String value) {
this.key = key;
this.value = value;
}
private static final Logger logger = LoggerFactory.getLogger(VelocityProperties.class);
/**
* Get key from enum.
* @return key
* Velocity property filename.
*/
String key() {
return this.key;
}
private static final String FILENAME = "velocity.properties";
private static VelocityProperties instance = null;
/**
* Get value from enum.
* @return value
* Construct VelocityProperties, loading from resource file.
*/
String value() {
return this.value;
private VelocityProperties() {
String propertyFile = getClass().getClassLoader().getResource(FILENAME).getPath();
try (InputStream propertyStream = new FileInputStream(propertyFile)) {
super.load(propertyStream);
} catch (FileNotFoundException e) {
logger.error("velocity.properties could not be found");
} catch (IOException e) {
logger.error("velocity.properties could not be read");
}
}
/**
* Generate and return Properties from enum.
* @return Properties
*/
public static Properties get() {
Properties p = new Properties();
for (VelocityProperties vp : VelocityProperties.values()) {
p.setProperty(vp.key(), vp.value());
public static VelocityProperties get() {
if (instance == null) {
instance = new VelocityProperties();
}
return p;
return instance;
}
}
\ No newline at end of file
}
resource.loaders=class
resource.loader.class.class=org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader
velocimacro.library.path=templates/common.vm
\ No newline at end of file
......@@ -13,8 +13,10 @@ package org.eclipse.ice.tests.dev.annotations.processors;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Locale;
import javax.annotation.processing.Processor;
import javax.tools.Diagnostic;
import javax.tools.JavaFileObject;
import org.eclipse.ice.dev.annotations.processors.DataElementProcessor;
......@@ -22,6 +24,7 @@ import org.eclipse.ice.dev.annotations.processors.DataElementProcessor;
import com.google.testing.compile.Compilation;
import static com.google.testing.compile.Compiler.*;
import static com.google.testing.compile.CompilationSubject.*;
/**
* Helper class for testing DataElement related annotations.
......@@ -29,6 +32,15 @@ import static com.google.testing.compile.Compiler.*;
*/
public class DataElementAnnotationTestHelper {
private boolean showDiagnostics = false;
public DataElementAnnotationTestHelper() {
String show = System.getenv("SHOW_DIAGNOSTICS");
if (show != null && show.equals("true")) {
this.showDiagnostics = true;
}
}
/**
* Retrieve an instance of Lombok's Annotation Processor.
*
......@@ -55,16 +67,32 @@ public class DataElementAnnotationTestHelper {
return p;
}
private void printDiagnostics(Compilation compilation) {
for (Diagnostic<? extends JavaFileObject> diag :
compilation.diagnostics()
) {
System.err.println(String.format(
"[%s]: %s",
diag.getKind().toString(),
diag.getMessage(Locale.ENGLISH)
));
}
}
/**
* Compile the sources with needed processors.
* @param sources to compile
* @return Compilation result
*/
public Compilation compile(JavaFileObject... sources) {
return javac()
Compilation compilation = javac()
.withProcessors(
getLombokAnnotationProcessor(),
new DataElementProcessor()
).compile(sources);
if (showDiagnostics) {
printDiagnostics(compilation);
}
return compilation;
}
}
......@@ -224,6 +224,7 @@ class DataElementProcessorTest {
@Test
void testNoDataFieldsSucceeds() {
Compilation compilation = helper.compile(Inputs.NO_DATAFIELDS.get());
assertThat(compilation).succeededWithoutWarnings();
assertDefaultsPresent(compilation);
}
......@@ -233,6 +234,7 @@ class DataElementProcessorTest {
@Test
void testWithSingleDataFieldSucceeds() {
Compilation compilation = helper.compile(Inputs.SINGLE.get());
assertThat(compilation).succeededWithoutWarnings();
assertDefaultsPresent(compilation);
assertInterfaceMatches(compilation, Patterns.SINGLE_INT.get());
assertImplementationMatches(compilation, Patterns.SINGLE_IMPL.get());
......@@ -244,6 +246,7 @@ class DataElementProcessorTest {
@Test
void testWithManyDataFieldsSucceeds() {
Compilation compilation = helper.compile(Inputs.MANY.get());
assertThat(compilation).succeededWithoutWarnings();
assertDefaultsPresent(compilation);
assertInterfaceMatches(compilation, Patterns.MANY_INT.get());
assertImplementationMatches(compilation, Patterns.MANY_IMPL.get());
......@@ -255,6 +258,7 @@ class DataElementProcessorTest {
@Test
void testSingleNonPrimitiveDataFieldSucceeds() {
Compilation compilation = helper.compile(Inputs.SINGLE_NON_PRIMITIVE.get());
assertThat(compilation).succeededWithoutWarnings();
assertDefaultsPresent(compilation);
assertInterfaceMatches(compilation, Patterns.SINGLE_NON_PRIMITIVE_INT.get());
assertImplementationMatches(compilation, Patterns.SINGLE_NON_PRIMITIVE_IMPL.get());
......@@ -266,6 +270,7 @@ class DataElementProcessorTest {
@Test
void testManyNonPrimitiveDataFieldSucceeds() {
Compilation compilation = helper.compile(Inputs.MANY_NON_PRIMITIVE.get());
assertThat(compilation).succeededWithoutWarnings();
assertDefaultsPresent(compilation);
assertInterfaceMatches(compilation, Patterns.MANY_NON_PRIMITIVE_INT.get());
assertImplementationMatches(compilation, Patterns.MANY_NON_PRIMITIVE_IMPL.get());
......@@ -298,6 +303,7 @@ class DataElementProcessorTest {
@Test
void testDocStringsPreserved() {
Compilation compilation = helper.compile(Inputs.SINGLE.get());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation).generatedSourceFile(IMPLEMENTATION)
.contentsAsUtf8String()
.contains("* A UNIQUE STRING IN THE DOC STRING.");
......@@ -313,6 +319,7 @@ class DataElementProcessorTest {
@Test
void testAccessibilityPreserved() {
Compilation compilation = helper.compile(Inputs.ACCESSIBILITY_PRESERVED.get());
assertThat(compilation).succeededWithoutWarnings();
assertImplementationMatches(compilation, Patterns.ACCESSIBILITY_PRESERVED.get());
}
......@@ -345,6 +352,7 @@ class DataElementProcessorTest {
@Test
void testDataFieldGetterOption() {
Compilation compilation = helper.compile(Inputs.DATAFIELD_GETTER.get());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile(INTERFACE)
.hasSourceEquivalentTo(Patterns.DATAFIELD_GETTER_INT.get());
......@@ -356,6 +364,7 @@ class DataElementProcessorTest {
@Test
void testDataFieldSetterOption() {
Compilation compilation = helper.compile(Inputs.DATAFIELD_SETTER.get());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile(INTERFACE)
.hasSourceEquivalentTo(Patterns.DATAFIELD_SETTER_INT.get());
......@@ -367,6 +376,7 @@ class DataElementProcessorTest {
@Test
void testDataFieldMatchOption() {
Compilation compilation = helper.compile(Inputs.DATAFIELD_MATCH.get());
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedSourceFile(IMPLEMENTATION)
.contentsAsUtf8String()
......@@ -383,6 +393,7 @@ class DataElementProcessorTest {
@Test
void testDataFieldDefaultNonString() {
Compilation compilation = helper.compile(Inputs.DEFAULT_NON_STRING.get());
assertThat(compilation).succeededWithoutWarnings();
assertImplementationMatches(
compilation,
Patterns.DEFAULT_NON_STRING_IMPL.get()
......@@ -395,6 +406,7 @@ class DataElementProcessorTest {
@Test
void testDataFieldDefaultString() {
Compilation compilation = helper.compile(Inputs.DEFAULT_STRING.get());
assertThat(compilation).succeededWithoutWarnings();
assertImplementationMatches(
compilation,
Patterns.DEFAULT_STRING_IMPL.get()
......
### Dependencies
All dependencies are noted in the `pom` file, and all but one are within maven central. The only non-centralized dependency is the ICE package `org.eclipse.ice.tests.data`. To install it, perform the following commands (after cloning the ICE repositiory) so that the Commands package can build successfully:
```shell
$ cd org.eclipse.ice.tests
$ mvn clean install
```
### Notes about tests
The automated testing is performed with a dummy remote host, which has private credentials. Thus, if the tests are built with the package, a significant portion of the tests will fail due to the fact that the dummy remote host credentials are not distributed publicly. To solve this, one may enter any generic remote host credentials into the file `$TEST_DATA_PATH/commands/ice-remote-creds.txt` in the following order
```
username
password
hostname
```
See the README in `org.eclipse.ice.tests/org.eclipse.ice.tests.data` for information regarding the `$TEST_DATA_PATH` environment variable; [this link](https://github.com/dbluhm/ice/blob/next/org.eclipse.ice.tests/org.eclipse.ice.tests.data/README.md) takes you to the README on the `next` branch.
The automated tests will then grab the necessary credentials from this file to run. Any valid ssh connection will work. If you still find that the tests fail, ensure that the ssh connection you are using has been logged into before from your host computer such that there is a key fingerprint associated to that host in your `~/.ssh/known_hosts` file. The Commands package requires that this key exists in order for authentication to proceed, no matter what form of authentication you use. In the event that tests fail on a host that already exists in `known_hosts` (e.g. with the error message `server key did not validate`, try deleting your `known_hosts` file (or the entries in your `known_hosts` that correspond to the host you are trying to run the tests on), logging in again to re-establish a fingerprint, and running the tests again.
Alternatively, you can set `StrictHostKeyChecking` to false in the `ConnectionManager`, which is in general not advised as it is inherently unsecure. To do this for the static `ConnectionManager`, just write:
```java
ConnectionManagerFactory.getConnectionManager().setRequireStrictHostKeyChecking(false);
```
Note that this is also a way through which ssh validation can be performed in the package for running actual remote commands/file transfers.
#### EmailHandler test
To test the `EmailUpdateHandler` class, a similar file to the ssh credential file must be created. Instead, a file in the location `$TEST_DATA_PATH/commands/ice-email-creds.txt` must exist which contains the following information:
```
email@address
password
SmtpHost
```
The EmailHandler will send an email from your own address to the same address with updates on when the job finishes. In order for this to happen, the email address must be authenticated. In the case of the tests, and for CI purposes, these authentications are placed in the above text file. For developer use, one could simply enter this information as it is entered in EmailHandlerTest, or you could implement another method (e.g. through use of the text file).
#### KeyGen Tests and Connections
Connections may be established via a public/private key pair that is generated between the local and remote host. Commands can function with ECDSA or RSA type keys. To generate an RSA key, for example, use:
```bash
$ ssh-keygen -t rsa -m PEM
$ ssh-copy-id -i ~/.ssh/keyname.pub username@hostname
```
Then you should be able to remotely login via `ssh -i /path/to/key username@hostname` without a password requirement.
For the keygen connection tests to pass, you should also create a key to a remote host that the tests expect to find. This can be done with any arbitrary remote server that you have credential access to; however, the key must be named dummyhostkey and must exist in your home `.ssh` directory. In other words, the key must be here:
```
$HOME/.ssh/dummyhostkey
```
where `$HOME` is the result returned from `System.getProperty("user.home")`.
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>org.eclipse.ice.tests.integration</artifactId>
<groupId>org.eclipse.ice</groupId>
<version>3.0.0-SNAPSHOT</version>
</parent>
<groupId>org.eclipse.ice</groupId>
<artifactId>org.eclipse.ice.tests.integration.commands</artifactId>
<version>3.0-SNAPSHOT</version>
<name>org.eclipse.ice.tests.integration.commands</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.ice</groupId>
<artifactId>org.eclipse.ice.commands</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.30</version>
</dependency>
<dependency>
<groupId>org.eclipse.ice</groupId>
<artifactId>org.eclipse.ice.tests.data</artifactId>
<version>3.0.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.apache.sshd</groupId>
<artifactId>sshd-core</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>org.apache.sshd</groupId>
<artifactId>sshd-sftp</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>com.sun.mail</groupId>
<artifactId>javax.mail</artifactId>
<version>1.6.2</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.10</version>
</dependency>
<dependency>
<groupId>org.eclipse.ice</groupId>
<artifactId>org.eclipse.ice.data</artifactId>
<version>3.0.0-SNAPSHOT</version>
</dependency>
</dependencies>
<build>
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<plugins>
<!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>