How to receive a callback from non native java method to C++ - java

My Constraints are, I got a api.jar from client which I can not edit.
The java code pasted below is from the test class which I wrote to test the api.jar.
Consumer<DemoAdapter> callbackLogin = demoAdapter -> {
if (webBrowser != null) {
webBrowser.stop();
}
};
Consumer<DemoAdapter> callbackLogout = demoAdapter -> {
if (webBrowser != null) {
webBrowser.stop();
}
};
// Create
AdapterConfig config = Builder.buildConfig();
//Constructor which I need to call from C++;Issue is with above to consumer.
keycloakAdapterApplication = new KeycloakAdapterApplication(callbackLogin,callbackLogout, config);
Now same jar(api.jar) I want to use from C++.So I am supposed to write the test class in C++ using JNI.
I wrote the test class for all the methods which doesn't involve Consumer & BiConsumer of java in their call.
The parameters mentioned above (callbackLogin,callbackLogout) receives callbacks in test class.
Please help me on how to create these two parameters at C++ side?

Related

How to access an annotation value (JUnit 4 -> JUnit 5)

I am trying to port a project from JUnit 4 to JUnit 5. The project includes a custom runner that has a listener that detects whether a test has a certain annotation (#GradedTest) and accesses the annotation's key-value pairs. For example, it would be able to access the values associated with name and points in this code:
#Test
#GradedTest(name = "greet() test", points = "1")
public void defaultGreeting() {
assertEquals(GREETING, unit.greet());
}
The existing JUnit 4 code has a listener that extends RunListener and overrides testStarted():
#Override
public void testStarted(Description description) throws Exception {
super.testStarted(description);
this.currentGradedTestResult = null;
GradedTest gradedTestAnnotation = description.getAnnotation(GradedTest.class);
if (gradedTestAnnotation != null) {
this.currentGradedTestResult = new GradedTestResult(
gradedTestAnnotation.name(),
gradedTestAnnotation.number(),
gradedTestAnnotation.points(),
gradedTestAnnotation.visibility()
);
}
}
Note that this makes use of Description.getAnnotation().
I am trying to switch to the JUnit Platform Launcher API. I can use a LauncherDiscoveryRequestBuilder to select the tests I want to run, and I can create listeners that extend SummaryGeneratingListener and override executionStarted(TestIdentifier testIdentifier). I see no way, however, to get an annotation and its values from a TestIdentifier.
What is the JUnit 5 equivalent of Description.getAnnotation() or the new way of getting a test annotation's values?
I did find a way to get annotations, but I do not know how robust it is. This is how I overrode SummaryGeneratingListener.executionStarted(TestIdentifier identifier):
#Override
public void executionStarted(TestIdentifier identifier) {
super.executionStarted(identifier);
this.currentGradedTestResult = null;
// Check if this is an atomic test, not a container.
if (identifier.isTest()) {
// Check if the test's source is provided.
TestSource source = identifier.getSource().orElse(null);
// If so, and if it's a MethodSource, get and use the annotation if present.
if (source != null && source instanceof MethodSource) {
GradedTest gradedTestAnnotation = ((MethodSource) source).getJavaMethod().getAnnotation(GradedTest.class);
if (gradedTestAnnotation != null) {
this.currentGradedTestResult = new GradedTestResult(
gradedTestAnnotation.name(),
gradedTestAnnotation.number(),
gradedTestAnnotation.points(),
gradedTestAnnotation.visibility()
);
this.currentGradedTestResult.setScore(gradedTestAnnotation.points());
}
}
}
this.testOutput = new ByteArrayOutputStream();
System.setOut(new PrintStream(this.testOutput));
}
The weak link is TestIdentifier.getSource(). The documentation says it gets "the source of the represented test or container, if available." It works for my tests, but I don't know under what circumstances the source is (not) available.

Functional endpoints in micronaut [duplicate]

Simple question. Is it possible to create endpoints without #Endpoint?
I want to create rather dynamic endpoints by a file and depending on the content to its context.
Thanks!
Update about my idea. I would to create something like a plugin system, to make my application more extensible for maintenance and future features.
It is worth to be mentioned I am using Micronaut with Kotlin. Right now I've got fixed defined Endpoints, which matches my command scripts.
My description files will be under /src/main/resources
I've got following example description file how it might look like.
ENDPOINT: GET /myapi/customendpoint/version
COMMAND: """
#!/usr/bin/env bash
# This will be executed via SSH and streamed to stdout for further handling
echo "1.0.0"
"""
# This is a template JSON which will generate a JSON as production on the endpoint
OUTPUT: """
{
"version": "Server version: $RESULT"
}
"""
How I would like to make it work with the application.
import io.micronaut.docs.context.events.SampleEvent
import io.micronaut.context.event.StartupEvent
import io.micronaut.context.event.ShutdownEvent
import io.micronaut.runtime.event.annotation.EventListener
#Singleton
class SampleEventListener {
/*var invocationCounter = 0
#EventListener
internal fun onSampleEvent(event: SampleEvent) {
invocationCounter++
}*/
#EventListener
internal fun onStartupEvent(event: StartupEvent) {
// 1. I read all my description files
// 2. Parse them (for what I created a parser)
// 3. Now the tricky part, how to add those information to Micronaut Runtime
val do = MyDescription() // After I parsed
// Would be awesome if it is that simple! :)
Micronaut.addEndpoint(
do.getEndpoint(), do.getHttpOption(),
MyCustomRequestHandler(do.getCommand()) // Maybe there is a base class for inheritance?
)
}
#EventListener
internal fun onShutdownEvent(event: ShutdownEvent) {
// shutdown logic here
}
}
You can create a custom RouteBuilder that will register your custom endpoints at runtime:
#Singleton
class CustomRouteBuilder extends DefaultRouteBuilder {
#PostConstruct
fun initRoutes() {
val do = MyDescription();
val method = do.getMethod();
val routeUri = do.getEndpoint();
val routeHandle = MethodExecutionHandle<Object, Object>() {
// implement the 'MethodExecutionHandle' in a suitable manner to invoke the 'do.getCommand()'
};
buildRoute(HttpMethod.parse(method), routeUri, routeHandle);
}
}
Note that while this would still feasible, it would be better to consider another extension path as the solution defeats the whole Micronaut philosophy of being an AOT compilation framework.
It was actually pretty easy. The solution for me was to implement a HttpServerFilter.
#Filter("/api/sws/custom/**")
class SwsRouteFilter(
private val swsService: SwsService
): HttpServerFilter {
override fun doFilter(request: HttpRequest<*>?, chain: ServerFilterChain?): Publisher<MutableHttpResponse<*>> {
return Flux.from(Mono.fromCallable {
runBlocking {
swsService.execute(request)
}
}.subscribeOn(Schedulers.boundedElastic()).flux())
}
}
And the service can process with the HttpRequest object:
suspend fun execute(request: HttpRequest<*>?): MutableHttpResponse<Feedback> {
val path = request!!.path.split("/api/sws/custom")[1]
val httpMethod = request.method
val parameters: Map<String, List<String>> = request.parameters.asMap()
// TODO: Handle request body
// and do your stuff ...
}

How can I get a reference to my deployed verticle after deploying it with Vertx?

I have a service called TestService which extends AbstractVerticle:
public class TestService extends AbstractVerticle {
#Override
public void start() throws Exception {
//Do things
}
}
I then deploy that verticle with vertx like this:
Vertx vertx = Vertx.vertx();
vertx.deployVerticle(TestService.class.getName());
How can I get a reference to my deployed TestService after vertx instantiates it?
You should use an alternative method for deployment:
vertx.deployVerticle(TestService.class.getName(), deployment -> {
if (deployment.succeeded()) {
// here is your ID
String deploymentId = deployment.result();
} else {
// deployment failed...
}
});
If you're just interested in listing all deployed verticles then you can just request the list of ids:
vertx.deploymentIDs()
I know this question is old however it may be useful to someone to see an example of how to do this.
You will often see examples for deployment like this from vertx-examples
this follows as asynchronous micro service framework, however its really easy to get the reference as the method 'deployVerticle' (see line 29 in the link) will take an instance as shown in the simple example below, and u can get a reference in the call back as shown.
example in Kotlin easily translate to java
MyVert: io.vertx.core.AbstractVerticle() {
override fun start() {
// init
}
fun someFunction() {
}
}
fun main() {
val vertx = Vertx.vertx()
val myVert = MyVert()
vertx.deployVerticle(myVert) {
if(it.succeeded() ) {
myVert.someFunction()
}
else { println(it.cause().localizedMessage)} }
}
you can get all deployed verticles in current vertx instance by this way
Set<String> strings = vertx.deploymentIDs();
strings
.stream()
.map(id -> ((VertxImpl)vertx.getDelegate()).getDeployment(id))
.forEach(deployment -> System.out.println(deployment.verticleIdentifier() + " " + deployment.isChild() ));
Looks like the vertx API does not allow you to retrieve the Verticle objects once they are deployed. Maybe because verticles can be distributed over multiple JVM.
I needed to do it for unit tests though and I came up with this.
This is unreliable since you rely on VertxImpl (it can break at any vertx version upgrade). But I prefer this over changing production code to be able to test it.
private static <T extends Verticle> List<T> retrieveVerticles(Vertx vertx, Class<T> verticleClass) {
VertxImpl vertxImpl = (VertxImpl) vertx;
return vertxImpl.deploymentIDs().stream().
map(vertxImpl::getDeployment).
map(Deployment::getVerticles).
flatMap(Set::stream).
filter(verticleClass::isInstance).
map(verticleClass::cast).
collect(Collectors.toList());
}
Usage example:
vertx.deployVerticle(new MainVerticle());
// some MyCustomVerticle instances are deployed from the MainVerticle.start
// you can't reach the MyCustomVerticle objects from there
// so the trick is to rely on VertxImpl
List<MyCustomVerticle> deployedVerticles = retrieveVerticles(vertx, MyCustomVerticle.class);

How to mock a javax.mail.Session

i need to mock a javax.mail.Session object in my unit tests.
The class javax.mail.Session is marked final so Mockito is not able to create a mock. Does anyone have an idea how to fix this?
Edit:
My test is an Arquillian test and has already an annotation #RunWith(Arquillian.class). Therefore powermock is not an option.
You may refactor your code a little bit. In the "Working with Legacy Code" book by Martin Fowler, he describes a technique of separating the external API (think Java Mail API) from your own application code. The technique is called "Wrap and Skin" and is pretty simple.
What you should do is simply:
Create an interface MySession (which is your own stuff) by extracting methods from the javax.mail.Session class.
Implement that interface by creating a concrete class (looking a bit like the original javax.mail.Session)
In each method DELEGATE the call to equivalent javax.mail.Session method
Create your mock class which implements MySession :-)
Update your production code to use MySession instead of javax.mail.Session
Happy testing!
EDIT: Also take a look at this blog post: http://www.mhaller.de/archives/18-How-to-mock-a-thirdparty-final-class.html
Use PowerMockito to mock it.
#RunWith(PowerMockRunner.class)
// We prepare PartialMockClass for test because it's final or we need to mock private or static methods
#PrepareForTest(javax.mail.Session.class)
public class YourTestCase {
#Test
public void test() throws Exception {
PowerMockito.doReturn(value).when(classUnderTest, "methodToMock", "parameter1");
}
}
You can use the Mock JavaMail project. I first found it from Kohsuke Kawaguchi. Alan Franzoni also has a primer for it on his blog.
When you put this jar file in your classpath, it substitutes any sending of mail to in memory mailboxes that can be checked immediately. It's super easy to use.
Adding this to your classpath is admittedly a pretty heavy handed way to mock something, but you rarely want to send real emails in your automated tests anyway.
If you want to mock a final classes you can use the JDave unfinalizer which can be found here : http://jdave.org/documentation.html#mocking
It uses CGLib to alter the bytecode dynamically when the JVM is loaded to transform the class as a non final class.
This library can then be used with JMock2 ( http://www.jmock.org/mocking-classes.html ) to make your tests because as far as I know, Mockito is not compatible with JDave.
Use Java 8 Functions!
public class SendEmailGood {
private final Supplier<Message> messageSupplier;
private final Consumer<Message> messageSender;
public SendEmailGood(Supplier<Message> messageSupplier,
Consumer<Message> messageSender) {
this.messageSupplier = messageSupplier;
this.messageSender = messageSender;
}
public void send(String[] addresses, String from,
String subject, String body)
throws MessagingException {
Message message = messageSupplier.get();
for (String address : addresses) {
message.addRecipient
(Message.RecipientType.TO, new InternetAddress(address));
}
message.addFrom(new InternetAddress[]{new InternetAddress(from)});
message.setSubject(subject);
message.setText(body);
messageSender.accept(message);
}
}
Then your test code will look something like the following:
#Test
public void sendBasicEmail() throws MessagingException {
final boolean[] messageCalled = {false};
Consumer<Message> consumer = message -> {
messageCalled[0] = true;
};
Message message = mock(Message.class);
Supplier<Message> supplier = () -> message;
SendEmailGood sendEmailGood = new SendEmailGood(supplier, consumer);
String[] addresses = new String[2];
addresses[0] = "foo#foo.com";
addresses[1] = "boo#boo.com";
String from = "baz#baz.com";
String subject = "Test Email";
String body = "This is a sample email from us!";
sendEmailGood.send(addresses, from, subject, body);
verify(message).addRecipient(Message.RecipientType.TO, new InternetAddress("foo#foo.com"));
verify(message).addRecipient(Message.RecipientType.TO, new InternetAddress("boo#boo.com"));
verify(message).addFrom(new InternetAddress[]{new InternetAddress("baz#baz.com")});
verify(message).setSubject(subject);
verify(message).setText(body);
assertThat(messageCalled[0]).isTrue();
}
To create an integration test, plugin the real Session, and Transport.
Consumer<Message> consumer = message -> {
try {
Transport.send(message);
} catch (MessagingException e) {
e.printStackTrace();
}
};
Supplier<Message> supplier = () -> {
Properties properties = new Properties();
return new MimeMessage(Session.getDefaultInstance(properties));
};
See the PowerMock docs for running under JUnit 3, since it did not have runners, or use a byte-code manipulation tool.
If you can introduce Spring into your project you can use the JavaMailSender and mock that. I don't know how complicated your requirements are.
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
#Test
public void createAndSendBookChangesMail() {
// Your custom service layer object to test
MailServiceImpl service = new MailServiceImpl();
// MOCK BEHAVIOUR
JavaMailSender mailSender = mock(JavaMailSender.class);
service.setMailSender(mailSender);
// PERFORM TEST
service.createAndSendMyMail("some mail message content");
// ASSERT
verify(mailSender).send(any(SimpleMailMessage.class));
}
This is a pretty old question, but you could always implement your own Transport using the JavaMail API. With your own transport, you could just configure it according to this documentation. One benefit of this approach is you could do anything you want with these messages. Perhaps you would store them in a hash/set that you could then ensure they actually got sent in your unit tests. This way, you don't have to mock the final object, you just implement your own.
I use the mock-javamail library. It just replace the origin javamail implementation in the classpath. You can send mails normally, it just sends to in-memory MailBox, not a real mailbox.
Finally, you can use the MailBox object to assert anything you want to check.

How do you create a secure JEXL (scripting) sandbox?

I'm creating a sandbox for JEXL scripts to execute in so that a malicious user can't access data outside the variables we give them access to and also can't perform a DOS attack on the server. I'd like to document this for anybody else also doing this and also get other people's input into the approach.
The following is a list of the things I'm aware of that needs to be addressed:
Only allow instantiating classes using 'new' that are on a whitelist.
Do not allow accessing the getClass method on any class because then forName can be called and any class can be accessed.
Restrict access to resources such as files.
Allow an expression only a certain amount of time to execute so that we can limit the amount of resources it consumes.
This does not apply to JEXL but may apply to the scripting language you are using:
Do not allow an object to have a custom finalize method because the finalize method is called from the finalizer thread and will execute with the original AccessControlContext instead of the one being used to create the object and execute the code in it.
UPDATE: This was all done using JEXL 2.0.1. You may have to adapt this to make it work with newer versions.
Here is my approach for dealing with each of these cases. I've created unit tests to test each of these cases and I have verified that they work.
JEXL makes this pretty easy. Just create a custom ClassLoader. Override the two loadClass() methods. On JexlEngine call setClassLoader().
Again, JEXL makes this pretty easy. You must block both '.class' and '.getClass()'. Create your own Uberspect class which extends UberspectImpl. Override getPropertyGet, if identifier equals "class" return null. Override getMethod, if method equals "getClass" return null. When constructing JexlEngine pass a reference to your Uberspect implementation.
class MyUberspectImpl extends UberspectImpl {
public MyUberspectImpl(Log jexlLog) {
super(jexlLog);
}
#Override
public JexlPropertyGet getPropertyGet(Object obj, Object identifier, JexlInfo info) {
// for security we do not allow access to .class property
if ("class".equals(identifier)) throw new RuntimeException("Access to getClass() method is not allowed");
JexlPropertyGet propertyGet = super.getPropertyGet(obj, identifier, info);
return propertyGet;
}
#Override
public JexlMethod getMethod(Object obj, String method, Object[] args, JexlInfo info) {
// for security we do not allow access to .getClass() method
if ("getClass".equals(method)) throw new RuntimeException("Access to getClass() method is not allowed");
return super.getMethod(obj, method, args, info);
}
}
You do this using Java's AccessController mechanism. I'll give a quick run-down of doing this. Start java with -Djava.security.policy=policyfile. Make a file named policyfile containing this line:
grant { permission java.security.AllPermission; };
Set the default SecurityManager with this call: System.setSecurityManager(new SecurityManager()); Now you can control permissions and your app by default has all permissions. It would be better if you limit the permissions of your app to only what it requires of course. Next, create an AccessControlContext that limits the permissions to the bare minimum and call AccessController.doPrivileged() and pass the AccessControlContext, then execute the JEXL script inside doPrivileged(). Here is a small program that demonstrates this. The JEXL script calls System.exit(1) and if it isn't wrapped in doPrivileged() it would successfully terminate the JVM.
System.out.println("java.security.policy=" + System.getProperty("java.security.policy"));
System.setSecurityManager(new SecurityManager());
try {
Permissions perms = new Permissions();
perms.add(new RuntimePermission("accessDeclaredMembers"));
ProtectionDomain domain = new ProtectionDomain(new CodeSource( null, (Certificate[]) null ), perms );
AccessControlContext restrictedAccessControlContext = new AccessControlContext(new ProtectionDomain[] { domain } );
JexlEngine jexlEngine = new JexlEngine();
final Script finalExpression = jexlEngine.createScript(
"i = 0; intClazz = i.class; "
+ "clazz = intClazz.forName(\"java.lang.System\"); "
+ "m = clazz.methods; m[0].invoke(null, 1); c");
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
#Override
public Object run() throws Exception {
return finalExpression.execute(new MapContext());
}
}, restrictedAccessControlContext);
}
catch (Throwable ex) {
ex.printStackTrace();
}
The trick with this is interrupting the script before it finishes. One way I found to do this is to create a custom JexlArithmetic class. Then override each method in that class and before calling the real method in the super class check if the script should stop executing. I'm using an ExecutorService to create threads. When Future.get() is called pass the amount of time to wait. If a TimeoutException is thrown call Future.cancel() which interrupts the Thread running the script. Inside each overridden method in the new JexlArithmetic class check Thread.interrupted() and if true throw java.util.concurrent.CancellationException.
Is there a better location to put code which will get executed regularly as a script is being executed so that it can be interrupted?
Here is an excerpt of the MyJexlArithmetic class. You have to add all the other methods:
public class MyJexlArithmetic extends JexlArithmetic {
public MyJexlArithmetic(boolean lenient) {
super(lenient);
}
private void checkInterrupted() {
if (Thread.interrupted()) throw new CancellationException();
}
#Override
public boolean equals(Object left, Object right) {
checkInterrupted();
return super.equals(left, right); //To change body of generated methods, choose Tools | Templates.
}
#Override
public Object add(Object left, Object right) {
checkInterrupted();
return super.add(left, right);
}
}
Here is how I am instantiating JexlEngine:
Log jexlLog = LogFactory.getLog("JEXL");
Map <String, Object> functions = new HashMap();
jexlEngine = new JexlEngine(new MyUberspectImpl(jexlLog), new MyJexlArithmetic(false), functions, jexlLog);

Categories

Resources