I am exploring Ignite dataStreamer with the following code.
But the output is:
For MessageKey0001, the output all displays data is null.
For MessageKey0003, the output also all displays data is null
For MessageKey0002, the output shows nothing, looks that receiver code is not run
When I change
dataStreamer.addData(i, "data-" + i);
to
IgniteFuture future = dataStreamer.addData(i, "data-" + i);
future.get();
The future.get() doesn't return, looks addData doesn't finish anyway?
I am not sure where the problem is, can someone take a look? Thanks!
package ignite.streamer;
import org.apache.ignite.*;
import org.apache.ignite.cache.query.annotations.QuerySqlField;
import org.apache.ignite.configuration.CacheConfiguration;
import org.apache.ignite.stream.StreamReceiver;
import javax.cache.Cache;
import java.io.Serializable;
import java.util.Collection;
import java.util.Map;
class IgniteDataStreamer_Person implements Serializable {
#QuerySqlField(index = true)
private String name;
#QuerySqlField(index = true)
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
public class IgniteDataStreamerTest {
public static void main(String[] args) {
String configPath = "D:/Software/apache-ignite-fabric-1.7.0-bin/apache-ignite-fabric-1.7.0-bin/config/default-config.xml";
Ignite ignite = Ignition.start(configPath);
CacheConfiguration<Integer, String> cfg = new CacheConfiguration<Integer, String>();
String cacheName = "stream_cache";
cfg.setName(cacheName);
cfg.setIndexedTypes(Integer.class, IgniteDataStreamer_Person.class);
Cache cache = ignite.getOrCreateCache(cfg);
IgniteDataStreamer<Integer, String> dataStreamer = ignite.dataStreamer(cacheName);
for (int i = 0; i < 3; i++) {
dataStreamer.addData(i, "data-" + i);
}
//null is got from cache
for (int i = 0; i < 3; i++) {
System.out.println(String.format("0001: data is %s ", cache.get(i)));
}
dataStreamer.receiver(new StreamReceiver<Integer, String>() {
public void receive(IgniteCache<Integer, String> cache, Collection<Map.Entry<Integer, String>> entries) throws IgniteException {
//nothing is printed to console
for (Map.Entry<Integer, String> entry : entries) {
System.out.println(String.format("0002: key is: %s, value is: %s", entry.getKey(), entry.getValue()));
}
}
});
//null is got from cache
for (int i = 0; i < 3; i++) {
System.out.println(String.format("0003: data is %s ", cache.get(i)));
}
ignite.close();
}
}
DataStreamer uses batches in order to provide good performance. You should flush data in your case (use flush() method) before block on future.get() method.
Please, see IgniteDataStreamer javadocs for details.
Related
I am facing an issue related to WhatsApp sticker implementation. I have used this library I want to check that particular sticker is already added or not in WhatsApp.
How can I achieve this? Please guide me.
I have used below file from this library. isPackageInstalled() function worked for me (Note : I just wanted this functionality only for Android)
package org.roborox.whatsapp;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ProviderInfo;
import android.database.Cursor;
import android.net.Uri;
import androidx.annotation.NonNull;
public class WhitelistCheck {
private static final String AUTHORITY_QUERY_PARAM = "authority";
private static final String IDENTIFIER_QUERY_PARAM = "identifier";
private static String STICKER_APP_AUTHORITY = "sticker_pack_authority";// StickerContentProvider.authority;
public static String CONSUMER_WHATSAPP_PACKAGE_NAME = "com.whatsapp";
public static String INSTAGRAM_PACKAGE_NAME = "com.instagram.android";
public static String SMB_WHATSAPP_PACKAGE_NAME = "com.whatsapp.w4b";
private static String CONTENT_PROVIDER = ".provider.sticker_whitelist_check";
private static String QUERY_PATH = "is_whitelisted";
private static String QUERY_RESULT_COLUMN_NAME = "result";
public static boolean isWhitelisted(#NonNull Context context, #NonNull String identifier) {
try {
boolean consumerResult = isWhitelistedFromProvider(context, identifier, CONSUMER_WHATSAPP_PACKAGE_NAME);
boolean smbResult = isWhitelistedFromProvider(context, identifier, SMB_WHATSAPP_PACKAGE_NAME);
return consumerResult && smbResult;
} catch (Exception e) {
return false;
}
}
private static boolean isWhitelistedFromProvider(#NonNull Context context, #NonNull String identifier, String whatsappPackageName) {
final PackageManager packageManager = context.getPackageManager();
if (isPackageInstalled(whatsappPackageName, packageManager)) {
final String whatsappProviderAuthority = whatsappPackageName + CONTENT_PROVIDER;
final ProviderInfo providerInfo = packageManager.resolveContentProvider(whatsappProviderAuthority, PackageManager.GET_META_DATA);
// provider is not there.
if (providerInfo == null) {
return false;
}
final Uri queryUri = new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT).authority(whatsappProviderAuthority).appendPath(QUERY_PATH).
appendQueryParameter(AUTHORITY_QUERY_PARAM, BuildConfig.CONTENT_PROVIDER_AUTHORITY).appendQueryParameter(IDENTIFIER_QUERY_PARAM, identifier).build();
final Cursor cursor = context.getContentResolver().query(queryUri, null, null, null, null);
if (cursor != null && cursor.moveToFirst()) {
final int whiteListResult = cursor.getInt(cursor.getColumnIndexOrThrow(QUERY_RESULT_COLUMN_NAME));
return whiteListResult == 1;
}
} else {
//if app is not installed, then don't need to take into its whitelist info into account.
return true;
}
return false;
}
public static boolean isPackageInstalled(String packageName, PackageManager packageManager) {
try {
final ApplicationInfo applicationInfo = packageManager.getApplicationInfo(packageName, 0);
//noinspection SimplifiableIfStatement
if (applicationInfo != null) {
return applicationInfo.enabled;
} else {
return false;
}
} catch (PackageManager.NameNotFoundException e) {
return false;
}
}
public static boolean redirectToInstagram(Context context) {
final PackageManager packageManager = context.getPackageManager();
if (isPackageInstalled(INSTAGRAM_PACKAGE_NAME, packageManager)) {
Intent i = context.getPackageManager().getLaunchIntentForPackage(INSTAGRAM_PACKAGE_NAME);
context.startActivity(i);
return true;
} else {
return false;
}
}
}
I have coded a simple card game (using IntelliJ 3.3) that updates gui each second and contains many nodes in game which are used to display game events and animation. People who have tried the game said that their system slows down and memory and cpu usage goes up (I was shocked when I saw from one of my friend's screen that it used around 1.4 GB ram) is this supposed to happen?
I have checked some questions related to javaFX memory usage problems but could not relate to my matter. In one article, I read that using many nodes in a JavaFX game might result in high memory usage.
in a short runtime:
minimum memory usage is around 100-250 MB
maximum memory usage is around 800-1200 MB
average memory usage is around 500-700 MB
IMPORTANT:
THERE ARE 100 BUTTONS IN A 10X10 GRIDPANE WHICH DO NOT HAVE FX IDS
in gameButtonClicked matches are found buttons.indexOf(event.getSource())
UML DIAGRAM
Main.java
IMPORTS:
import javafx.application.Application;
import javafx.application.Platform;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import javafx.stage.Stage;
import javafx.util.Duration;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Random;
import java.util.concurrent.atomic.AtomicLong;
public class Main extends Application {
static boolean isMuted;
static Stage window;
static MediaPlayer mediaPlayerBGM;
static MediaPlayer mediaPlayerSFX;
private static HashMap<String, Media> sounds;
private static ArrayList<Long> usage;
private final String[] SOUND_LIST = {"bgm_credits.mp3", "bgm_game.mp3", "bgm_game_1.mp3", "bgm_game_2.mp3", "bgm_game_3.mp3",
"bgm_how_to.mp3", "bgm_menu.mp3", "bgm_victory.mp3", "sfx_button_clicked.wav",
"sfx_card_unfold.wav", "sfx_toggle.wav"
};
public static void main(String[] args) {
launch(args);
AtomicLong sum = new AtomicLong();
usage.forEach(sum::addAndGet);
long average = sum.get() / usage.size();
System.out.printf("minimum usage: %d, maximum usage: %d, average usage: %d",
Collections.min(usage), Collections.max(usage), average);
}
static void playBGM(String key) {
mediaPlayerBGM.stop();
mediaPlayerBGM.setStartTime(Duration.ZERO);
if (key.equals("bgm_game")) {
String[] suffix = {"", "_1", "_2", "_3"};
Random random = new Random();
mediaPlayerBGM = new MediaPlayer(sounds.get(key + suffix[random.nextInt(4)]));
} else {
mediaPlayerBGM = new MediaPlayer(sounds.get(key));
}
mediaPlayerBGM.setCycleCount(MediaPlayer.INDEFINITE);
if (isMuted) {
mediaPlayerBGM.setVolume(0.0);
}
mediaPlayerBGM.play();
}
static void playSFX(String key) {
if (mediaPlayerSFX != null) {
mediaPlayerSFX.stop();
}
mediaPlayerSFX = new MediaPlayer(sounds.get(key));
if (isMuted) {
mediaPlayerSFX.setVolume(0.0);
}
mediaPlayerSFX.play();
}
#Override
public void start(Stage primaryStage) throws Exception {
sounds = new HashMap<>();
usage = new ArrayList<>();
isMuted = false;
for (String soundName :
SOUND_LIST) {
URL resource = getClass().getResource("/" + soundName);
System.out.println(soundName);
System.out.println(resource.toString());
sounds.put(soundName.substring(0, soundName.lastIndexOf('.')), new Media(resource.toString()));
}
mediaPlayerBGM = new MediaPlayer(sounds.get("bgm_menu"));
mediaPlayerBGM.setCycleCount(MediaPlayer.INDEFINITE);
mediaPlayerBGM.play();
window = primaryStage;
Parent root = FXMLLoader.load(getClass().getResource("menu.fxml"));
// long running operation runs on different thread
Thread thread = new Thread(() -> {
Runnable updater = () -> {
if (!Game.isGameIsOver() && Game.getScore() != 0 && window.getTitle().equals("The Main Pick") &&
Game.firstClickHappened()) {
Game.scoreCalculator();
}
};
while (true) {
try {
usage.add(Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory());
System.out.printf("Used memory: %d\n", Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory());
Thread.sleep(1000);
} catch (InterruptedException ex) {
System.out.println("Interrupted");
}
// UI update is run on the Application thread
Platform.runLater(updater);
}
});
// don't let thread prevent JVM shutdown
thread.setDaemon(true);
thread.start();
window.setTitle("Main Menu");
window.setScene(new Scene(root, 600, 600));
window.setResizable(false);
window.show();
}
}
Controller.java
IMPORTS:
package com.sample;
import javafx.animation.FadeTransition;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
importjavafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.RadioButton;
import javafx.scene.layout.GridPane;
import javafx.util.Duration;
import java.io.IOException;
public class Controller
{
#FXML
public RadioButton musicOnOff;
#FXML
public Button newGame;
#FXML
public Button howTo;
#FXML
public Button credits;
#FXML
public Button exit;
#FXML
public Button menu;
#FXML
public GridPane pane;
#FXML
public Label score;
#FXML
public Label time;
#FXML
public Label tries;
private boolean animating;
public void initialize() {
if (score != null && time != null && tries != null) {
score.textProperty().bind(Game.scoreProperty);
time.textProperty().bind(Game.timeProperty);
tries.textProperty().bind(Game.triesProperty);
animating=false;
}
if (musicOnOff!=null){
if(Main.isMuted){
musicOnOff.setSelected(true);
}
}
}
public void newGameButtonClicked() {
try {
Main.playSFX("sfx_button_clicked");
new Game();
Main.window.hide();
Main.window.setScene(getScene("game"));
Main.window.setTitle("The Main Pick");
Main.window.setMaximized(true);
Main.playBGM("bgm_game");
Main.window.show();
} catch (IOException e) {
System.out.println("could not change the scene to: game");
}
}
public void menuButtonClicked() {
try {
Main.playSFX("sfx_button_clicked");
Main.playBGM("bgm_menu");
if (Main.window.getTitle().equals("The Main Pick")) {
Main.window.hide();
Game.setGameOver();
Main.window.setScene(getScene("menu"));
Main.window.setMaximized(false);
Main.window.show();
} else {
Main.window.setScene(getScene("menu"));
}
Main.window.setTitle("Main Menu");
} catch (IOException e) {
System.out.println("could not change the scene to: game");
}
}
public void gameButtonClicked(ActionEvent event) {
ObservableList<Node> buttons = pane.getChildren();
int index = buttons.indexOf(event.getSource());
int column = index % 10;
int row = (index - index % 10) / 10;
if (!((Button) event.getSource()).getStyleClass().toString().equals("button button-treasure") &&
!((Button) event.getSource()).getStyleClass().toString().equals("button button-uncovered"))
{
FadeTransition transition = new FadeTransition();
transition.setNode((Button) event.getSource());
transition.setDuration(new Duration(500));
transition.setFromValue(1.0);
transition.setToValue(0.0);
transition.setCycleCount(1);
transition.setOnFinished(actionEvent -> {
if (((Button) event.getSource()).getStyleClass().toString().equals("button button-treasure")) {
loadVictoryScene();
}
if (!((Button) event.getSource()).getStyleClass().toString().equals("button button-treasure") &&
!((Button) event.getSource()).getStyleClass().toString().equals("button button-uncovered"))
{
transition.setFromValue(0.0);
transition.setToValue(1.0);
System.out.println(((Button) event.getSource()).getStyleClass().toString());
((Button) event.getSource()).getStyleClass().remove("button-covered");
((Button) event.getSource()).getStyleClass().add(Game.click(row, column));
transition.play();
transition.setOnFinished(ActionEvent->animating=false);
}
});
System.out.println(animating);
if(!animating){
animating=true;
transition.play();
Main.playSFX("sfx_card_unfold");}
}
System.out.printf("button index:%d,row:%d,column:%d\n", index, row, column);
}
public void howToPlayButtonClicked() {
try {
Main.playSFX("sfx_button_clicked");
Main.playBGM("bgm_how_to");
Main.window.setScene(getScene("howTo"));
Main.window.setTitle("How to Play");
} catch (IOException e) {
System.out.println("could not change the scene to: how to play");
}
}
public void creditsButtonClicked() {
try {
Main.playSFX("sfx_button_clicked");
Main.playBGM("bgm_credits");
Main.window.setScene(getScene("credits"));
Main.window.setTitle("Credits");
} catch (IOException e) {
System.out.println("could not change the scene to: credits");
}
}
public void exitButtonClicked() {
Main.playSFX("sfx_button_clicked");
Main.window.close();
}
public void musicOnOffRadioButtonChecked() {
Main.playSFX("sfx_toggle");
if (musicOnOff.isSelected()) {
Main.isMuted=true;
Main.mediaPlayerBGM.setVolume(0.0);
Main.mediaPlayerSFX.setVolume(0.0);
System.out.println("now selected");
} else {
Main.isMuted=false;
Main.mediaPlayerBGM.setVolume(1.0);
Main.mediaPlayerSFX.setVolume(1.0);
System.out.println("unselected");
}
}
private void loadVictoryScene() {
try {
Main.window.hide();
Main.playBGM("bgm_victory");
Main.window.setScene(getScene("victory"));
Main.window.setTitle("Victory");
Main.window.setMaximized(false);
Main.window.show();
} catch (IOException e) {
System.out.println("could not change the scene to: victory");
}
}
private Scene getScene(String name) throws IOException {
Parent root = FXMLLoader.load(getClass().getResource(name + ".fxml"));
if (name.equals("game")) {
return new Scene(root, 800, 800);
}
return new Scene(root, 600, 600);
}
}
Game.java
IMPORTS:
package com.sample;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import java.util.Random;
public class Game {
static StringProperty scoreProperty;
static StringProperty timeProperty;
static StringProperty triesProperty;
private static int time;
private static int score;
private static int tries;
private static int[][] tiles;
private static boolean gameIsOver;
private static boolean firstClick;
public Game() {
System.out.println("Game created...");
tries = 0;
score = 100000;
time = 0;
gameIsOver = false;
firstClick = false;
scoreProperty = new SimpleStringProperty("" + score);
timeProperty = new SimpleStringProperty("0");
triesProperty = new SimpleStringProperty("0");
tiles = new int[10][10];
Random random = new Random();
int treasureColumn = random.nextInt(10);
int treasureRow = random.nextInt(10);
tiles[treasureRow][treasureColumn] = 1;
}
static boolean firstClickHappened() {
return firstClick;
}
static void setGameOver() {
gameIsOver = true;
}
static boolean isGameIsOver() {
return gameIsOver;
}
static int getScore() {
return score;
}
static void scoreCalculator() {
time++;
if (time < 10) {
score = score - 100;
} else if (time < 20) {
score = score - 200;
} else if (time < 30) {
score = score - 300;
} else if (time < 50) {
score = score - 500;
} else {
score = score - 1000;
}
if (score < 0) {
score = 0;
}
scoreProperty.setValue("" + score);
timeProperty.setValue("" + time);
triesProperty.setValue("" + tries);
System.out.printf("Score:%s,Time:%s,Tries%s\n", scoreProperty.getValue(), timeProperty.getValue(), triesProperty.getValue());
}
static String click(int row, int column) {
if (!firstClickHappened()) firstClick = true;
System.out.println(row + "," + column);
int clickValue = tiles[row][column];
System.out.println(clickValue);
if (clickValue == 0) {
tries++;
score -= 1000;
} else {
setGameOver();
}
return (clickValue == 1) ? "button-treasure" : "button-uncovered";
}
}
I am trying to fetch the data using data provider in selenium from an excel sheet. When the data is returned/passed on to the caller function, i get null values for the first time even though loop begins from the second row having the actual data. I am not sure why this is happening.
package pageobjectmodel;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import org.testng.Assert;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import Utils.ReadingExcelfile;
import Utils.TestBase;
import pagebasedexecution.LinkedInloginPage;
public class LinkedInLoginTest extends TestBase
{
//public static ReadExcel excelfile;
public static ReadingExcelfile excelfile;
LinkedInloginPage loginPage;
public LinkedInLoginTest() throws IOException
{
super();
}
#BeforeMethod
public void Setup() throws IOException, NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException
{
BrowserSetup();
loginPage = new LinkedInloginPage();
}
#Test(dataProvider="TestData")
public void LoginTest(String uname, String password) throws InterruptedException
{
// System.out.println("received data is --- " +uname + " , " + password);
loginPage.LoginIntoAccount(uname, password);
String title = loginPage.VerifyTitle();
Assert.assertEquals(title, "LinkedIn", "Unable to login: invalid credentials");
Thread.sleep(5000);
}
/*#Test(priority=2)
public void VerifyloginPageTitleTest() throws InterruptedException
{
String title = loginPage.VerifyTitle();
Assert.assertEquals(title, "LinkedIn", "Unable to login: invalid credentials");
}*/
#DataProvider
public Object[][] TestData() throws IOException
{
excelfile = new ReadingExcelfile(System.getProperty("user.dir")+"\\src\\main\\java\\testData\\LinkedIn.xlsx");
int rows = excelfile.RowCount(1);
int colm = excelfile.TotalColm("LoginPage", 0);
Object[][] credentials = new Object[rows][colm];
for(int i = 1; i < rows; i++)
{
for(int j = 0; j<colm; j++)
{
credentials[i][j] = excelfile.getdata("LoginPage", i, j);
System.out.println("Fetched data from excel sheet is -- "+credentials[i][j]);
}
}
return credentials;
}
#AfterMethod
public void closebrowser()
{
System.out.println("quitting browser");
driver.quit();
}
}
Even though i am fetching the data from second row, somehow it's fetching the data from first row(column names) and first set of data is returned as null, null. i have provided the screenshot of error console and highlighted the error portion. Any help is appreciated.
Thanks
This is because here
Object[][] credentials = new Object[rows][colm];
you are creating array of object with number of rows and colums present in your sheet but you are inserting value in this array from second row So In first row it is taking default null values.
Replace code :
for(int j = 0; j<colm; j++)
{
credentials[i][j] = excelfile.getdata("LoginPage", i, j);
System.out.println("Fetched data from excel sheet is -- "+credentials[i][j]);
}
With
for(int j = 0; j<colm; j++)
{
credentials[i-1][j] = excelfile.getdata("LoginPage", i, j);
System.out.println("Fetched data from excel sheet is -- "+credentials[i-1][j]);
}
This question already has answers here:
Compile code fully in memory with javax.tools.JavaCompiler [duplicate]
(7 answers)
Closed 6 years ago.
I want to treat a String as a Java file then compile and run it. In other words, use Java as a script language.
To get better performance, we should avoid writing .class files to disk.
This answer is from one of my blogs, Compile and Run Java Source Code in Memory.
Here are the three source code files.
MemoryJavaCompiler.java
package me.soulmachine.compiler;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Writer;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.tools.*;
/**
* Simple interface to Java compiler using JSR 199 Compiler API.
*/
public class MemoryJavaCompiler {
private javax.tools.JavaCompiler tool;
private StandardJavaFileManager stdManager;
public MemoryJavaCompiler() {
tool = ToolProvider.getSystemJavaCompiler();
if (tool == null) {
throw new RuntimeException("Could not get Java compiler. Please, ensure that JDK is used instead of JRE.");
}
stdManager = tool.getStandardFileManager(null, null, null);
}
/**
* Compile a single static method.
*/
public Method compileStaticMethod(final String methodName, final String className,
final String source)
throws ClassNotFoundException {
final Map<String, byte[]> classBytes = compile(className + ".java", source);
final MemoryClassLoader classLoader = new MemoryClassLoader(classBytes);
final Class clazz = classLoader.loadClass(className);
final Method[] methods = clazz.getDeclaredMethods();
for (final Method method : methods) {
if (method.getName().equals(methodName)) {
if (!method.isAccessible()) method.setAccessible(true);
return method;
}
}
throw new NoSuchMethodError(methodName);
}
public Map<String, byte[]> compile(String fileName, String source) {
return compile(fileName, source, new PrintWriter(System.err), null, null);
}
/**
* compile given String source and return bytecodes as a Map.
*
* #param fileName source fileName to be used for error messages etc.
* #param source Java source as String
* #param err error writer where diagnostic messages are written
* #param sourcePath location of additional .java source files
* #param classPath location of additional .class files
*/
private Map<String, byte[]> compile(String fileName, String source,
Writer err, String sourcePath, String classPath) {
// to collect errors, warnings etc.
DiagnosticCollector<JavaFileObject> diagnostics =
new DiagnosticCollector<JavaFileObject>();
// create a new memory JavaFileManager
MemoryJavaFileManager fileManager = new MemoryJavaFileManager(stdManager);
// prepare the compilation unit
List<JavaFileObject> compUnits = new ArrayList<JavaFileObject>(1);
compUnits.add(fileManager.makeStringSource(fileName, source));
return compile(compUnits, fileManager, err, sourcePath, classPath);
}
private Map<String, byte[]> compile(final List<JavaFileObject> compUnits,
final MemoryJavaFileManager fileManager,
Writer err, String sourcePath, String classPath) {
// to collect errors, warnings etc.
DiagnosticCollector<JavaFileObject> diagnostics =
new DiagnosticCollector<JavaFileObject>();
// javac options
List<String> options = new ArrayList<String>();
options.add("-Xlint:all");
// options.add("-g:none");
options.add("-deprecation");
if (sourcePath != null) {
options.add("-sourcepath");
options.add(sourcePath);
}
if (classPath != null) {
options.add("-classpath");
options.add(classPath);
}
// create a compilation task
javax.tools.JavaCompiler.CompilationTask task =
tool.getTask(err, fileManager, diagnostics,
options, null, compUnits);
if (task.call() == false) {
PrintWriter perr = new PrintWriter(err);
for (Diagnostic diagnostic : diagnostics.getDiagnostics()) {
perr.println(diagnostic);
}
perr.flush();
return null;
}
Map<String, byte[]> classBytes = fileManager.getClassBytes();
try {
fileManager.close();
} catch (IOException exp) {
}
return classBytes;
}
}
MemoryJavaFileManager.java
package me.soulmachine.compiler;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URI;
import java.nio.CharBuffer;
import java.util.HashMap;
import java.util.Map;
import javax.tools.FileObject;
import javax.tools.ForwardingJavaFileManager;
import javax.tools.JavaFileManager;
import javax.tools.JavaFileObject;
import javax.tools.JavaFileObject.Kind;
import javax.tools.SimpleJavaFileObject;
/**
* JavaFileManager that keeps compiled .class bytes in memory.
*/
#SuppressWarnings("unchecked")
final class MemoryJavaFileManager extends ForwardingJavaFileManager {
/** Java source file extension. */
private final static String EXT = ".java";
private Map<String, byte[]> classBytes;
public MemoryJavaFileManager(JavaFileManager fileManager) {
super(fileManager);
classBytes = new HashMap<>();
}
public Map<String, byte[]> getClassBytes() {
return classBytes;
}
public void close() throws IOException {
classBytes = null;
}
public void flush() throws IOException {
}
/**
* A file object used to represent Java source coming from a string.
*/
private static class StringInputBuffer extends SimpleJavaFileObject {
final String code;
StringInputBuffer(String fileName, String code) {
super(toURI(fileName), Kind.SOURCE);
this.code = code;
}
public CharBuffer getCharContent(boolean ignoreEncodingErrors) {
return CharBuffer.wrap(code);
}
}
/**
* A file object that stores Java bytecode into the classBytes map.
*/
private class ClassOutputBuffer extends SimpleJavaFileObject {
private String name;
ClassOutputBuffer(String name) {
super(toURI(name), Kind.CLASS);
this.name = name;
}
public OutputStream openOutputStream() {
return new FilterOutputStream(new ByteArrayOutputStream()) {
public void close() throws IOException {
out.close();
ByteArrayOutputStream bos = (ByteArrayOutputStream)out;
classBytes.put(name, bos.toByteArray());
}
};
}
}
public JavaFileObject getJavaFileForOutput(JavaFileManager.Location location,
String className,
Kind kind,
FileObject sibling) throws IOException {
if (kind == Kind.CLASS) {
return new ClassOutputBuffer(className);
} else {
return super.getJavaFileForOutput(location, className, kind, sibling);
}
}
static JavaFileObject makeStringSource(String fileName, String code) {
return new StringInputBuffer(fileName, code);
}
static URI toURI(String name) {
File file = new File(name);
if (file.exists()) {
return file.toURI();
} else {
try {
final StringBuilder newUri = new StringBuilder();
newUri.append("mfm:///");
newUri.append(name.replace('.', '/'));
if(name.endsWith(EXT)) newUri.replace(newUri.length() - EXT.length(), newUri.length(), EXT);
return URI.create(newUri.toString());
} catch (Exception exp) {
return URI.create("mfm:///com/sun/script/java/java_source");
}
}
}
}
MemoryClassLoader.java
package me.soulmachine.compiler;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
/**
* ClassLoader that loads .class bytes from memory.
*/
final class MemoryClassLoader extends URLClassLoader {
private Map<String, byte[]> classBytes;
public MemoryClassLoader(Map<String, byte[]> classBytes,
String classPath, ClassLoader parent) {
super(toURLs(classPath), parent);
this.classBytes = classBytes;
}
public MemoryClassLoader(Map<String, byte[]> classBytes, String classPath) {
this(classBytes, classPath, ClassLoader.getSystemClassLoader());
}
public MemoryClassLoader(Map<String, byte[]> classBytes) {
this(classBytes, null, ClassLoader.getSystemClassLoader());
}
public Class load(String className) throws ClassNotFoundException {
return loadClass(className);
}
public Iterable<Class> loadAll() throws ClassNotFoundException {
List<Class> classes = new ArrayList<Class>(classBytes.size());
for (String name : classBytes.keySet()) {
classes.add(loadClass(name));
}
return classes;
}
protected Class findClass(String className) throws ClassNotFoundException {
byte[] buf = classBytes.get(className);
if (buf != null) {
// clear the bytes in map -- we don't need it anymore
classBytes.put(className, null);
return defineClass(className, buf, 0, buf.length);
} else {
return super.findClass(className);
}
}
private static URL[] toURLs(String classPath) {
if (classPath == null) {
return new URL[0];
}
List<URL> list = new ArrayList<URL>();
StringTokenizer st = new StringTokenizer(classPath, File.pathSeparator);
while (st.hasMoreTokens()) {
String token = st.nextToken();
File file = new File(token);
if (file.exists()) {
try {
list.add(file.toURI().toURL());
} catch (MalformedURLException mue) {}
} else {
try {
list.add(new URL(token));
} catch (MalformedURLException mue) {}
}
}
URL[] res = new URL[list.size()];
list.toArray(res);
return res;
}
}
Explanations:
In order to represent a Java source file in memory instead of disk, I defined a StringInputBuffer class in the MemoryJavaFileManager.java.
To save the compiled .class files in memory, I implemented a class MemoryJavaFileManager. The main idea is to override the function getJavaFileForOutput() to store bytecodes into a map.
To load the bytecodes in memory, I have to implement a customized classloader MemoryClassLoader, which reads bytecodes in the map and turn them into classes.
Here is a unite test.
package me.soulmachine.compiler;
import org.junit.Test;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import static org.junit.Assert.assertEquals;
public class MemoryJavaCompilerTest {
private final static MemoryJavaCompiler compiler = new MemoryJavaCompiler();
#Test public void compileStaticMethodTest()
throws ClassNotFoundException, InvocationTargetException, IllegalAccessException {
final String source = "public final class Solution {\n"
+ "public static String greeting(String name) {\n"
+ "\treturn \"Hello \" + name;\n" + "}\n}\n";
final Method greeting = compiler.compileStaticMethod("greeting", "Solution", source);
final Object result = greeting.invoke(null, "soulmachine");
assertEquals("Hello soulmachine", result.toString());
}
}
Reference
JavaCompiler.java from Cloudera Morphlines
How to create an object from a string in Java (how to eval a string)?
InMemoryJavaCompiler
Java-Runtime-Compiler
动态的Java - 无废话JavaCompilerAPI中文指南
Hi i am trying to use junit and it does not work s well.
Here is my code.
package safe;
import java.lang.reflect.*;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import safe.SafetyException;
public class SafetyInspector {
public static boolean isSafe(Class<?> clazz) throws SafetyException{
if (clazz.equals(Object.class)) return true;
if (clazz == null ) {
throw new SafetyException();
}
Field fields[] = clazz.getDeclaredFields();
for(Field f: fields){
f.setAccessible(true);
int mod = f.getModifiers();
if (Modifier.isFinal(mod)){
continue;
}
else if (Modifier.isPrivate(mod)){
Class<?> typeArray[] = new Class<?>[1] ;
typeArray[0] = f.getType();
try {
Method mSet = clazz.getMethod("set" + f.getName().substring(0, 0).toUpperCase() + f.getName().substring(1),typeArray );
int modMet = mSet.getModifiers();
if(!Modifier.isPublic(modMet)) return false;
if(!mSet.getReturnType().equals(void.class)) return false;
}
catch (SecurityException e) {
throw new SafetyException();
}
catch (NoSuchMethodException e) {
return false;
}
try {
Class<?> typeArray2[] = new Class<?>[1] ;
Method mGet = clazz.getMethod("get" + f.getName().substring(0, 0).toUpperCase() + f.getName().substring(1),typeArray2);
int modMet2 = mGet.getModifiers();
if(!Modifier.isPublic(modMet2)) return false;
if(!mGet.getReturnType().equals(f.getType())) return false;
}
catch (SecurityException e) {
throw new SafetyException() ;
}
catch (NoSuchMethodException e) {
return false;
}
}
}
return isSafe(clazz.getSuperclass());
}
public static void sort(List<Class<?>> classes) throws SafetyException{
for (int i = 1; i < classes.size(); i++) {
for (int j = 0; j < classes.size() - i; j++) {
if (compare(classes.get(j), classes.get(j + 1)) > 0) {
swap(classes, j);
}
}
}
}
public static void reset(Object object) throws SafetyException{
Class c = object.getClass();
Field fields[] = c.getDeclaredFields();
for(Field f :fields ){
if (!isSafe(f.getClass()))
{
f.setAccessible(true);
try{
if(!f.getClass().isPrimitive()){
}
else if(f.getClass().equals(boolean.class)){
f.setBoolean(object, false);
}
else{
f.set(object, 0);
}
}
catch(Exception e)
{
throw new SafetyException();
}
}
}
}
private static int compare(Class<?> o1, Class<?> o2) throws SafetyException {
Field[] fields1 = o1.getDeclaredFields();
int count1 = 0;
for (Field f : fields1){
if (isSafe(f.getClass())) count1++;
}
Field[] fields2 = o2.getDeclaredFields();
int count2 = 0;
for (Field f : fields2){
if (isSafe(f.getClass())) count2++;
}
if (count1 == count2)
return o1.getName().compareTo(o2.getName());
else return count1- count2;
}
private static void swap(List<Class<?>> list, int j) {
Class<?> temp = list.get(j);
list.set(j, list.get(j+1));
list.set(j + 1, temp);
}
};
and here is the code junit test that they gave me.
package test;
import static org.junit.Assert.assertEquals;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import org.junit.Test;
import safe.SafetyException;
import safe.SafetyInspector;
public class SafetyInspectorTest {
#Test
public void testIsSafeEmployee() throws SafetyException {
assertEquals(false, SafetyInspector.isSafe(Employee.class));
}
#Test
public void testResetEmployee() throws SafetyException {
Employee e = new Employee(123,3000);
SafetyInspector.reset(e);
assertEquals(0, e.id);
assertEquals(3000, e.getSalary());
}
#Test
public void testSort() throws SafetyException {
List<Class<?>> sortedClasses = new LinkedList<Class<?>>();
sortedClasses.add(Employee.class);
List<Class<?>> classes = new LinkedList<Class<?>>(sortedClasses);
Collections.shuffle(classes);
SafetyInspector.sort(classes);
assertEquals(sortedClasses, classes);
}
}
and when I run the safetyInspectorTest as a junitTESTCLASS i get an initialization error. I work with eclipse if it helps and I put Junit as a library of the project.
An initialization error in JUnit is generally caused by a bad classpath. See this related question which also suffered from initialization error:
Eclipse JUnit - possible causes of seeing "initializationError" in Eclipse window
The most likely cause is as that question addressed, you are using a version of JUnit 4 which requires the hamcrest jar to be added. Instead of adding the junit and hamcrest jars you should be able to add the JUnit 4 library on your project's Java Build Path.
Your imports largely look benign but you should confirm safe.SafetyException is on your classpath.
Finally, the initialization error could be caused by a static initialization failure in code that loads before your test runs. The code you've posted looks safe but SafetyException class could possibly have an initialization block to check.