diff --git a/exts/jphp-httpserver-ext/api-docs/classes/php/http/HttpServer.md b/exts/jphp-httpserver-ext/api-docs/classes/php/http/HttpServer.md
index d43c900c4..0a46de6de 100644
--- a/exts/jphp-httpserver-ext/api-docs/classes/php/http/HttpServer.md
+++ b/exts/jphp-httpserver-ext/api-docs/classes/php/http/HttpServer.md
@@ -30,6 +30,7 @@ Class HttpServer
- `->`[`addHandler()`](#method-addhandler)
- `->`[`clearHandlers()`](#method-clearhandlers) - _Remove all handlers._
- `->`[`setRequestLogHandler()`](#method-setrequestloghandler)
+- `->`[`setErrorHandler()`](#method-seterrorhandler)
- `->`[`isRunning()`](#method-isrunning)
- `->`[`isFailed()`](#method-isfailed)
- `->`[`isStopped()`](#method-isstopped)
@@ -222,6 +223,15 @@ setRequestLogHandler([ callable|null $handler): void
---
+
+
+### setErrorHandler()
+```php
+setErrorHandler([ callable|null $handler): void
+```
+
+---
+
### isRunning()
diff --git a/exts/jphp-httpserver-ext/api-docs/classes/php/http/HttpServer.ru.md b/exts/jphp-httpserver-ext/api-docs/classes/php/http/HttpServer.ru.md
index 9dc933685..7510c3400 100644
--- a/exts/jphp-httpserver-ext/api-docs/classes/php/http/HttpServer.ru.md
+++ b/exts/jphp-httpserver-ext/api-docs/classes/php/http/HttpServer.ru.md
@@ -30,6 +30,7 @@ Class HttpServer
- `->`[`addHandler()`](#method-addhandler)
- `->`[`clearHandlers()`](#method-clearhandlers) - _Remove all handlers._
- `->`[`setRequestLogHandler()`](#method-setrequestloghandler)
+- `->`[`setErrorHandler()`](#method-seterrorhandler)
- `->`[`isRunning()`](#method-isrunning)
- `->`[`isFailed()`](#method-isfailed)
- `->`[`isStopped()`](#method-isstopped)
@@ -222,6 +223,15 @@ setRequestLogHandler([ callable|null $handler): void
---
+
+
+### setErrorHandler()
+```php
+setErrorHandler([ callable|null $handler): void
+```
+
+---
+
### isRunning()
diff --git a/exts/jphp-httpserver-ext/src/main/java/org/develnext/jphp/ext/httpserver/classes/PHttpServer.java b/exts/jphp-httpserver-ext/src/main/java/org/develnext/jphp/ext/httpserver/classes/PHttpServer.java
index 9b6bc0547..7d017e80b 100644
--- a/exts/jphp-httpserver-ext/src/main/java/org/develnext/jphp/ext/httpserver/classes/PHttpServer.java
+++ b/exts/jphp-httpserver-ext/src/main/java/org/develnext/jphp/ext/httpserver/classes/PHttpServer.java
@@ -1,5 +1,6 @@
package org.develnext.jphp.ext.httpserver.classes;
+import javax.servlet.RequestDispatcher;
import org.develnext.jphp.ext.httpserver.HttpServerExtension;
import org.eclipse.jetty.server.*;
import org.eclipse.jetty.server.handler.*;
@@ -442,6 +443,23 @@ public void setRequestLogHandler(Environment env, @Nullable Invoker invoker) {
}
}
+ @Signature
+ public void setErrorHandler(Environment env, @Nullable Invoker invoker) {
+ if (invoker == null) {
+ server.setErrorHandler(null);
+ } else {
+ ErrorHandler errorHandler = new ErrorHandler();
+
+ server.setErrorHandler(new ErrorHandler() {
+ @Override
+ public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException {
+ Throwable th = (Throwable)request.getAttribute(RequestDispatcher.ERROR_EXCEPTION);
+ invoker.callAny(th, new PHttpServerRequest(env, Request.getBaseRequest(request)), new PHttpServerResponse(env, response));
+ }
+ });
+ }
+ }
+
public static class InvokeHandler extends AbstractHandler {
private final Invoker invoker;
diff --git a/exts/jphp-httpserver-ext/src/main/resources/JPHP-INF/sdk/php/http/HttpServer.php b/exts/jphp-httpserver-ext/src/main/resources/JPHP-INF/sdk/php/http/HttpServer.php
index 2f11803c5..67e59740a 100644
--- a/exts/jphp-httpserver-ext/src/main/resources/JPHP-INF/sdk/php/http/HttpServer.php
+++ b/exts/jphp-httpserver-ext/src/main/resources/JPHP-INF/sdk/php/http/HttpServer.php
@@ -1,6 +1,8 @@
addVendorClassPath($vendor);
$exec->addPackageClassPath($event->package());
- $buildFileName = "{$event->package()->getName()}-{$event->package()->getVersion('last')}.jar";
+ $buildFileName = "{$event->package()->getName()}-{$event->package()->getVersion('last')}";
- if ($build['fileName']) {
- $buildFileName = $build['fileName'];
+ if ($build['file-name']) {
+ $buildFileName = $build['file-name'];
}
$buildDir = $event->package()->getConfigBuildPath();
Tasks::createDir("$buildDir");
- Tasks::createFile("$buildDir/$buildFileName");
+ Tasks::createFile("$buildDir/$buildFileName.jar");
- $zip = new ZipArchive("$buildDir/$buildFileName");
+ $zip = new ZipArchive("$buildDir/$buildFileName.jar");
$zip->open();
- Tasks::createDir("$buildDir/app");
+ Tasks::createDir("$buildDir/.app");
$metaInfServices = [];
@@ -91,7 +94,7 @@ function build(Event $event)
fs::scan($classPath, function ($filename) use ($zip, $classPath, &$metaInfServices, $buildDir) {
$name = fs::relativize($filename, $classPath);
- $file = "$buildDir/app/$name";
+ $file = "$buildDir/.app/$name";
Console::log("--> add file: {$classPath}/{$name}");
@@ -120,7 +123,7 @@ function build(Event $event)
if (str::startsWith($name, "META-INF/services/")) {
$metaInfServices[$name] = flow((array) $metaInfServices[$name], str::lines($stream->readFully()))->toArray();
} else {
- $file = "$buildDir/app/{$name}";
+ $file = "$buildDir/.app/{$name}";
//Console::log("--> add jar file: $name");
@@ -131,18 +134,18 @@ function build(Event $event)
}
}
- Tasks::cleanDir("$buildDir/app/JPHP-INF/sdk");
- Tasks::deleteFile("$buildDir/app/JPHP-INF/sdk");
+ Tasks::cleanDir("$buildDir/.app/JPHP-INF/sdk");
+ Tasks::deleteFile("$buildDir/.app/JPHP-INF/sdk");
- fs::delete("$buildDir/app/META-INF/manifest.mf");
- fs::delete("$buildDir/app/META-INF/Manifest.mf");
- fs::delete("$buildDir/app/META-INF/MANIFEST.MF");
+ fs::delete("$buildDir/.app/META-INF/manifest.mf");
+ fs::delete("$buildDir/.app/META-INF/Manifest.mf");
+ fs::delete("$buildDir/.app/META-INF/MANIFEST.MF");
if (!$launcher['disable-launcher']) {
Console::log("-> create jphp app launcher");
- Tasks::createDir("$buildDir/app/JPHP-INF/");
- Tasks::createDir("$buildDir/app/META-INF/");
+ Tasks::createDir("$buildDir/.app/JPHP-INF/");
+ Tasks::createDir("$buildDir/.app/META-INF/");
$includes = (array) $vendor->fetchPaths()['includes'];
@@ -152,14 +155,14 @@ function build(Event $event)
$launcher['bootstrap'] = arr::pop($includes);
}
- fs::formatAs("$buildDir/app/JPHP-INF/launcher.conf", [
+ fs::formatAs("$buildDir/.app/JPHP-INF/launcher.conf", [
'bootstrap.files' => flow($includes)->map(function ($one) { return "res://$one"; })->toString('|'),
'bootstrap.file' => $launcher['bootstrap'] ? "res://{$launcher['bootstrap']}" : 'res://JPHP-INF/.bootstrap.php'
], 'ini');
- Tasks::createFile("$buildDir/app/META-INF/MANIFEST.MF");
+ Tasks::createFile("$buildDir/.app/META-INF/MANIFEST.MF");
- Stream::putContents("$buildDir/app/META-INF/MANIFEST.MF", str::join([
+ Stream::putContents("$buildDir/.app/META-INF/MANIFEST.MF", str::join([
"Manifest-Version: 1.0",
"Created-By: jppm (JPHP Packager " . $event->packager()->getVersion() . ")",
"Main-Class: " . ($launcher['mainClass'] ?? 'php.runtime.launcher.Launcher'),
@@ -171,24 +174,65 @@ function build(Event $event)
}
foreach ($metaInfServices as $name => $lines) {
- fs::ensureParent("$buildDir/app/$name");
- Stream::putContents("$buildDir/app/$name", str::join($lines, "\n"));
+ fs::ensureParent("$buildDir/.app/$name");
+ Stream::putContents("$buildDir/.app/$name", str::join($lines, "\n"));
}
- fs::scan("$buildDir/app", function (File $file) use ($zip, $buildDir) {
+ fs::scan("$buildDir/.app", function (File $file) use ($zip, $buildDir) {
if ($file->isFile()) {
- $zip->addFile($file, fs::relativize($file, "$buildDir/app"));
+ $zip->addFile($file, fs::relativize($file, "$buildDir/.app"));
}
});
$zip->close();
- $time = Time::millis() - $time;
+ Tasks::deleteFile("$buildDir/.app");
- if (!$launcher['disable-launcher']) {
- Console::log("\n Use 'java -jar \"$buildDir/$buildFileName\"' to run the result app.");
+ foreach ($event->package()->getAny('app.assets', []) as $asset) {
+ Tasks::deleteFile("$buildDir/" . fs::name($asset));
+
+ if (fs::isDir($asset)) {
+ Tasks::copy($asset, "$buildDir/" . fs::name($asset));
+ } else {
+ Tasks::copy($asset, "$buildDir/");
+ }
+ }
+
+ switch (str::lower($event->package()->getAny('app.build.result'))) {
+ case 'tar':
+ Console::log("-> pack build dir to tar.gz archive ...");
+
+ $archFile = File::createTemp($buildFileName, ".tar.gz");
+ $archFile->deleteOnExit();
+
+ $tar = new TarArchive(new GzipOutputStream($archFile));
+ $tar->open();
+
+ fs::scan("$buildDir/", function ($file) use ($buildDir, $tar) {
+ Console::log("-> pack '{0}'", fs::relativize($file, $buildDir . "/"));
+ if (fs::isFile($file)) {
+ $tar->addFile($file, fs::relativize($file, $buildDir . "/"));
+ } else {
+ $tar->addEmptyEntry(new TarArchiveEntry(fs::relativize($file, $buildDir . "/")));
+ }
+ });
+
+ $tar->close();
+
+ Tasks::cleanDir("$buildDir/");
+ Tasks::copy($archFile, "$buildDir/");
+ fs::rename("$buildDir/" . fs::name($archFile), "{$buildFileName}.tar.gz");
+
+ break;
+
+ default:
+ if (!$launcher['disable-launcher']) {
+ Console::log("\n Use 'java -jar \"$buildDir/$buildFileName.jar\"' to run the result app.");
+ }
}
+ $time = Time::millis() - $time;
+
Console::log("\n-----");
Console::log("Building time: {0} sec.", round($time / 1000, 2));
Console::log("Building is SUCCESSFUL. :)");
diff --git a/packager/package.php.yml b/packager/package.php.yml
index 0b78babb3..b41d31d89 100644
--- a/packager/package.php.yml
+++ b/packager/package.php.yml
@@ -1,5 +1,5 @@
name: jppm
-version: 0.2.7
+version: 0.2.8
plugins: [GitHub, Hub, Doc]
@@ -14,7 +14,8 @@ github:
> JPHP Package Manager v%version%
**What's new**
- + Improve the `tasks` section in package yml.
+ + Improve App Plugin.
+ + Improve internal api.
**Downloads**
+ For Windows: [JPPM Windows Installer](%github.address%/releases/download/jppm-%version%/jppm-setup-%version%.exe)
diff --git a/packager/src-php/Tasks.php b/packager/src-php/Tasks.php
index 88d0dd870..9129e7aae 100644
--- a/packager/src-php/Tasks.php
+++ b/packager/src-php/Tasks.php
@@ -20,6 +20,43 @@ static function run(string $name, array $args = [], ...$flags)
$app->invokeTask($name, $args, ...arr::combine($flags, $flags));
}
+ /**
+ * Copy file or directory.
+ *
+ * @param string $path
+ * @param string $intoDir
+ * @param bool $ignoreErrs
+ */
+ static function copy(string $path, string $intoDir, bool $ignoreErrs = false)
+ {
+ if (fs::isFile($path)) {
+ if (fs::copy($path, "$intoDir/" . fs::name($path), 1024 * 128) < 0) {
+ Console::error("Failed to copy file '{0}' into dir '{1}'", $path, $intoDir);
+ if (!$ignoreErrs) {
+ exit(-1);
+ }
+ }
+ } else if (fs::isDir($path)) {
+ fs::scan($path, function ($file) use ($path, $intoDir, $ignoreErrs) {
+ $name = fs::relativize($file, $path);
+
+ if (fs::isDir($file)) {
+ fs::makeDir("$intoDir/$name");
+ return;
+ }
+
+ fs::ensureParent("$intoDir/$name");
+
+ if (fs::copy($file, "$intoDir/$name", 1024 * 128) < 0) {
+ Console::error("Failed to copy file '{0}' into dir '{1}'", $path, $intoDir);
+ if (!$ignoreErrs) {
+ exit(-1);
+ }
+ }
+ });
+ }
+ }
+
/**
* @param string $path
* @param string $content
@@ -35,7 +72,7 @@ static function createFile(string $path, string $content = '', bool $ignoreErrs
Stream::putContents($path, $content);
return true;
} catch (IOException $e) {
- Console::error("Failed to create file '{0}', cause = {0}", $path, $e->getMessage());
+ Console::error("Failed to create file '{0}', cause = {1}", $path, $e->getMessage());
if (!$ignoreErrs) {
exit(-1);
}