Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ We welcoming to contributions this project 💪
## Not currently supported
Sorry, I do not have enough time (T_T)

- Inner classes
- Annotations
- Extends other class
- Implements
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"description": "JVM emulator by PHP",
"type": "library",
"license": "MIT",
"version": "0.0.3-dev",
"version": "0.0.3.1-dev",
"authors": [
{
"name": "memory"
Expand Down
10 changes: 9 additions & 1 deletion src/Core/JVM/Invoker/Invokable.php
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,13 @@ public function call(string $name, ...$arguments)
->getConstantPool()
->getEntries();

if ($name === '<init>' && $this->javaClassInvoker->getJavaClass()->hasParentClass()) {
array_unshift(
$arguments,
$this->javaClassInvoker->getJavaClass()->getParentClass()
);
}

// Find same method
$convertedPassedArguments = Formatter::buildArgumentsSignature(
array_map(
Expand All @@ -80,11 +87,12 @@ function ($argument) {
);

$method = null;

// the special method
foreach ($methodReferences as $methodReference) {
$methodSignature = Formatter::buildArgumentsSignature(
Formatter::parseSignature($constantPool[$methodReference->getDescriptorIndex()]->getString())['arguments']
);

if ($methodSignature === $convertedPassedArguments) {
$method = $methodReference;
break;
Expand Down
43 changes: 42 additions & 1 deletion src/Core/JavaClass.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
use PHPJava\Core\JVM\ConstantPool;
use PHPJava\Core\JVM\Validations\MagicByte;
use PHPJava\Exceptions\ValidatorException;
use PHPJava\Kernel\Attributes\AttributeInterface;
use PHPJava\Kernel\Attributes\InnerClassesAttribute;
use PHPJava\Kernel\Maps\AccessFlag;
use PHPJava\Kernel\Structures\_Utf8;
use PHPJava\Utilities\Formatter;
Expand Down Expand Up @@ -62,6 +64,10 @@ class JavaClass
*/
private $invoker;

private $innerClasses = [];

private $parentClass;

/**
* JavaClass constructor.
* @param JavaClassReader $reader
Expand Down Expand Up @@ -94,6 +100,7 @@ public function __construct(JavaClassReader $reader)
$this->thisClass = $reader->getBinaryReader()->readUnsignedShort();

$constantPoolEntries = $this->constantPool->getEntries();

$this->className = $constantPoolEntries[$constantPoolEntries[$this->thisClass]->getClassIndex()];

// read super class
Expand Down Expand Up @@ -127,14 +134,32 @@ public function __construct(JavaClassReader $reader)
$this->constantPool
);

foreach ($this->activeAttributes->getEntries() as $entry) {
if ($entry->getAttributeData() instanceof InnerClassesAttribute) {
$this->innerClasses = array_merge(
$this->innerClasses,
$entry->getAttributeData()->getClasses()
);
}
}

$this->invoker = new JavaClassInvoker($this);
}

public function getClassName(): string
public function getClassName(bool $shortName = false): string
{
if ($shortName === true) {
$split = explode('$', $this->className->getString());
return $split[count($split) - 1];
}
return $this->className->getString();
}

public function getInnerClasses(): array
{
return $this->innerClasses;
}

public function getFields(): array
{
return $this->activeFields->getEntries();
Expand All @@ -156,6 +181,22 @@ public function appendDebug($log)
return $this;
}

public function hasParentClass(): bool
{
return isset($this->parentClass);
}

public function setParentClass(JavaClass $class): self
{
$this->parentClass = $class;
return $this;
}

public function getParentClass(): JavaClass
{
return $this->parentClass;
}

public function debug(): void
{
$cpInfo = $this->getConstantPool()->getEntries();
Expand Down
5 changes: 3 additions & 2 deletions src/Core/JavaClassInvoker.php
Original file line number Diff line number Diff line change
Expand Up @@ -93,17 +93,18 @@ public function __construct(JavaClass $javaClass)
}

/**
* @param array $arguments
* @return JavaClassInvoker
*/
public function construct(): self
public function construct(...$arguments): self
{
$this->dynamicAccessor = new DynamicAccessor(
$this,
$this->dynamicMethods
);

if (isset($this->dynamicMethods['<init>'])) {
$this->getDynamic()->getMethods()->call('<init>');
$this->getDynamic()->getMethods()->call('<init>', ...$arguments);
}

return $this;
Expand Down
18 changes: 10 additions & 8 deletions src/Kernel/Attributes/InnerClassesAttribute.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
namespace PHPJava\Kernel\Attributes;

use PHPJava\Exceptions\NotImplementedException;
use PHPJava\Kernel\Structures\_Classes;
use PHPJava\Utilities\BinaryTool;

final class InnerClassesAttribute implements AttributeInterface
Expand All @@ -10,20 +11,21 @@ final class InnerClassesAttribute implements AttributeInterface
use \PHPJava\Kernel\Core\ConstantPool;

private $numberOfClasses = 0;
private $classes = array();
private $classes = [];

public function execute(): void
{
$this->numberOfClasses = $this->readUnsignedShort();
for ($i = 0; $i < $this->numberOfClasses; $i++) {
$thises[$i] = new JavaStructureClasses($this);
$thises[$i]->setInnerClassInfoIndex($this->readUnsignedShort());
$thises[$i]->setOuterClassInfoIndex($this->readUnsignedShort());
$thises[$i]->setInnerNameIndex($this->readUnsignedShort());
$thises[$i]->setInnerClassAccessFlag($this->readUnsignedShort());
$this->classes[$i] = new _Classes($this->reader);
$this->classes[$i]->setInnerClassInfoIndex($this->readUnsignedShort());
$this->classes[$i]->setOuterClassInfoIndex($this->readUnsignedShort());
$this->classes[$i]->setInnerNameIndex($this->readUnsignedShort());
$this->classes[$i]->setInnerClassAccessFlag($this->readUnsignedShort());
}
}
public function getClasses()
public function getClasses(): array
{
return $thises;
return $this->classes;
}
}
14 changes: 13 additions & 1 deletion src/Kernel/Mnemonics/_invokespecial.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ public function execute(): void
krsort($arguments);

$methodName = $cpInfo[$nameAndTypeIndex->getNameIndex()]->getString();

if ($this->javaClassInvoker->isInvoked($methodName, $signature)) {
return;
}
Expand All @@ -38,7 +39,18 @@ public function execute(): void
->addToSpecialInvokedList($methodName, $signature);

if ($invokerClass instanceof JavaClass) {
$result = $invokerClass->getInvoker()->getDynamic()->getMethods()
if ($invokerClass->getInvoker()->isInvoked($methodName, $signature)) {
return;
}

$invokerClass
->getInvoker()
->addToSpecialInvokedList($methodName, $signature);

$result = $invokerClass
->getInvoker()
->getDynamic()
->getMethods()
->call(
$methodName,
...$arguments
Expand Down
10 changes: 3 additions & 7 deletions src/Kernel/Mnemonics/_new.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,13 @@ public function execute(): void
return;
}

[$resourceType, $classObject] = ClassResolver::resolve($className);
[$resourceType, $classObject] = ClassResolver::resolve($className, $this->javaClass);
if ($resourceType === ClassResolver::RESOLVED_TYPE_CLASS) {
/**
* @var \PHPJava\Core\JavaClass $classObject
*/
$this->pushStack(
$classObject
->getInvoker()
->construct()
->getJavaClass()
);

$this->pushStack($classObject->getInvoker()->construct()->getJavaClass());
return;
}
$this->pushStack(new $classObject());
Expand Down
8 changes: 6 additions & 2 deletions src/Utilities/ClassResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class ClassResolver
private static $resolves = [];
private static $resolvedPaths = [];

public static function resolve($javaPath): array
public static function resolve(string $javaPath, JavaClass $class = null): array
{
$namespaces = explode('.', str_replace('/', '.', $javaPath));
$buildClassPath = [];
Expand All @@ -39,9 +39,13 @@ public static function resolve($javaPath): array
return static::$resolvedPaths[$key];
}
if (is_file($path)) {
$initiatedClass = new JavaClass(new JavaClassReader($path));
if (strpos($relativePath, '$') !== false && $class !== null) {
$initiatedClass->setParentClass($class);
}
return $resolvedPaths[] = [
static::RESOLVED_TYPE_CLASS,
new JavaClass(new JavaClassReader($path)),
$initiatedClass,
];
}
break;
Expand Down
11 changes: 11 additions & 0 deletions src/Utilities/TypeResolver.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<?php
namespace PHPJava\Utilities;

use PHPJava\Core\JavaClass;
use PHPJava\Exceptions\TypeException;

class TypeResolver
Expand Down Expand Up @@ -76,6 +77,16 @@ public static function convertPHPtoJava($arguments, $defaultJavaArgumentType = '
$firstParameter['deep_array'] += $deepArray;
return $firstParameter;
}
if ($phpType === 'object') {
if ($arguments instanceof JavaClass) {
return [
'type' => 'class',
'class_name' => $arguments->getClassName(false),
'deep_array' => $deepArray,
];
}
throw new TypeException(get_class($arguments) . ' does not supported to convert to Java\'s argument.');
}
$resolveType = static::SIGNATURE_MAP[static::PHP_TYPE_MAP[$phpType][0]] ?? null;
if ($resolveType === 'class') {
return [
Expand Down
28 changes: 28 additions & 0 deletions tests/InnerClassTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php
namespace PHPJava\Tests;

use PHPUnit\Framework\TestCase;

class InnerClassTest extends Base
{
protected $fixtures = [
'InnerClassTest',
];

public function testCallMainHavingStringArguments()
{
ob_start();
// call main
$this->initiatedJavaClasses['InnerClassTest']
->getInvoker()
->getStatic()
->getMethods()
->call(
'main',
["Hello", "World"]
);
$result = ob_get_clean();

$this->assertEquals("Hello World", $result);
}
}
20 changes: 20 additions & 0 deletions tests/fixtures/java/InnerClassTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
class InnerClassTest
{
public static void main(String[] args)
{
(new InnerClassTest()).callInnerClass(args[0], args[1]);
}

public void callInnerClass(String a, String b)
{
System.out.print((new InnerClassTestInnerClass()).helloWorld(a, b));
}

public class InnerClassTestInnerClass
{
public String helloWorld(String a, String b)
{
return a + " " + b;
}
}
}