diff --git a/Java/src/main/java/org/ciyam/at/AtLogger.java b/Java/src/main/java/org/ciyam/at/AtLogger.java new file mode 100644 index 0000000..d8a0f41 --- /dev/null +++ b/Java/src/main/java/org/ciyam/at/AtLogger.java @@ -0,0 +1,11 @@ +package org.ciyam.at; + +public interface AtLogger { + + void error(final String message); + + void debug(final String message); + + void echo(final String message); + +} diff --git a/Java/src/main/java/org/ciyam/at/AtLoggerFactory.java b/Java/src/main/java/org/ciyam/at/AtLoggerFactory.java new file mode 100644 index 0000000..2a07fa2 --- /dev/null +++ b/Java/src/main/java/org/ciyam/at/AtLoggerFactory.java @@ -0,0 +1,7 @@ +package org.ciyam.at; + +public interface AtLoggerFactory { + + AtLogger create(final Class loggerName); + +} diff --git a/Java/src/main/java/org/ciyam/at/LoggerInterface.java b/Java/src/main/java/org/ciyam/at/LoggerInterface.java deleted file mode 100644 index 501493f..0000000 --- a/Java/src/main/java/org/ciyam/at/LoggerInterface.java +++ /dev/null @@ -1,11 +0,0 @@ -package org.ciyam.at; - -public interface LoggerInterface { - - public void error(String message); - - public void debug(String message); - - public void echo(String message); - -} diff --git a/Java/src/main/java/org/ciyam/at/MachineState.java b/Java/src/main/java/org/ciyam/at/MachineState.java index 723ff9a..7d57c95 100644 --- a/Java/src/main/java/org/ciyam/at/MachineState.java +++ b/Java/src/main/java/org/ciyam/at/MachineState.java @@ -126,7 +126,8 @@ public class MachineState { private boolean isFirstOpCodeAfterSleeping; private API api; - private LoggerInterface logger; + private AtLoggerFactory loggerFactory; + private AtLogger logger; // NOTE: These are package-scope to allow easy access/operations in Opcode/FunctionCode. /* package */ ByteBuffer codeByteBuffer; @@ -137,7 +138,7 @@ public class MachineState { // Constructors /** For internal use when recreating a machine state */ - private MachineState(API api, LoggerInterface logger, byte[] headerBytes) { + private MachineState(byte[] headerBytes, API api, AtLoggerFactory loggerFactory) { if (headerBytes.length != HEADER_LENGTH) throw new IllegalArgumentException("headerBytes length " + headerBytes.length + " incorrect, expected " + HEADER_LENGTH); @@ -190,12 +191,13 @@ public class MachineState { this.currentBalance = 0; this.previousBalance = 0; this.steps = 0; - this.logger = logger; + this.loggerFactory = loggerFactory; + this.logger = loggerFactory.create(MachineState.class); } /** For creating a new machine state */ - public MachineState(API api, byte[] creationBytes) { - this(api, null, Arrays.copyOfRange(creationBytes, 0, HEADER_LENGTH)); + public MachineState(API api, AtLoggerFactory loggerFactory, byte[] creationBytes) { + this(Arrays.copyOfRange(creationBytes, 0, HEADER_LENGTH), api, loggerFactory); int expectedLength = HEADER_LENGTH + this.numCodePages * this.constants.CODE_PAGE_SIZE + this.numDataPages * this.constants.DATA_PAGE_SIZE; if (creationBytes.length != expectedLength) @@ -210,8 +212,8 @@ public class MachineState { } /** For creating a new machine state - used in tests */ - public MachineState(API api, LoggerInterface logger, byte[] headerBytes, byte[] codeBytes, byte[] dataBytes) { - this(api, logger, headerBytes); + public MachineState(API api, AtLoggerFactory loggerFactory, byte[] headerBytes, byte[] codeBytes, byte[] dataBytes) { + this(headerBytes, api, loggerFactory); if (codeBytes.length > this.numCodePages * this.constants.CODE_PAGE_SIZE) throw new IllegalArgumentException("Number of code pages too small to hold code bytes"); @@ -342,7 +344,11 @@ public class MachineState { return this.api; } - public LoggerInterface getLogger() { + public AtLoggerFactory getLoggerFactory() { + return this.loggerFactory; + } + + /* package */ AtLogger getLogger() { return this.logger; } @@ -516,13 +522,13 @@ public class MachineState { } /** For restoring a previously serialized machine state */ - public static MachineState fromBytes(API api, LoggerInterface logger, byte[] bytes, byte[] codeBytes) { + public static MachineState fromBytes(API api, AtLoggerFactory loggerFactory, byte[] bytes, byte[] codeBytes) { ByteBuffer byteBuffer = ByteBuffer.wrap(bytes); byte[] headerBytes = new byte[HEADER_LENGTH]; byteBuffer.get(headerBytes); - MachineState state = new MachineState(api, logger, headerBytes); + MachineState state = new MachineState(headerBytes, api, loggerFactory); if (codeBytes.length != state.codeByteBuffer.capacity()) throw new IllegalStateException("Passed codeBytes does not match length in header"); diff --git a/Java/src/test/java/org/ciyam/at/MiscTests.java b/Java/src/test/java/org/ciyam/at/MiscTests.java index 11cfa29..8a3175d 100644 --- a/Java/src/test/java/org/ciyam/at/MiscTests.java +++ b/Java/src/test/java/org/ciyam/at/MiscTests.java @@ -62,7 +62,7 @@ public class MiscTests extends ExecutableTest { byte[] codeBytes = codeByteBuffer.array(); byte[] dataBytes = new byte[0]; - state = new MachineState(api, logger, headerBytes, codeBytes, dataBytes); + state = new MachineState(api, loggerFactory, headerBytes, codeBytes, dataBytes); assertTrue(state.isFrozen()); assertEquals((Long) (minActivationAmount - 1L), state.getFrozenBalance()); diff --git a/Java/src/test/java/org/ciyam/at/SerializationTests.java b/Java/src/test/java/org/ciyam/at/SerializationTests.java index fe644f8..d12b133 100644 --- a/Java/src/test/java/org/ciyam/at/SerializationTests.java +++ b/Java/src/test/java/org/ciyam/at/SerializationTests.java @@ -102,12 +102,12 @@ public class SerializationTests extends ExecutableTest { byte[] codeBytes = codeByteBuffer.array(); byte[] dataBytes = dataByteBuffer.array(); - state = new MachineState(api, logger, headerBytes, codeBytes, dataBytes); + state = new MachineState(api, loggerFactory, headerBytes, codeBytes, dataBytes); packedState = state.toBytes(); byte[] creationBytes = MachineState.toCreationBytes(TestUtils.VERSION, codeBytes, dataBytes, TestUtils.NUM_CALL_STACK_PAGES, TestUtils.NUM_USER_STACK_PAGES, TestUtils.MIN_ACTIVATION_AMOUNT); - MachineState restoredState = new MachineState(api, creationBytes); + MachineState restoredState = new MachineState(api, loggerFactory, creationBytes); byte[] packedRestoredSate = restoredState.toBytes(); assertTrue(Arrays.equals(packedState, packedRestoredSate)); @@ -118,14 +118,14 @@ public class SerializationTests extends ExecutableTest { byte[] codeBytes = codeByteBuffer.array(); byte[] dataBytes = new byte[0]; - state = new MachineState(api, logger, headerBytes, codeBytes, dataBytes); + state = new MachineState(api, loggerFactory, headerBytes, codeBytes, dataBytes); return executeAndCheck(state); } private byte[] continueSimulation(byte[] savedState) { byte[] codeBytes = codeByteBuffer.array(); - state = MachineState.fromBytes(api, logger, savedState, codeBytes); + state = MachineState.fromBytes(api, loggerFactory, savedState, codeBytes); // Pretend we're on next block api.bumpCurrentBlockHeight(); @@ -141,7 +141,7 @@ public class SerializationTests extends ExecutableTest { byte[] codeBytes = state.getCodeBytes(); // Rebuild new MachineState using fetched state & bytes - MachineState restoredState = MachineState.fromBytes(api, logger, stateBytes, codeBytes); + MachineState restoredState = MachineState.fromBytes(api, loggerFactory, stateBytes, codeBytes); // Extract rebuilt state and code bytes byte[] restoredStateBytes = restoredState.toBytes(); byte[] restoredCodeBytes = state.getCodeBytes(); diff --git a/Java/src/test/java/org/ciyam/at/test/ExecutableTest.java b/Java/src/test/java/org/ciyam/at/test/ExecutableTest.java index aea4b45..cc5bff8 100644 --- a/Java/src/test/java/org/ciyam/at/test/ExecutableTest.java +++ b/Java/src/test/java/org/ciyam/at/test/ExecutableTest.java @@ -14,7 +14,7 @@ public abstract class ExecutableTest { private static final int DATA_OFFSET = MachineState.HEADER_LENGTH; // code bytes are not present private static final int CALL_STACK_OFFSET = DATA_OFFSET + TestUtils.NUM_DATA_PAGES * MachineState.VALUE_SIZE; - public TestLogger logger; + public TestLoggerFactory loggerFactory; public TestAPI api; public MachineState state; public ByteBuffer codeByteBuffer; @@ -32,7 +32,7 @@ public abstract class ExecutableTest { @Before public void beforeTest() { - logger = new TestLogger(); + loggerFactory = new TestLoggerFactory(); api = new TestAPI(); codeByteBuffer = ByteBuffer.allocate(TestUtils.NUM_CODE_PAGES * MachineState.OPCODE_SIZE); dataByteBuffer = ByteBuffer.allocate(TestUtils.NUM_DATA_PAGES * MachineState.VALUE_SIZE); @@ -47,7 +47,7 @@ public abstract class ExecutableTest { codeByteBuffer = null; dataByteBuffer = null; api = null; - logger = null; + loggerFactory = null; } protected void execute(boolean onceOnly) { @@ -58,12 +58,12 @@ public abstract class ExecutableTest { if (packedState == null) { // First time System.out.println("First execution - deploying..."); - state = new MachineState(api, logger, headerBytes, codeBytes, dataBytes); + state = new MachineState(api, loggerFactory, headerBytes, codeBytes, dataBytes); packedState = state.toBytes(); } do { - state = MachineState.fromBytes(api, logger, packedState, codeBytes); + state = MachineState.fromBytes(api, loggerFactory, packedState, codeBytes); System.out.println("Starting execution round!"); System.out.println("Current block height: " + api.getCurrentBlockHeight()); diff --git a/Java/src/test/java/org/ciyam/at/test/TestLogger.java b/Java/src/test/java/org/ciyam/at/test/TestLogger.java index bec6121..01c624c 100644 --- a/Java/src/test/java/org/ciyam/at/test/TestLogger.java +++ b/Java/src/test/java/org/ciyam/at/test/TestLogger.java @@ -1,8 +1,9 @@ package org.ciyam.at.test; -import org.ciyam.at.LoggerInterface; +import org.ciyam.at.AtLogger; + +public class TestLogger implements AtLogger { -public class TestLogger implements LoggerInterface { @Override public void error(String message) { System.err.println("ERROR: " + message); diff --git a/Java/src/test/java/org/ciyam/at/test/TestLoggerFactory.java b/Java/src/test/java/org/ciyam/at/test/TestLoggerFactory.java new file mode 100644 index 0000000..18fa67f --- /dev/null +++ b/Java/src/test/java/org/ciyam/at/test/TestLoggerFactory.java @@ -0,0 +1,13 @@ +package org.ciyam.at.test; + +import org.ciyam.at.AtLogger; +import org.ciyam.at.AtLoggerFactory; + +public class TestLoggerFactory implements AtLoggerFactory { + + @Override + public AtLogger create(Class loggerName) { + return new TestLogger(); + } + +}