summaryrefslogtreecommitdiff
path: root/packages
diff options
context:
space:
mode:
authormichael <michael@3ad0048d-3df7-0310-abae-a5850022a9f2>2010-06-03 15:09:29 +0000
committermichael <michael@3ad0048d-3df7-0310-abae-a5850022a9f2>2010-06-03 15:09:29 +0000
commit34240c1abe68f2d3de9fd8ffdd8aa3ecf1a31b07 (patch)
tree44ad9bc3cc069868e958c21b0ddb5dffb41c4d13 /packages
parent8a7658a19dc279f5a0581522a9a80d5565682e49 (diff)
downloadfpc-34240c1abe68f2d3de9fd8ffdd8aa3ecf1a31b07.tar.gz
* Added JSON-RPC functionality
git-svn-id: http://svn.freepascal.org/svn/fpc/trunk@15360 3ad0048d-3df7-0310-abae-a5850022a9f2
Diffstat (limited to 'packages')
-rw-r--r--packages/fcl-web/src/jsonrpc/Makefile2455
-rw-r--r--packages/fcl-web/src/jsonrpc/Makefile.fpc26
-rw-r--r--packages/fcl-web/src/jsonrpc/fpextdirect.pp416
-rw-r--r--packages/fcl-web/src/jsonrpc/fpjsonrpc.pp1230
-rw-r--r--packages/fcl-web/src/jsonrpc/readme.txt189
-rw-r--r--packages/fcl-web/src/jsonrpc/webjsonrpc.pp309
6 files changed, 4625 insertions, 0 deletions
diff --git a/packages/fcl-web/src/jsonrpc/Makefile b/packages/fcl-web/src/jsonrpc/Makefile
new file mode 100644
index 0000000000..493640cad8
--- /dev/null
+++ b/packages/fcl-web/src/jsonrpc/Makefile
@@ -0,0 +1,2455 @@
+#
+# Don't edit, this file is generated by FPCMake Version 2.0.0 [2009/11/05]
+#
+default: all
+MAKEFILETARGETS=i386-linux i386-go32v2 i386-win32 i386-os2 i386-freebsd i386-beos i386-haiku i386-netbsd i386-solaris i386-qnx i386-netware i386-openbsd i386-wdosx i386-darwin i386-emx i386-watcom i386-netwlibc i386-wince i386-embedded i386-symbian m68k-linux m68k-freebsd m68k-netbsd m68k-amiga m68k-atari m68k-openbsd m68k-palmos m68k-embedded powerpc-linux powerpc-netbsd powerpc-amiga powerpc-macos powerpc-darwin powerpc-morphos powerpc-embedded sparc-linux sparc-netbsd sparc-solaris sparc-embedded x86_64-linux x86_64-freebsd x86_64-darwin x86_64-win64 x86_64-embedded arm-linux arm-palmos arm-darwin arm-wince arm-gba arm-nds arm-embedded arm-symbian powerpc64-linux powerpc64-darwin powerpc64-embedded avr-embedded armeb-linux armeb-embedded
+BSDs = freebsd netbsd openbsd darwin
+UNIXs = linux $(BSDs) solaris qnx
+LIMIT83fs = go32v2 os2 emx watcom
+OSNeedsComspecToRunBatch = go32v2 watcom
+FORCE:
+.PHONY: FORCE
+override PATH:=$(patsubst %/,%,$(subst \,/,$(PATH)))
+ifneq ($(findstring darwin,$(OSTYPE)),)
+inUnix=1 #darwin
+SEARCHPATH:=$(filter-out .,$(subst :, ,$(PATH)))
+else
+ifeq ($(findstring ;,$(PATH)),)
+inUnix=1
+SEARCHPATH:=$(filter-out .,$(subst :, ,$(PATH)))
+else
+SEARCHPATH:=$(subst ;, ,$(PATH))
+endif
+endif
+SEARCHPATH+=$(patsubst %/,%,$(subst \,/,$(dir $(MAKE))))
+PWD:=$(strip $(wildcard $(addsuffix /pwd.exe,$(SEARCHPATH))))
+ifeq ($(PWD),)
+PWD:=$(strip $(wildcard $(addsuffix /pwd,$(SEARCHPATH))))
+ifeq ($(PWD),)
+$(error You need the GNU utils package to use this Makefile)
+else
+PWD:=$(firstword $(PWD))
+SRCEXEEXT=
+endif
+else
+PWD:=$(firstword $(PWD))
+SRCEXEEXT=.exe
+endif
+ifndef inUnix
+ifeq ($(OS),Windows_NT)
+inWinNT=1
+else
+ifdef OS2_SHELL
+inOS2=1
+endif
+endif
+else
+ifneq ($(findstring cygdrive,$(PATH)),)
+inCygWin=1
+endif
+endif
+ifdef inUnix
+SRCBATCHEXT=.sh
+else
+ifdef inOS2
+SRCBATCHEXT=.cmd
+else
+SRCBATCHEXT=.bat
+endif
+endif
+ifdef COMSPEC
+ifneq ($(findstring $(OS_SOURCE),$(OSNeedsComspecToRunBatch)),)
+RUNBATCH=$(COMSPEC) /C
+endif
+endif
+ifdef inUnix
+PATHSEP=/
+else
+PATHSEP:=$(subst /,\,/)
+ifdef inCygWin
+PATHSEP=/
+endif
+endif
+ifdef PWD
+BASEDIR:=$(subst \,/,$(shell $(PWD)))
+ifdef inCygWin
+ifneq ($(findstring /cygdrive/,$(BASEDIR)),)
+BASENODIR:=$(patsubst /cygdrive%,%,$(BASEDIR))
+BASEDRIVE:=$(firstword $(subst /, ,$(BASENODIR)))
+BASEDIR:=$(subst /cygdrive/$(BASEDRIVE)/,$(BASEDRIVE):/,$(BASEDIR))
+endif
+endif
+else
+BASEDIR=.
+endif
+ifdef inOS2
+ifndef ECHO
+ECHO:=$(strip $(wildcard $(addsuffix /gecho$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(ECHO),)
+ECHO:=$(strip $(wildcard $(addsuffix /echo$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(ECHO),)
+ECHO=echo
+else
+ECHO:=$(firstword $(ECHO))
+endif
+else
+ECHO:=$(firstword $(ECHO))
+endif
+endif
+export ECHO
+endif
+override DEFAULT_FPCDIR=../../../..
+ifndef FPC
+ifdef PP
+FPC=$(PP)
+endif
+endif
+ifndef FPC
+FPCPROG:=$(strip $(wildcard $(addsuffix /fpc$(SRCEXEEXT),$(SEARCHPATH))))
+ifneq ($(FPCPROG),)
+FPCPROG:=$(firstword $(FPCPROG))
+ifneq ($(CPU_TARGET),)
+FPC:=$(shell $(FPCPROG) -P$(CPU_TARGET) -PB)
+else
+FPC:=$(shell $(FPCPROG) -PB)
+endif
+ifneq ($(findstring Error,$(FPC)),)
+override FPC=$(firstword $(strip $(wildcard $(addsuffix /ppc386$(SRCEXEEXT),$(SEARCHPATH)))))
+else
+ifeq ($(strip $(wildcard $(FPC))),)
+FPC:=$(firstword $(FPCPROG))
+endif
+endif
+else
+override FPC=$(firstword $(strip $(wildcard $(addsuffix /ppc386$(SRCEXEEXT),$(SEARCHPATH)))))
+endif
+endif
+override FPC:=$(subst $(SRCEXEEXT),,$(FPC))
+override FPC:=$(subst \,/,$(FPC))$(SRCEXEEXT)
+FOUNDFPC:=$(strip $(wildcard $(FPC)))
+ifeq ($(FOUNDFPC),)
+FOUNDFPC=$(strip $(wildcard $(addsuffix /$(FPC),$(SEARCHPATH))))
+ifeq ($(FOUNDFPC),)
+$(error Compiler $(FPC) not found)
+endif
+endif
+ifndef FPC_COMPILERINFO
+FPC_COMPILERINFO:=$(shell $(FPC) -iVSPTPSOTO)
+endif
+ifndef FPC_VERSION
+FPC_VERSION:=$(word 1,$(FPC_COMPILERINFO))
+endif
+export FPC FPC_VERSION FPC_COMPILERINFO
+unexport CHECKDEPEND ALLDEPENDENCIES
+ifndef CPU_TARGET
+ifdef CPU_TARGET_DEFAULT
+CPU_TARGET=$(CPU_TARGET_DEFAULT)
+endif
+endif
+ifndef OS_TARGET
+ifdef OS_TARGET_DEFAULT
+OS_TARGET=$(OS_TARGET_DEFAULT)
+endif
+endif
+ifneq ($(words $(FPC_COMPILERINFO)),5)
+FPC_COMPILERINFO+=$(shell $(FPC) -iSP)
+FPC_COMPILERINFO+=$(shell $(FPC) -iTP)
+FPC_COMPILERINFO+=$(shell $(FPC) -iSO)
+FPC_COMPILERINFO+=$(shell $(FPC) -iTO)
+endif
+ifndef CPU_SOURCE
+CPU_SOURCE:=$(word 2,$(FPC_COMPILERINFO))
+endif
+ifndef CPU_TARGET
+CPU_TARGET:=$(word 3,$(FPC_COMPILERINFO))
+endif
+ifndef OS_SOURCE
+OS_SOURCE:=$(word 4,$(FPC_COMPILERINFO))
+endif
+ifndef OS_TARGET
+OS_TARGET:=$(word 5,$(FPC_COMPILERINFO))
+endif
+FULL_TARGET=$(CPU_TARGET)-$(OS_TARGET)
+FULL_SOURCE=$(CPU_SOURCE)-$(OS_SOURCE)
+ifeq ($(CPU_TARGET),armeb)
+ARCH=arm
+override FPCOPT+=-Cb
+else
+ifeq ($(CPU_TARGET),armel)
+ARCH=arm
+override FPCOPT+=-CaEABI
+else
+ARCH=$(CPU_TARGET)
+endif
+endif
+ifneq ($(findstring $(OS_SOURCE),$(LIMIT83fs)),)
+TARGETSUFFIX=$(OS_TARGET)
+SOURCESUFFIX=$(OS_SOURCE)
+else
+TARGETSUFFIX=$(FULL_TARGET)
+SOURCESUFFIX=$(FULL_SOURCE)
+endif
+ifneq ($(FULL_TARGET),$(FULL_SOURCE))
+CROSSCOMPILE=1
+endif
+ifeq ($(findstring makefile,$(MAKECMDGOALS)),)
+ifeq ($(findstring $(FULL_TARGET),$(MAKEFILETARGETS)),)
+$(error The Makefile doesn't support target $(FULL_TARGET), please run fpcmake first)
+endif
+endif
+ifneq ($(findstring $(OS_TARGET),$(BSDs)),)
+BSDhier=1
+endif
+ifeq ($(OS_TARGET),linux)
+linuxHier=1
+endif
+export OS_TARGET OS_SOURCE ARCH CPU_TARGET CPU_SOURCE FULL_TARGET FULL_SOURCE TARGETSUFFIX SOURCESUFFIX CROSSCOMPILE
+ifdef FPCDIR
+override FPCDIR:=$(subst \,/,$(FPCDIR))
+ifeq ($(wildcard $(addprefix $(FPCDIR)/,rtl units)),)
+override FPCDIR=wrong
+endif
+else
+override FPCDIR=wrong
+endif
+ifdef DEFAULT_FPCDIR
+ifeq ($(FPCDIR),wrong)
+override FPCDIR:=$(subst \,/,$(DEFAULT_FPCDIR))
+ifeq ($(wildcard $(addprefix $(FPCDIR)/,rtl units)),)
+override FPCDIR=wrong
+endif
+endif
+endif
+ifeq ($(FPCDIR),wrong)
+ifdef inUnix
+override FPCDIR=/usr/local/lib/fpc/$(FPC_VERSION)
+ifeq ($(wildcard $(FPCDIR)/units),)
+override FPCDIR=/usr/lib/fpc/$(FPC_VERSION)
+endif
+else
+override FPCDIR:=$(subst /$(FPC),,$(firstword $(strip $(wildcard $(addsuffix /$(FPC),$(SEARCHPATH))))))
+override FPCDIR:=$(FPCDIR)/..
+ifeq ($(wildcard $(addprefix $(FPCDIR)/,rtl units)),)
+override FPCDIR:=$(FPCDIR)/..
+ifeq ($(wildcard $(addprefix $(FPCDIR)/,rtl units)),)
+override FPCDIR:=$(BASEDIR)
+ifeq ($(wildcard $(addprefix $(FPCDIR)/,rtl units)),)
+override FPCDIR=c:/pp
+endif
+endif
+endif
+endif
+endif
+ifndef CROSSBINDIR
+CROSSBINDIR:=$(wildcard $(FPCDIR)/bin/$(TARGETSUFFIX))
+endif
+ifeq ($(OS_TARGET),darwin)
+ifeq ($(OS_SOURCE),darwin)
+DARWIN2DARWIN=1
+endif
+endif
+ifndef BINUTILSPREFIX
+ifndef CROSSBINDIR
+ifdef CROSSCOMPILE
+ifndef DARWIN2DARWIN
+BINUTILSPREFIX=$(CPU_TARGET)-$(OS_TARGET)-
+endif
+endif
+endif
+endif
+UNITSDIR:=$(wildcard $(FPCDIR)/units/$(TARGETSUFFIX))
+ifeq ($(UNITSDIR),)
+UNITSDIR:=$(wildcard $(FPCDIR)/units/$(OS_TARGET))
+endif
+PACKAGESDIR:=$(wildcard $(FPCDIR) $(FPCDIR)/packages $(FPCDIR)/packages/base $(FPCDIR)/packages/extra)
+override PACKAGE_NAME=fcl-web
+override PACKAGE_VERSION=2.5.1
+PACKAGEDIR_MAIN:=$(firstword $(subst /Makefile.fpc,,$(strip $(wildcard $(addsuffix /fcl-web/Makefile.fpc,$(PACKAGESDIR))))))
+ifeq ($(FULL_TARGET),i386-linux)
+override TARGET_UNITS+=fpjsonrpc webjsonrpc fpextdirect
+endif
+ifeq ($(FULL_TARGET),i386-go32v2)
+override TARGET_UNITS+=fpjsonrpc webjsonrpc fpextdirect
+endif
+ifeq ($(FULL_TARGET),i386-win32)
+override TARGET_UNITS+=fpjsonrpc webjsonrpc fpextdirect
+endif
+ifeq ($(FULL_TARGET),i386-os2)
+override TARGET_UNITS+=fpjsonrpc webjsonrpc fpextdirect
+endif
+ifeq ($(FULL_TARGET),i386-freebsd)
+override TARGET_UNITS+=fpjsonrpc webjsonrpc fpextdirect
+endif
+ifeq ($(FULL_TARGET),i386-beos)
+override TARGET_UNITS+=fpjsonrpc webjsonrpc fpextdirect
+endif
+ifeq ($(FULL_TARGET),i386-haiku)
+override TARGET_UNITS+=fpjsonrpc webjsonrpc fpextdirect
+endif
+ifeq ($(FULL_TARGET),i386-netbsd)
+override TARGET_UNITS+=fpjsonrpc webjsonrpc fpextdirect
+endif
+ifeq ($(FULL_TARGET),i386-solaris)
+override TARGET_UNITS+=fpjsonrpc webjsonrpc fpextdirect
+endif
+ifeq ($(FULL_TARGET),i386-qnx)
+override TARGET_UNITS+=fpjsonrpc webjsonrpc fpextdirect
+endif
+ifeq ($(FULL_TARGET),i386-netware)
+override TARGET_UNITS+=fpjsonrpc webjsonrpc fpextdirect
+endif
+ifeq ($(FULL_TARGET),i386-openbsd)
+override TARGET_UNITS+=fpjsonrpc webjsonrpc fpextdirect
+endif
+ifeq ($(FULL_TARGET),i386-wdosx)
+override TARGET_UNITS+=fpjsonrpc webjsonrpc fpextdirect
+endif
+ifeq ($(FULL_TARGET),i386-darwin)
+override TARGET_UNITS+=fpjsonrpc webjsonrpc fpextdirect
+endif
+ifeq ($(FULL_TARGET),i386-emx)
+override TARGET_UNITS+=fpjsonrpc webjsonrpc fpextdirect
+endif
+ifeq ($(FULL_TARGET),i386-watcom)
+override TARGET_UNITS+=fpjsonrpc webjsonrpc fpextdirect
+endif
+ifeq ($(FULL_TARGET),i386-netwlibc)
+override TARGET_UNITS+=fpjsonrpc webjsonrpc fpextdirect
+endif
+ifeq ($(FULL_TARGET),i386-wince)
+override TARGET_UNITS+=fpjsonrpc webjsonrpc fpextdirect
+endif
+ifeq ($(FULL_TARGET),i386-embedded)
+override TARGET_UNITS+=fpjsonrpc webjsonrpc fpextdirect
+endif
+ifeq ($(FULL_TARGET),i386-symbian)
+override TARGET_UNITS+=fpjsonrpc webjsonrpc fpextdirect
+endif
+ifeq ($(FULL_TARGET),m68k-linux)
+override TARGET_UNITS+=fpjsonrpc webjsonrpc fpextdirect
+endif
+ifeq ($(FULL_TARGET),m68k-freebsd)
+override TARGET_UNITS+=fpjsonrpc webjsonrpc fpextdirect
+endif
+ifeq ($(FULL_TARGET),m68k-netbsd)
+override TARGET_UNITS+=fpjsonrpc webjsonrpc fpextdirect
+endif
+ifeq ($(FULL_TARGET),m68k-amiga)
+override TARGET_UNITS+=fpjsonrpc webjsonrpc fpextdirect
+endif
+ifeq ($(FULL_TARGET),m68k-atari)
+override TARGET_UNITS+=fpjsonrpc webjsonrpc fpextdirect
+endif
+ifeq ($(FULL_TARGET),m68k-openbsd)
+override TARGET_UNITS+=fpjsonrpc webjsonrpc fpextdirect
+endif
+ifeq ($(FULL_TARGET),m68k-palmos)
+override TARGET_UNITS+=fpjsonrpc webjsonrpc fpextdirect
+endif
+ifeq ($(FULL_TARGET),m68k-embedded)
+override TARGET_UNITS+=fpjsonrpc webjsonrpc fpextdirect
+endif
+ifeq ($(FULL_TARGET),powerpc-linux)
+override TARGET_UNITS+=fpjsonrpc webjsonrpc fpextdirect
+endif
+ifeq ($(FULL_TARGET),powerpc-netbsd)
+override TARGET_UNITS+=fpjsonrpc webjsonrpc fpextdirect
+endif
+ifeq ($(FULL_TARGET),powerpc-amiga)
+override TARGET_UNITS+=fpjsonrpc webjsonrpc fpextdirect
+endif
+ifeq ($(FULL_TARGET),powerpc-macos)
+override TARGET_UNITS+=fpjsonrpc webjsonrpc fpextdirect
+endif
+ifeq ($(FULL_TARGET),powerpc-darwin)
+override TARGET_UNITS+=fpjsonrpc webjsonrpc fpextdirect
+endif
+ifeq ($(FULL_TARGET),powerpc-morphos)
+override TARGET_UNITS+=fpjsonrpc webjsonrpc fpextdirect
+endif
+ifeq ($(FULL_TARGET),powerpc-embedded)
+override TARGET_UNITS+=fpjsonrpc webjsonrpc fpextdirect
+endif
+ifeq ($(FULL_TARGET),sparc-linux)
+override TARGET_UNITS+=fpjsonrpc webjsonrpc fpextdirect
+endif
+ifeq ($(FULL_TARGET),sparc-netbsd)
+override TARGET_UNITS+=fpjsonrpc webjsonrpc fpextdirect
+endif
+ifeq ($(FULL_TARGET),sparc-solaris)
+override TARGET_UNITS+=fpjsonrpc webjsonrpc fpextdirect
+endif
+ifeq ($(FULL_TARGET),sparc-embedded)
+override TARGET_UNITS+=fpjsonrpc webjsonrpc fpextdirect
+endif
+ifeq ($(FULL_TARGET),x86_64-linux)
+override TARGET_UNITS+=fpjsonrpc webjsonrpc fpextdirect
+endif
+ifeq ($(FULL_TARGET),x86_64-freebsd)
+override TARGET_UNITS+=fpjsonrpc webjsonrpc fpextdirect
+endif
+ifeq ($(FULL_TARGET),x86_64-darwin)
+override TARGET_UNITS+=fpjsonrpc webjsonrpc fpextdirect
+endif
+ifeq ($(FULL_TARGET),x86_64-win64)
+override TARGET_UNITS+=fpjsonrpc webjsonrpc fpextdirect
+endif
+ifeq ($(FULL_TARGET),x86_64-embedded)
+override TARGET_UNITS+=fpjsonrpc webjsonrpc fpextdirect
+endif
+ifeq ($(FULL_TARGET),arm-linux)
+override TARGET_UNITS+=fpjsonrpc webjsonrpc fpextdirect
+endif
+ifeq ($(FULL_TARGET),arm-palmos)
+override TARGET_UNITS+=fpjsonrpc webjsonrpc fpextdirect
+endif
+ifeq ($(FULL_TARGET),arm-darwin)
+override TARGET_UNITS+=fpjsonrpc webjsonrpc fpextdirect
+endif
+ifeq ($(FULL_TARGET),arm-wince)
+override TARGET_UNITS+=fpjsonrpc webjsonrpc fpextdirect
+endif
+ifeq ($(FULL_TARGET),arm-gba)
+override TARGET_UNITS+=fpjsonrpc webjsonrpc fpextdirect
+endif
+ifeq ($(FULL_TARGET),arm-nds)
+override TARGET_UNITS+=fpjsonrpc webjsonrpc fpextdirect
+endif
+ifeq ($(FULL_TARGET),arm-embedded)
+override TARGET_UNITS+=fpjsonrpc webjsonrpc fpextdirect
+endif
+ifeq ($(FULL_TARGET),arm-symbian)
+override TARGET_UNITS+=fpjsonrpc webjsonrpc fpextdirect
+endif
+ifeq ($(FULL_TARGET),powerpc64-linux)
+override TARGET_UNITS+=fpjsonrpc webjsonrpc fpextdirect
+endif
+ifeq ($(FULL_TARGET),powerpc64-darwin)
+override TARGET_UNITS+=fpjsonrpc webjsonrpc fpextdirect
+endif
+ifeq ($(FULL_TARGET),powerpc64-embedded)
+override TARGET_UNITS+=fpjsonrpc webjsonrpc fpextdirect
+endif
+ifeq ($(FULL_TARGET),avr-embedded)
+override TARGET_UNITS+=fpjsonrpc webjsonrpc fpextdirect
+endif
+ifeq ($(FULL_TARGET),armeb-linux)
+override TARGET_UNITS+=fpjsonrpc webjsonrpc fpextdirect
+endif
+ifeq ($(FULL_TARGET),armeb-embedded)
+override TARGET_UNITS+=fpjsonrpc webjsonrpc fpextdirect
+endif
+override INSTALL_FPCPACKAGE=y
+ifeq ($(FULL_TARGET),i386-linux)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),i386-go32v2)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),i386-win32)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),i386-os2)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),i386-freebsd)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),i386-beos)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),i386-haiku)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),i386-netbsd)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),i386-solaris)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),i386-qnx)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),i386-netware)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),i386-openbsd)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),i386-wdosx)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),i386-darwin)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),i386-emx)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),i386-watcom)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),i386-netwlibc)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),i386-wince)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),i386-embedded)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),i386-symbian)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),m68k-linux)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),m68k-freebsd)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),m68k-netbsd)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),m68k-amiga)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),m68k-atari)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),m68k-openbsd)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),m68k-palmos)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),m68k-embedded)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),powerpc-linux)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),powerpc-netbsd)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),powerpc-amiga)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),powerpc-macos)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),powerpc-darwin)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),powerpc-morphos)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),powerpc-embedded)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),sparc-linux)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),sparc-netbsd)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),sparc-solaris)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),sparc-embedded)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),x86_64-linux)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),x86_64-freebsd)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),x86_64-darwin)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),x86_64-win64)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),x86_64-embedded)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),arm-linux)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),arm-palmos)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),arm-darwin)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),arm-wince)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),arm-gba)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),arm-nds)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),arm-embedded)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),arm-symbian)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),powerpc64-linux)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),powerpc64-darwin)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),powerpc64-embedded)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),avr-embedded)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),armeb-linux)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifeq ($(FULL_TARGET),armeb-embedded)
+override COMPILER_OPTIONS+=-S2h
+endif
+ifdef REQUIRE_UNITSDIR
+override UNITSDIR+=$(REQUIRE_UNITSDIR)
+endif
+ifdef REQUIRE_PACKAGESDIR
+override PACKAGESDIR+=$(REQUIRE_PACKAGESDIR)
+endif
+ifdef ZIPINSTALL
+ifneq ($(findstring $(OS_TARGET),$(UNIXs)),)
+UNIXHier=1
+endif
+else
+ifneq ($(findstring $(OS_SOURCE),$(UNIXs)),)
+UNIXHier=1
+endif
+endif
+ifndef INSTALL_PREFIX
+ifdef PREFIX
+INSTALL_PREFIX=$(PREFIX)
+endif
+endif
+ifndef INSTALL_PREFIX
+ifdef UNIXHier
+INSTALL_PREFIX=/usr/local
+else
+ifdef INSTALL_FPCPACKAGE
+INSTALL_BASEDIR:=/pp
+else
+INSTALL_BASEDIR:=/$(PACKAGE_NAME)
+endif
+endif
+endif
+export INSTALL_PREFIX
+ifdef INSTALL_FPCSUBDIR
+export INSTALL_FPCSUBDIR
+endif
+ifndef DIST_DESTDIR
+DIST_DESTDIR:=$(BASEDIR)
+endif
+export DIST_DESTDIR
+ifndef COMPILER_UNITTARGETDIR
+ifdef PACKAGEDIR_MAIN
+COMPILER_UNITTARGETDIR=$(PACKAGEDIR_MAIN)/units/$(TARGETSUFFIX)
+else
+COMPILER_UNITTARGETDIR=units/$(TARGETSUFFIX)
+endif
+endif
+ifndef COMPILER_TARGETDIR
+COMPILER_TARGETDIR=.
+endif
+ifndef INSTALL_BASEDIR
+ifdef UNIXHier
+ifdef INSTALL_FPCPACKAGE
+INSTALL_BASEDIR:=$(INSTALL_PREFIX)/lib/fpc/$(FPC_VERSION)
+else
+INSTALL_BASEDIR:=$(INSTALL_PREFIX)/lib/$(PACKAGE_NAME)
+endif
+else
+INSTALL_BASEDIR:=$(INSTALL_PREFIX)
+endif
+endif
+ifndef INSTALL_BINDIR
+ifdef UNIXHier
+INSTALL_BINDIR:=$(INSTALL_PREFIX)/bin
+else
+INSTALL_BINDIR:=$(INSTALL_BASEDIR)/bin
+ifdef INSTALL_FPCPACKAGE
+ifdef CROSSCOMPILE
+ifdef CROSSINSTALL
+INSTALL_BINDIR:=$(INSTALL_BINDIR)/$(SOURCESUFFIX)
+else
+INSTALL_BINDIR:=$(INSTALL_BINDIR)/$(TARGETSUFFIX)
+endif
+else
+INSTALL_BINDIR:=$(INSTALL_BINDIR)/$(TARGETSUFFIX)
+endif
+endif
+endif
+endif
+ifndef INSTALL_UNITDIR
+INSTALL_UNITDIR:=$(INSTALL_BASEDIR)/units/$(TARGETSUFFIX)
+ifdef INSTALL_FPCPACKAGE
+ifdef PACKAGE_NAME
+INSTALL_UNITDIR:=$(INSTALL_UNITDIR)/$(PACKAGE_NAME)
+endif
+endif
+endif
+ifndef INSTALL_LIBDIR
+ifdef UNIXHier
+INSTALL_LIBDIR:=$(INSTALL_PREFIX)/lib
+else
+INSTALL_LIBDIR:=$(INSTALL_UNITDIR)
+endif
+endif
+ifndef INSTALL_SOURCEDIR
+ifdef UNIXHier
+ifdef BSDhier
+SRCPREFIXDIR=share/src
+else
+ifdef linuxHier
+SRCPREFIXDIR=share/src
+else
+SRCPREFIXDIR=src
+endif
+endif
+ifdef INSTALL_FPCPACKAGE
+ifdef INSTALL_FPCSUBDIR
+INSTALL_SOURCEDIR:=$(INSTALL_PREFIX)/$(SRCPREFIXDIR)/fpc-$(FPC_VERSION)/$(INSTALL_FPCSUBDIR)/$(PACKAGE_NAME)
+else
+INSTALL_SOURCEDIR:=$(INSTALL_PREFIX)/$(SRCPREFIXDIR)/fpc-$(FPC_VERSION)/$(PACKAGE_NAME)
+endif
+else
+INSTALL_SOURCEDIR:=$(INSTALL_PREFIX)/$(SRCPREFIXDIR)/$(PACKAGE_NAME)-$(PACKAGE_VERSION)
+endif
+else
+ifdef INSTALL_FPCPACKAGE
+ifdef INSTALL_FPCSUBDIR
+INSTALL_SOURCEDIR:=$(INSTALL_BASEDIR)/source/$(INSTALL_FPCSUBDIR)/$(PACKAGE_NAME)
+else
+INSTALL_SOURCEDIR:=$(INSTALL_BASEDIR)/source/$(PACKAGE_NAME)
+endif
+else
+INSTALL_SOURCEDIR:=$(INSTALL_BASEDIR)/source
+endif
+endif
+endif
+ifndef INSTALL_DOCDIR
+ifdef UNIXHier
+ifdef BSDhier
+DOCPREFIXDIR=share/doc
+else
+ifdef linuxHier
+DOCPREFIXDIR=share/doc
+else
+DOCPREFIXDIR=doc
+endif
+endif
+ifdef INSTALL_FPCPACKAGE
+INSTALL_DOCDIR:=$(INSTALL_PREFIX)/$(DOCPREFIXDIR)/fpc-$(FPC_VERSION)/$(PACKAGE_NAME)
+else
+INSTALL_DOCDIR:=$(INSTALL_PREFIX)/$(DOCPREFIXDIR)/$(PACKAGE_NAME)-$(PACKAGE_VERSION)
+endif
+else
+ifdef INSTALL_FPCPACKAGE
+INSTALL_DOCDIR:=$(INSTALL_BASEDIR)/doc/$(PACKAGE_NAME)
+else
+INSTALL_DOCDIR:=$(INSTALL_BASEDIR)/doc
+endif
+endif
+endif
+ifndef INSTALL_EXAMPLEDIR
+ifdef UNIXHier
+ifdef INSTALL_FPCPACKAGE
+ifdef BSDhier
+INSTALL_EXAMPLEDIR:=$(INSTALL_PREFIX)/share/examples/fpc-$(FPC_VERSION)/$(PACKAGE_NAME)
+else
+ifdef linuxHier
+INSTALL_EXAMPLEDIR:=$(INSTALL_DOCDIR)/examples
+else
+INSTALL_EXAMPLEDIR:=$(INSTALL_PREFIX)/doc/fpc-$(FPC_VERSION)/examples/$(PACKAGE_NAME)
+endif
+endif
+else
+ifdef BSDhier
+INSTALL_EXAMPLEDIR:=$(INSTALL_PREFIX)/share/examples/$(PACKAGE_NAME)-$(PACKAGE_VERSION)
+else
+ifdef linuxHier
+INSTALL_EXAMPLEDIR:=$(INSTALL_DOCDIR)/examples/$(PACKAGE_NAME)-$(PACKAGE_VERSION)
+else
+INSTALL_EXAMPLEDIR:=$(INSTALL_PREFIX)/doc/$(PACKAGE_NAME)-$(PACKAGE_VERSION)
+endif
+endif
+endif
+else
+ifdef INSTALL_FPCPACKAGE
+INSTALL_EXAMPLEDIR:=$(INSTALL_BASEDIR)/examples/$(PACKAGE_NAME)
+else
+INSTALL_EXAMPLEDIR:=$(INSTALL_BASEDIR)/examples
+endif
+endif
+endif
+ifndef INSTALL_DATADIR
+INSTALL_DATADIR=$(INSTALL_BASEDIR)
+endif
+ifndef INSTALL_SHAREDDIR
+INSTALL_SHAREDDIR=$(INSTALL_PREFIX)/lib
+endif
+ifdef CROSSCOMPILE
+ifndef CROSSBINDIR
+CROSSBINDIR:=$(wildcard $(CROSSTARGETDIR)/bin/$(SOURCESUFFIX))
+ifeq ($(CROSSBINDIR),)
+CROSSBINDIR:=$(wildcard $(INSTALL_BASEDIR)/cross/$(TARGETSUFFIX)/bin/$(FULL_SOURCE))
+endif
+endif
+else
+CROSSBINDIR=
+endif
+ifeq ($(OS_SOURCE),linux)
+ifndef GCCLIBDIR
+ifeq ($(CPU_TARGET),i386)
+ifneq ($(findstring x86_64,$(shell uname -a)),)
+ifeq ($(BINUTILSPREFIX),)
+GCCLIBDIR:=$(shell dirname `gcc -m32 -print-libgcc-file-name`)
+endif
+endif
+endif
+ifeq ($(CPU_TARGET),powerpc64)
+ifeq ($(BINUTILSPREFIX),)
+GCCLIBDIR:=$(shell dirname `gcc -m64 -print-libgcc-file-name`)
+endif
+endif
+endif
+ifndef GCCLIBDIR
+CROSSGCC=$(strip $(wildcard $(addsuffix /$(BINUTILSPREFIX)gcc$(SRCEXEEXT),$(SEARCHPATH))))
+ifneq ($(CROSSGCC),)
+GCCLIBDIR:=$(shell dirname `$(CROSSGCC) -print-libgcc-file-name`)
+endif
+endif
+ifndef OTHERLIBDIR
+OTHERLIBDIR:=$(shell grep -v "^\#" /etc/ld.so.conf | awk '{ ORS=" "; print $1 }')
+endif
+endif
+ifdef inUnix
+ifeq ($(OS_SOURCE),netbsd)
+OTHERLIBDIR+=/usr/pkg/lib
+endif
+export GCCLIBDIR OTHERLIB
+endif
+BATCHEXT=.bat
+LOADEREXT=.as
+EXEEXT=.exe
+PPLEXT=.ppl
+PPUEXT=.ppu
+OEXT=.o
+ASMEXT=.s
+SMARTEXT=.sl
+STATICLIBEXT=.a
+SHAREDLIBEXT=.so
+SHAREDLIBPREFIX=libfp
+STATICLIBPREFIX=libp
+IMPORTLIBPREFIX=libimp
+RSTEXT=.rst
+ifeq ($(findstring 1.0.,$(FPC_VERSION)),)
+ifeq ($(OS_TARGET),go32v1)
+STATICLIBPREFIX=
+SHORTSUFFIX=v1
+endif
+ifeq ($(OS_TARGET),go32v2)
+STATICLIBPREFIX=
+SHORTSUFFIX=dos
+IMPORTLIBPREFIX=
+endif
+ifeq ($(OS_TARGET),watcom)
+STATICLIBPREFIX=
+OEXT=.obj
+ASMEXT=.asm
+SHAREDLIBEXT=.dll
+SHORTSUFFIX=wat
+IMPORTLIBPREFIX=
+endif
+ifeq ($(OS_TARGET),linux)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=lnx
+endif
+ifeq ($(OS_TARGET),freebsd)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=fbs
+endif
+ifeq ($(OS_TARGET),netbsd)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=nbs
+endif
+ifeq ($(OS_TARGET),openbsd)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=obs
+endif
+ifeq ($(OS_TARGET),win32)
+SHAREDLIBEXT=.dll
+SHORTSUFFIX=w32
+endif
+ifeq ($(OS_TARGET),os2)
+BATCHEXT=.cmd
+AOUTEXT=.out
+STATICLIBPREFIX=
+SHAREDLIBEXT=.dll
+SHORTSUFFIX=os2
+ECHO=echo
+IMPORTLIBPREFIX=
+endif
+ifeq ($(OS_TARGET),emx)
+BATCHEXT=.cmd
+AOUTEXT=.out
+STATICLIBPREFIX=
+SHAREDLIBEXT=.dll
+SHORTSUFFIX=emx
+ECHO=echo
+IMPORTLIBPREFIX=
+endif
+ifeq ($(OS_TARGET),amiga)
+EXEEXT=
+SHAREDLIBEXT=.library
+SHORTSUFFIX=amg
+endif
+ifeq ($(OS_TARGET),morphos)
+EXEEXT=
+SHAREDLIBEXT=.library
+SHORTSUFFIX=mos
+endif
+ifeq ($(OS_TARGET),atari)
+EXEEXT=.ttp
+SHORTSUFFIX=ata
+endif
+ifeq ($(OS_TARGET),beos)
+BATCHEXT=.sh
+EXEEXT=
+SHORTSUFFIX=be
+endif
+ifeq ($(OS_TARGET),haiku)
+BATCHEXT=.sh
+EXEEXT=
+SHORTSUFFIX=hai
+endif
+ifeq ($(OS_TARGET),solaris)
+BATCHEXT=.sh
+EXEEXT=
+SHORTSUFFIX=sun
+endif
+ifeq ($(OS_TARGET),qnx)
+BATCHEXT=.sh
+EXEEXT=
+SHORTSUFFIX=qnx
+endif
+ifeq ($(OS_TARGET),netware)
+EXEEXT=.nlm
+STATICLIBPREFIX=
+SHORTSUFFIX=nw
+IMPORTLIBPREFIX=imp
+endif
+ifeq ($(OS_TARGET),netwlibc)
+EXEEXT=.nlm
+STATICLIBPREFIX=
+SHORTSUFFIX=nwl
+IMPORTLIBPREFIX=imp
+endif
+ifeq ($(OS_TARGET),macos)
+BATCHEXT=
+EXEEXT=
+DEBUGSYMEXT=.xcoff
+SHORTSUFFIX=mac
+IMPORTLIBPREFIX=imp
+endif
+ifeq ($(OS_TARGET),darwin)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=dwn
+endif
+ifeq ($(OS_TARGET),gba)
+EXEEXT=.gba
+SHAREDLIBEXT=.so
+SHORTSUFFIX=gba
+endif
+ifeq ($(OS_TARGET),symbian)
+SHAREDLIBEXT=.dll
+SHORTSUFFIX=symbian
+endif
+else
+ifeq ($(OS_TARGET),go32v1)
+PPUEXT=.pp1
+OEXT=.o1
+ASMEXT=.s1
+SMARTEXT=.sl1
+STATICLIBEXT=.a1
+SHAREDLIBEXT=.so1
+STATICLIBPREFIX=
+SHORTSUFFIX=v1
+IMPORTLIBPREFIX=
+endif
+ifeq ($(OS_TARGET),go32v2)
+STATICLIBPREFIX=
+SHORTSUFFIX=dos
+IMPORTLIBPREFIX=
+endif
+ifeq ($(OS_TARGET),watcom)
+STATICLIBPREFIX=
+SHORTSUFFIX=wat
+IMPORTLIBPREFIX=
+endif
+ifeq ($(OS_TARGET),linux)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=lnx
+endif
+ifeq ($(OS_TARGET),freebsd)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=fbs
+endif
+ifeq ($(OS_TARGET),netbsd)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=nbs
+endif
+ifeq ($(OS_TARGET),openbsd)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=obs
+endif
+ifeq ($(OS_TARGET),win32)
+PPUEXT=.ppw
+OEXT=.ow
+ASMEXT=.sw
+SMARTEXT=.slw
+STATICLIBEXT=.aw
+SHAREDLIBEXT=.dll
+SHORTSUFFIX=w32
+endif
+ifeq ($(OS_TARGET),os2)
+BATCHEXT=.cmd
+PPUEXT=.ppo
+ASMEXT=.so2
+OEXT=.oo2
+AOUTEXT=.out
+SMARTEXT=.sl2
+STATICLIBPREFIX=
+STATICLIBEXT=.ao2
+SHAREDLIBEXT=.dll
+SHORTSUFFIX=os2
+ECHO=echo
+IMPORTLIBPREFIX=
+endif
+ifeq ($(OS_TARGET),amiga)
+EXEEXT=
+PPUEXT=.ppu
+ASMEXT=.s
+OEXT=.o
+SMARTEXT=.sl
+STATICLIBEXT=.a
+SHAREDLIBEXT=.library
+SHORTSUFFIX=amg
+endif
+ifeq ($(OS_TARGET),atari)
+PPUEXT=.ppu
+ASMEXT=.s
+OEXT=.o
+SMARTEXT=.sl
+STATICLIBEXT=.a
+EXEEXT=.ttp
+SHORTSUFFIX=ata
+endif
+ifeq ($(OS_TARGET),beos)
+BATCHEXT=.sh
+PPUEXT=.ppu
+ASMEXT=.s
+OEXT=.o
+SMARTEXT=.sl
+STATICLIBEXT=.a
+EXEEXT=
+SHORTSUFFIX=be
+endif
+ifeq ($(OS_TARGET),solaris)
+BATCHEXT=.sh
+PPUEXT=.ppu
+ASMEXT=.s
+OEXT=.o
+SMARTEXT=.sl
+STATICLIBEXT=.a
+EXEEXT=
+SHORTSUFFIX=sun
+endif
+ifeq ($(OS_TARGET),qnx)
+BATCHEXT=.sh
+PPUEXT=.ppu
+ASMEXT=.s
+OEXT=.o
+SMARTEXT=.sl
+STATICLIBEXT=.a
+EXEEXT=
+SHORTSUFFIX=qnx
+endif
+ifeq ($(OS_TARGET),netware)
+STATICLIBPREFIX=
+PPUEXT=.ppu
+OEXT=.o
+ASMEXT=.s
+SMARTEXT=.sl
+STATICLIBEXT=.a
+SHAREDLIBEXT=.nlm
+EXEEXT=.nlm
+SHORTSUFFIX=nw
+IMPORTLIBPREFIX=imp
+endif
+ifeq ($(OS_TARGET),netwlibc)
+STATICLIBPREFIX=
+PPUEXT=.ppu
+OEXT=.o
+ASMEXT=.s
+SMARTEXT=.sl
+STATICLIBEXT=.a
+SHAREDLIBEXT=.nlm
+EXEEXT=.nlm
+SHORTSUFFIX=nwl
+IMPORTLIBPREFIX=imp
+endif
+ifeq ($(OS_TARGET),macos)
+BATCHEXT=
+PPUEXT=.ppu
+ASMEXT=.s
+OEXT=.o
+SMARTEXT=.sl
+STATICLIBEXT=.a
+EXEEXT=
+DEBUGSYMEXT=.xcoff
+SHORTSUFFIX=mac
+IMPORTLIBPREFIX=imp
+endif
+endif
+ifneq ($(findstring $(OS_SOURCE),$(LIMIT83fs)),)
+FPCMADE=fpcmade.$(SHORTSUFFIX)
+ZIPSUFFIX=$(SHORTSUFFIX)
+ZIPCROSSPREFIX=
+ZIPSOURCESUFFIX=src
+ZIPEXAMPLESUFFIX=exm
+else
+FPCMADE=fpcmade.$(TARGETSUFFIX)
+ZIPSOURCESUFFIX=.source
+ZIPEXAMPLESUFFIX=.examples
+ifdef CROSSCOMPILE
+ZIPSUFFIX=.$(SOURCESUFFIX)
+ZIPCROSSPREFIX=$(TARGETSUFFIX)-
+else
+ZIPSUFFIX=.$(TARGETSUFFIX)
+ZIPCROSSPREFIX=
+endif
+endif
+ifndef ECHO
+ECHO:=$(strip $(wildcard $(addsuffix /gecho$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(ECHO),)
+ECHO:=$(strip $(wildcard $(addsuffix /echo$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(ECHO),)
+ECHO= __missing_command_ECHO
+else
+ECHO:=$(firstword $(ECHO))
+endif
+else
+ECHO:=$(firstword $(ECHO))
+endif
+endif
+export ECHO
+ifndef DATE
+DATE:=$(strip $(wildcard $(addsuffix /gdate$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(DATE),)
+DATE:=$(strip $(wildcard $(addsuffix /date$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(DATE),)
+DATE= __missing_command_DATE
+else
+DATE:=$(firstword $(DATE))
+endif
+else
+DATE:=$(firstword $(DATE))
+endif
+endif
+export DATE
+ifndef GINSTALL
+GINSTALL:=$(strip $(wildcard $(addsuffix /ginstall$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(GINSTALL),)
+GINSTALL:=$(strip $(wildcard $(addsuffix /install$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(GINSTALL),)
+GINSTALL= __missing_command_GINSTALL
+else
+GINSTALL:=$(firstword $(GINSTALL))
+endif
+else
+GINSTALL:=$(firstword $(GINSTALL))
+endif
+endif
+export GINSTALL
+ifndef CPPROG
+CPPROG:=$(strip $(wildcard $(addsuffix /cp$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(CPPROG),)
+CPPROG= __missing_command_CPPROG
+else
+CPPROG:=$(firstword $(CPPROG))
+endif
+endif
+export CPPROG
+ifndef RMPROG
+RMPROG:=$(strip $(wildcard $(addsuffix /rm$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(RMPROG),)
+RMPROG= __missing_command_RMPROG
+else
+RMPROG:=$(firstword $(RMPROG))
+endif
+endif
+export RMPROG
+ifndef MVPROG
+MVPROG:=$(strip $(wildcard $(addsuffix /mv$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(MVPROG),)
+MVPROG= __missing_command_MVPROG
+else
+MVPROG:=$(firstword $(MVPROG))
+endif
+endif
+export MVPROG
+ifndef MKDIRPROG
+MKDIRPROG:=$(strip $(wildcard $(addsuffix /gmkdir$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(MKDIRPROG),)
+MKDIRPROG:=$(strip $(wildcard $(addsuffix /mkdir$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(MKDIRPROG),)
+MKDIRPROG= __missing_command_MKDIRPROG
+else
+MKDIRPROG:=$(firstword $(MKDIRPROG))
+endif
+else
+MKDIRPROG:=$(firstword $(MKDIRPROG))
+endif
+endif
+export MKDIRPROG
+ifndef ECHOREDIR
+ifndef inUnix
+ECHOREDIR=echo
+else
+ECHOREDIR=$(ECHO)
+endif
+endif
+ifndef COPY
+COPY:=$(CPPROG) -fp
+endif
+ifndef COPYTREE
+COPYTREE:=$(CPPROG) -Rfp
+endif
+ifndef MKDIRTREE
+MKDIRTREE:=$(MKDIRPROG) -p
+endif
+ifndef MOVE
+MOVE:=$(MVPROG) -f
+endif
+ifndef DEL
+DEL:=$(RMPROG) -f
+endif
+ifndef DELTREE
+DELTREE:=$(RMPROG) -rf
+endif
+ifndef INSTALL
+ifdef inUnix
+INSTALL:=$(GINSTALL) -c -m 644
+else
+INSTALL:=$(COPY)
+endif
+endif
+ifndef INSTALLEXE
+ifdef inUnix
+INSTALLEXE:=$(GINSTALL) -c -m 755
+else
+INSTALLEXE:=$(COPY)
+endif
+endif
+ifndef MKDIR
+MKDIR:=$(GINSTALL) -m 755 -d
+endif
+export ECHOREDIR COPY COPYTREE MOVE DEL DELTREE INSTALL INSTALLEXE MKDIR
+ifndef PPUMOVE
+PPUMOVE:=$(strip $(wildcard $(addsuffix /ppumove$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(PPUMOVE),)
+PPUMOVE= __missing_command_PPUMOVE
+else
+PPUMOVE:=$(firstword $(PPUMOVE))
+endif
+endif
+export PPUMOVE
+ifndef FPCMAKE
+FPCMAKE:=$(strip $(wildcard $(addsuffix /fpcmake$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(FPCMAKE),)
+FPCMAKE= __missing_command_FPCMAKE
+else
+FPCMAKE:=$(firstword $(FPCMAKE))
+endif
+endif
+export FPCMAKE
+ifndef ZIPPROG
+ZIPPROG:=$(strip $(wildcard $(addsuffix /zip$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(ZIPPROG),)
+ZIPPROG= __missing_command_ZIPPROG
+else
+ZIPPROG:=$(firstword $(ZIPPROG))
+endif
+endif
+export ZIPPROG
+ifndef TARPROG
+TARPROG:=$(strip $(wildcard $(addsuffix /gtar$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(TARPROG),)
+TARPROG:=$(strip $(wildcard $(addsuffix /tar$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(TARPROG),)
+TARPROG= __missing_command_TARPROG
+else
+TARPROG:=$(firstword $(TARPROG))
+endif
+else
+TARPROG:=$(firstword $(TARPROG))
+endif
+endif
+export TARPROG
+ASNAME=$(BINUTILSPREFIX)as
+LDNAME=$(BINUTILSPREFIX)ld
+ARNAME=$(BINUTILSPREFIX)ar
+RCNAME=$(BINUTILSPREFIX)rc
+ifneq ($(findstring 1.0.,$(FPC_VERSION)),)
+ifeq ($(OS_TARGET),win32)
+ifeq ($(CROSSBINDIR),)
+ASNAME=asw
+LDNAME=ldw
+ARNAME=arw
+endif
+endif
+endif
+ifndef ASPROG
+ifdef CROSSBINDIR
+ASPROG=$(CROSSBINDIR)/$(ASNAME)$(SRCEXEEXT)
+else
+ASPROG=$(ASNAME)
+endif
+endif
+ifndef LDPROG
+ifdef CROSSBINDIR
+LDPROG=$(CROSSBINDIR)/$(LDNAME)$(SRCEXEEXT)
+else
+LDPROG=$(LDNAME)
+endif
+endif
+ifndef RCPROG
+ifdef CROSSBINDIR
+RCPROG=$(CROSSBINDIR)/$(RCNAME)$(SRCEXEEXT)
+else
+RCPROG=$(RCNAME)
+endif
+endif
+ifndef ARPROG
+ifdef CROSSBINDIR
+ARPROG=$(CROSSBINDIR)/$(ARNAME)$(SRCEXEEXT)
+else
+ARPROG=$(ARNAME)
+endif
+endif
+AS=$(ASPROG)
+LD=$(LDPROG)
+RC=$(RCPROG)
+AR=$(ARPROG)
+PPAS=ppas$(SRCBATCHEXT)
+ifdef inUnix
+LDCONFIG=ldconfig
+else
+LDCONFIG=
+endif
+ifdef DATE
+DATESTR:=$(shell $(DATE) +%Y%m%d)
+else
+DATESTR=
+endif
+ifndef UPXPROG
+ifeq ($(OS_TARGET),go32v2)
+UPXPROG:=1
+endif
+ifeq ($(OS_TARGET),win32)
+UPXPROG:=1
+endif
+ifdef UPXPROG
+UPXPROG:=$(strip $(wildcard $(addsuffix /upx$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(UPXPROG),)
+UPXPROG=
+else
+UPXPROG:=$(firstword $(UPXPROG))
+endif
+else
+UPXPROG=
+endif
+endif
+export UPXPROG
+ZIPOPT=-9
+ZIPEXT=.zip
+ifeq ($(USETAR),bz2)
+TAROPT=vj
+TAREXT=.tar.bz2
+else
+TAROPT=vz
+TAREXT=.tar.gz
+endif
+override REQUIRE_PACKAGES=rtl fcl-base fcl-xml fcl-json
+ifeq ($(FULL_TARGET),i386-linux)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+REQUIRE_PACKAGES_ICONVENC=1
+REQUIRE_PACKAGES_FCL-XML=1
+REQUIRE_PACKAGES_FCL-JSON=1
+endif
+ifeq ($(FULL_TARGET),i386-go32v2)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+REQUIRE_PACKAGES_FCL-XML=1
+REQUIRE_PACKAGES_FCL-JSON=1
+endif
+ifeq ($(FULL_TARGET),i386-win32)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+REQUIRE_PACKAGES_FCL-XML=1
+REQUIRE_PACKAGES_FCL-JSON=1
+endif
+ifeq ($(FULL_TARGET),i386-os2)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+REQUIRE_PACKAGES_FCL-XML=1
+REQUIRE_PACKAGES_FCL-JSON=1
+endif
+ifeq ($(FULL_TARGET),i386-freebsd)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+REQUIRE_PACKAGES_ICONVENC=1
+REQUIRE_PACKAGES_FCL-XML=1
+REQUIRE_PACKAGES_FCL-JSON=1
+endif
+ifeq ($(FULL_TARGET),i386-beos)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+REQUIRE_PACKAGES_ICONVENC=1
+REQUIRE_PACKAGES_FCL-XML=1
+REQUIRE_PACKAGES_FCL-JSON=1
+endif
+ifeq ($(FULL_TARGET),i386-haiku)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+REQUIRE_PACKAGES_ICONVENC=1
+REQUIRE_PACKAGES_FCL-XML=1
+REQUIRE_PACKAGES_FCL-JSON=1
+endif
+ifeq ($(FULL_TARGET),i386-netbsd)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+REQUIRE_PACKAGES_FCL-XML=1
+REQUIRE_PACKAGES_FCL-JSON=1
+endif
+ifeq ($(FULL_TARGET),i386-solaris)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+REQUIRE_PACKAGES_FCL-XML=1
+REQUIRE_PACKAGES_FCL-JSON=1
+endif
+ifeq ($(FULL_TARGET),i386-qnx)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+REQUIRE_PACKAGES_FCL-XML=1
+REQUIRE_PACKAGES_FCL-JSON=1
+endif
+ifeq ($(FULL_TARGET),i386-netware)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+REQUIRE_PACKAGES_FCL-XML=1
+REQUIRE_PACKAGES_FCL-JSON=1
+endif
+ifeq ($(FULL_TARGET),i386-openbsd)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+REQUIRE_PACKAGES_FCL-XML=1
+REQUIRE_PACKAGES_FCL-JSON=1
+endif
+ifeq ($(FULL_TARGET),i386-wdosx)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+REQUIRE_PACKAGES_FCL-XML=1
+REQUIRE_PACKAGES_FCL-JSON=1
+endif
+ifeq ($(FULL_TARGET),i386-darwin)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_UNIVINT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+REQUIRE_PACKAGES_ICONVENC=1
+REQUIRE_PACKAGES_FCL-XML=1
+REQUIRE_PACKAGES_FCL-JSON=1
+endif
+ifeq ($(FULL_TARGET),i386-emx)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+REQUIRE_PACKAGES_FCL-XML=1
+REQUIRE_PACKAGES_FCL-JSON=1
+endif
+ifeq ($(FULL_TARGET),i386-watcom)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+REQUIRE_PACKAGES_FCL-XML=1
+REQUIRE_PACKAGES_FCL-JSON=1
+endif
+ifeq ($(FULL_TARGET),i386-netwlibc)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+REQUIRE_PACKAGES_FCL-XML=1
+REQUIRE_PACKAGES_FCL-JSON=1
+endif
+ifeq ($(FULL_TARGET),i386-wince)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+REQUIRE_PACKAGES_FCL-XML=1
+REQUIRE_PACKAGES_FCL-JSON=1
+endif
+ifeq ($(FULL_TARGET),i386-embedded)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+REQUIRE_PACKAGES_FCL-XML=1
+REQUIRE_PACKAGES_FCL-JSON=1
+endif
+ifeq ($(FULL_TARGET),i386-symbian)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+REQUIRE_PACKAGES_FCL-XML=1
+REQUIRE_PACKAGES_FCL-JSON=1
+endif
+ifeq ($(FULL_TARGET),m68k-linux)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+REQUIRE_PACKAGES_ICONVENC=1
+REQUIRE_PACKAGES_FCL-XML=1
+REQUIRE_PACKAGES_FCL-JSON=1
+endif
+ifeq ($(FULL_TARGET),m68k-freebsd)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+REQUIRE_PACKAGES_ICONVENC=1
+REQUIRE_PACKAGES_FCL-XML=1
+REQUIRE_PACKAGES_FCL-JSON=1
+endif
+ifeq ($(FULL_TARGET),m68k-netbsd)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+REQUIRE_PACKAGES_FCL-XML=1
+REQUIRE_PACKAGES_FCL-JSON=1
+endif
+ifeq ($(FULL_TARGET),m68k-amiga)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+REQUIRE_PACKAGES_FCL-XML=1
+REQUIRE_PACKAGES_FCL-JSON=1
+endif
+ifeq ($(FULL_TARGET),m68k-atari)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+REQUIRE_PACKAGES_FCL-XML=1
+REQUIRE_PACKAGES_FCL-JSON=1
+endif
+ifeq ($(FULL_TARGET),m68k-openbsd)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+REQUIRE_PACKAGES_FCL-XML=1
+REQUIRE_PACKAGES_FCL-JSON=1
+endif
+ifeq ($(FULL_TARGET),m68k-palmos)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+REQUIRE_PACKAGES_FCL-XML=1
+REQUIRE_PACKAGES_FCL-JSON=1
+endif
+ifeq ($(FULL_TARGET),m68k-embedded)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+REQUIRE_PACKAGES_FCL-XML=1
+REQUIRE_PACKAGES_FCL-JSON=1
+endif
+ifeq ($(FULL_TARGET),powerpc-linux)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+REQUIRE_PACKAGES_ICONVENC=1
+REQUIRE_PACKAGES_FCL-XML=1
+REQUIRE_PACKAGES_FCL-JSON=1
+endif
+ifeq ($(FULL_TARGET),powerpc-netbsd)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+REQUIRE_PACKAGES_FCL-XML=1
+REQUIRE_PACKAGES_FCL-JSON=1
+endif
+ifeq ($(FULL_TARGET),powerpc-amiga)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+REQUIRE_PACKAGES_FCL-XML=1
+REQUIRE_PACKAGES_FCL-JSON=1
+endif
+ifeq ($(FULL_TARGET),powerpc-macos)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+REQUIRE_PACKAGES_FCL-XML=1
+REQUIRE_PACKAGES_FCL-JSON=1
+endif
+ifeq ($(FULL_TARGET),powerpc-darwin)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_UNIVINT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+REQUIRE_PACKAGES_ICONVENC=1
+REQUIRE_PACKAGES_FCL-XML=1
+REQUIRE_PACKAGES_FCL-JSON=1
+endif
+ifeq ($(FULL_TARGET),powerpc-morphos)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+REQUIRE_PACKAGES_FCL-XML=1
+REQUIRE_PACKAGES_FCL-JSON=1
+endif
+ifeq ($(FULL_TARGET),powerpc-embedded)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+REQUIRE_PACKAGES_FCL-XML=1
+REQUIRE_PACKAGES_FCL-JSON=1
+endif
+ifeq ($(FULL_TARGET),sparc-linux)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+REQUIRE_PACKAGES_ICONVENC=1
+REQUIRE_PACKAGES_FCL-XML=1
+REQUIRE_PACKAGES_FCL-JSON=1
+endif
+ifeq ($(FULL_TARGET),sparc-netbsd)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+REQUIRE_PACKAGES_FCL-XML=1
+REQUIRE_PACKAGES_FCL-JSON=1
+endif
+ifeq ($(FULL_TARGET),sparc-solaris)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+REQUIRE_PACKAGES_FCL-XML=1
+REQUIRE_PACKAGES_FCL-JSON=1
+endif
+ifeq ($(FULL_TARGET),sparc-embedded)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+REQUIRE_PACKAGES_FCL-XML=1
+REQUIRE_PACKAGES_FCL-JSON=1
+endif
+ifeq ($(FULL_TARGET),x86_64-linux)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+REQUIRE_PACKAGES_ICONVENC=1
+REQUIRE_PACKAGES_FCL-XML=1
+REQUIRE_PACKAGES_FCL-JSON=1
+endif
+ifeq ($(FULL_TARGET),x86_64-freebsd)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+REQUIRE_PACKAGES_ICONVENC=1
+REQUIRE_PACKAGES_FCL-XML=1
+REQUIRE_PACKAGES_FCL-JSON=1
+endif
+ifeq ($(FULL_TARGET),x86_64-darwin)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_UNIVINT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+REQUIRE_PACKAGES_ICONVENC=1
+REQUIRE_PACKAGES_FCL-XML=1
+REQUIRE_PACKAGES_FCL-JSON=1
+endif
+ifeq ($(FULL_TARGET),x86_64-win64)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+REQUIRE_PACKAGES_FCL-XML=1
+REQUIRE_PACKAGES_FCL-JSON=1
+endif
+ifeq ($(FULL_TARGET),x86_64-embedded)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+REQUIRE_PACKAGES_FCL-XML=1
+REQUIRE_PACKAGES_FCL-JSON=1
+endif
+ifeq ($(FULL_TARGET),arm-linux)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+REQUIRE_PACKAGES_ICONVENC=1
+REQUIRE_PACKAGES_FCL-XML=1
+REQUIRE_PACKAGES_FCL-JSON=1
+endif
+ifeq ($(FULL_TARGET),arm-palmos)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+REQUIRE_PACKAGES_FCL-XML=1
+REQUIRE_PACKAGES_FCL-JSON=1
+endif
+ifeq ($(FULL_TARGET),arm-darwin)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_UNIVINT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+REQUIRE_PACKAGES_ICONVENC=1
+REQUIRE_PACKAGES_FCL-XML=1
+REQUIRE_PACKAGES_FCL-JSON=1
+endif
+ifeq ($(FULL_TARGET),arm-wince)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+REQUIRE_PACKAGES_FCL-XML=1
+REQUIRE_PACKAGES_FCL-JSON=1
+endif
+ifeq ($(FULL_TARGET),arm-gba)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+REQUIRE_PACKAGES_FCL-XML=1
+REQUIRE_PACKAGES_FCL-JSON=1
+endif
+ifeq ($(FULL_TARGET),arm-nds)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+REQUIRE_PACKAGES_FCL-XML=1
+REQUIRE_PACKAGES_FCL-JSON=1
+endif
+ifeq ($(FULL_TARGET),arm-embedded)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+REQUIRE_PACKAGES_FCL-XML=1
+REQUIRE_PACKAGES_FCL-JSON=1
+endif
+ifeq ($(FULL_TARGET),arm-symbian)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+REQUIRE_PACKAGES_FCL-XML=1
+REQUIRE_PACKAGES_FCL-JSON=1
+endif
+ifeq ($(FULL_TARGET),powerpc64-linux)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+REQUIRE_PACKAGES_ICONVENC=1
+REQUIRE_PACKAGES_FCL-XML=1
+REQUIRE_PACKAGES_FCL-JSON=1
+endif
+ifeq ($(FULL_TARGET),powerpc64-darwin)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_UNIVINT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+REQUIRE_PACKAGES_ICONVENC=1
+REQUIRE_PACKAGES_FCL-XML=1
+REQUIRE_PACKAGES_FCL-JSON=1
+endif
+ifeq ($(FULL_TARGET),powerpc64-embedded)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+REQUIRE_PACKAGES_FCL-XML=1
+REQUIRE_PACKAGES_FCL-JSON=1
+endif
+ifeq ($(FULL_TARGET),avr-embedded)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+REQUIRE_PACKAGES_FCL-XML=1
+REQUIRE_PACKAGES_FCL-JSON=1
+endif
+ifeq ($(FULL_TARGET),armeb-linux)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+REQUIRE_PACKAGES_ICONVENC=1
+REQUIRE_PACKAGES_FCL-XML=1
+REQUIRE_PACKAGES_FCL-JSON=1
+endif
+ifeq ($(FULL_TARGET),armeb-embedded)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+REQUIRE_PACKAGES_FCL-XML=1
+REQUIRE_PACKAGES_FCL-JSON=1
+endif
+ifdef REQUIRE_PACKAGES_RTL
+PACKAGEDIR_RTL:=$(firstword $(subst /Makefile.fpc,,$(strip $(wildcard $(addsuffix /rtl/Makefile.fpc,$(PACKAGESDIR))))))
+ifneq ($(PACKAGEDIR_RTL),)
+ifneq ($(wildcard $(PACKAGEDIR_RTL)/units/$(TARGETSUFFIX)),)
+UNITDIR_RTL=$(PACKAGEDIR_RTL)/units/$(TARGETSUFFIX)
+else
+UNITDIR_RTL=$(PACKAGEDIR_RTL)
+endif
+ifdef CHECKDEPEND
+$(PACKAGEDIR_RTL)/$(FPCMADE):
+ $(MAKE) -C $(PACKAGEDIR_RTL) $(FPCMADE)
+override ALLDEPENDENCIES+=$(PACKAGEDIR_RTL)/$(FPCMADE)
+endif
+else
+PACKAGEDIR_RTL=
+UNITDIR_RTL:=$(subst /Package.fpc,,$(strip $(wildcard $(addsuffix /rtl/Package.fpc,$(UNITSDIR)))))
+ifneq ($(UNITDIR_RTL),)
+UNITDIR_RTL:=$(firstword $(UNITDIR_RTL))
+else
+UNITDIR_RTL=
+endif
+endif
+ifdef UNITDIR_RTL
+override COMPILER_UNITDIR+=$(UNITDIR_RTL)
+endif
+endif
+ifdef REQUIRE_PACKAGES_FCL-BASE
+PACKAGEDIR_FCL-BASE:=$(firstword $(subst /Makefile.fpc,,$(strip $(wildcard $(addsuffix /fcl-base/Makefile.fpc,$(PACKAGESDIR))))))
+ifneq ($(PACKAGEDIR_FCL-BASE),)
+ifneq ($(wildcard $(PACKAGEDIR_FCL-BASE)/units/$(TARGETSUFFIX)),)
+UNITDIR_FCL-BASE=$(PACKAGEDIR_FCL-BASE)/units/$(TARGETSUFFIX)
+else
+UNITDIR_FCL-BASE=$(PACKAGEDIR_FCL-BASE)
+endif
+ifdef CHECKDEPEND
+$(PACKAGEDIR_FCL-BASE)/$(FPCMADE):
+ $(MAKE) -C $(PACKAGEDIR_FCL-BASE) $(FPCMADE)
+override ALLDEPENDENCIES+=$(PACKAGEDIR_FCL-BASE)/$(FPCMADE)
+endif
+else
+PACKAGEDIR_FCL-BASE=
+UNITDIR_FCL-BASE:=$(subst /Package.fpc,,$(strip $(wildcard $(addsuffix /fcl-base/Package.fpc,$(UNITSDIR)))))
+ifneq ($(UNITDIR_FCL-BASE),)
+UNITDIR_FCL-BASE:=$(firstword $(UNITDIR_FCL-BASE))
+else
+UNITDIR_FCL-BASE=
+endif
+endif
+ifdef UNITDIR_FCL-BASE
+override COMPILER_UNITDIR+=$(UNITDIR_FCL-BASE)
+endif
+endif
+ifdef REQUIRE_PACKAGES_ICONVENC
+PACKAGEDIR_ICONVENC:=$(firstword $(subst /Makefile.fpc,,$(strip $(wildcard $(addsuffix /iconvenc/Makefile.fpc,$(PACKAGESDIR))))))
+ifneq ($(PACKAGEDIR_ICONVENC),)
+ifneq ($(wildcard $(PACKAGEDIR_ICONVENC)/units/$(TARGETSUFFIX)),)
+UNITDIR_ICONVENC=$(PACKAGEDIR_ICONVENC)/units/$(TARGETSUFFIX)
+else
+UNITDIR_ICONVENC=$(PACKAGEDIR_ICONVENC)
+endif
+ifdef CHECKDEPEND
+$(PACKAGEDIR_ICONVENC)/$(FPCMADE):
+ $(MAKE) -C $(PACKAGEDIR_ICONVENC) $(FPCMADE)
+override ALLDEPENDENCIES+=$(PACKAGEDIR_ICONVENC)/$(FPCMADE)
+endif
+else
+PACKAGEDIR_ICONVENC=
+UNITDIR_ICONVENC:=$(subst /Package.fpc,,$(strip $(wildcard $(addsuffix /iconvenc/Package.fpc,$(UNITSDIR)))))
+ifneq ($(UNITDIR_ICONVENC),)
+UNITDIR_ICONVENC:=$(firstword $(UNITDIR_ICONVENC))
+else
+UNITDIR_ICONVENC=
+endif
+endif
+ifdef UNITDIR_ICONVENC
+override COMPILER_UNITDIR+=$(UNITDIR_ICONVENC)
+endif
+endif
+ifdef REQUIRE_PACKAGES_FCL-XML
+PACKAGEDIR_FCL-XML:=$(firstword $(subst /Makefile.fpc,,$(strip $(wildcard $(addsuffix /fcl-xml/Makefile.fpc,$(PACKAGESDIR))))))
+ifneq ($(PACKAGEDIR_FCL-XML),)
+ifneq ($(wildcard $(PACKAGEDIR_FCL-XML)/units/$(TARGETSUFFIX)),)
+UNITDIR_FCL-XML=$(PACKAGEDIR_FCL-XML)/units/$(TARGETSUFFIX)
+else
+UNITDIR_FCL-XML=$(PACKAGEDIR_FCL-XML)
+endif
+ifdef CHECKDEPEND
+$(PACKAGEDIR_FCL-XML)/$(FPCMADE):
+ $(MAKE) -C $(PACKAGEDIR_FCL-XML) $(FPCMADE)
+override ALLDEPENDENCIES+=$(PACKAGEDIR_FCL-XML)/$(FPCMADE)
+endif
+else
+PACKAGEDIR_FCL-XML=
+UNITDIR_FCL-XML:=$(subst /Package.fpc,,$(strip $(wildcard $(addsuffix /fcl-xml/Package.fpc,$(UNITSDIR)))))
+ifneq ($(UNITDIR_FCL-XML),)
+UNITDIR_FCL-XML:=$(firstword $(UNITDIR_FCL-XML))
+else
+UNITDIR_FCL-XML=
+endif
+endif
+ifdef UNITDIR_FCL-XML
+override COMPILER_UNITDIR+=$(UNITDIR_FCL-XML)
+endif
+endif
+ifdef REQUIRE_PACKAGES_FCL-JSON
+PACKAGEDIR_FCL-JSON:=$(firstword $(subst /Makefile.fpc,,$(strip $(wildcard $(addsuffix /fcl-json/Makefile.fpc,$(PACKAGESDIR))))))
+ifneq ($(PACKAGEDIR_FCL-JSON),)
+ifneq ($(wildcard $(PACKAGEDIR_FCL-JSON)/units/$(TARGETSUFFIX)),)
+UNITDIR_FCL-JSON=$(PACKAGEDIR_FCL-JSON)/units/$(TARGETSUFFIX)
+else
+UNITDIR_FCL-JSON=$(PACKAGEDIR_FCL-JSON)
+endif
+ifdef CHECKDEPEND
+$(PACKAGEDIR_FCL-JSON)/$(FPCMADE):
+ $(MAKE) -C $(PACKAGEDIR_FCL-JSON) $(FPCMADE)
+override ALLDEPENDENCIES+=$(PACKAGEDIR_FCL-JSON)/$(FPCMADE)
+endif
+else
+PACKAGEDIR_FCL-JSON=
+UNITDIR_FCL-JSON:=$(subst /Package.fpc,,$(strip $(wildcard $(addsuffix /fcl-json/Package.fpc,$(UNITSDIR)))))
+ifneq ($(UNITDIR_FCL-JSON),)
+UNITDIR_FCL-JSON:=$(firstword $(UNITDIR_FCL-JSON))
+else
+UNITDIR_FCL-JSON=
+endif
+endif
+ifdef UNITDIR_FCL-JSON
+override COMPILER_UNITDIR+=$(UNITDIR_FCL-JSON)
+endif
+endif
+ifdef REQUIRE_PACKAGES_UNIVINT
+PACKAGEDIR_UNIVINT:=$(firstword $(subst /Makefile.fpc,,$(strip $(wildcard $(addsuffix /univint/Makefile.fpc,$(PACKAGESDIR))))))
+ifneq ($(PACKAGEDIR_UNIVINT),)
+ifneq ($(wildcard $(PACKAGEDIR_UNIVINT)/units/$(TARGETSUFFIX)),)
+UNITDIR_UNIVINT=$(PACKAGEDIR_UNIVINT)/units/$(TARGETSUFFIX)
+else
+UNITDIR_UNIVINT=$(PACKAGEDIR_UNIVINT)
+endif
+ifdef CHECKDEPEND
+$(PACKAGEDIR_UNIVINT)/$(FPCMADE):
+ $(MAKE) -C $(PACKAGEDIR_UNIVINT) $(FPCMADE)
+override ALLDEPENDENCIES+=$(PACKAGEDIR_UNIVINT)/$(FPCMADE)
+endif
+else
+PACKAGEDIR_UNIVINT=
+UNITDIR_UNIVINT:=$(subst /Package.fpc,,$(strip $(wildcard $(addsuffix /univint/Package.fpc,$(UNITSDIR)))))
+ifneq ($(UNITDIR_UNIVINT),)
+UNITDIR_UNIVINT:=$(firstword $(UNITDIR_UNIVINT))
+else
+UNITDIR_UNIVINT=
+endif
+endif
+ifdef UNITDIR_UNIVINT
+override COMPILER_UNITDIR+=$(UNITDIR_UNIVINT)
+endif
+endif
+ifndef NOCPUDEF
+override FPCOPTDEF=$(ARCH)
+endif
+ifneq ($(OS_TARGET),$(OS_SOURCE))
+override FPCOPT+=-T$(OS_TARGET)
+endif
+ifneq ($(CPU_TARGET),$(CPU_SOURCE))
+override FPCOPT+=-P$(ARCH)
+endif
+ifeq ($(OS_SOURCE),openbsd)
+override FPCOPT+=-FD$(NEW_BINUTILS_PATH)
+endif
+ifndef CROSSBOOTSTRAP
+ifneq ($(BINUTILSPREFIX),)
+override FPCOPT+=-XP$(BINUTILSPREFIX)
+endif
+ifneq ($(BINUTILSPREFIX),)
+override FPCOPT+=-Xr$(RLINKPATH)
+endif
+endif
+ifdef UNITDIR
+override FPCOPT+=$(addprefix -Fu,$(UNITDIR))
+endif
+ifdef LIBDIR
+override FPCOPT+=$(addprefix -Fl,$(LIBDIR))
+endif
+ifdef OBJDIR
+override FPCOPT+=$(addprefix -Fo,$(OBJDIR))
+endif
+ifdef INCDIR
+override FPCOPT+=$(addprefix -Fi,$(INCDIR))
+endif
+ifdef LINKSMART
+override FPCOPT+=-XX
+endif
+ifdef CREATESMART
+override FPCOPT+=-CX
+endif
+ifdef DEBUG
+override FPCOPT+=-gl
+override FPCOPTDEF+=DEBUG
+endif
+ifdef RELEASE
+ifneq ($(findstring 2.0.,$(FPC_VERSION)),)
+ifeq ($(CPU_TARGET),i386)
+FPCCPUOPT:=-OG2p3
+endif
+ifeq ($(CPU_TARGET),powerpc)
+FPCCPUOPT:=-O1r
+endif
+else
+FPCCPUOPT:=-O2
+endif
+override FPCOPT+=-Ur -Xs $(FPCCPUOPT) -n
+override FPCOPTDEF+=RELEASE
+endif
+ifdef STRIP
+override FPCOPT+=-Xs
+endif
+ifdef OPTIMIZE
+override FPCOPT+=-O2
+endif
+ifdef VERBOSE
+override FPCOPT+=-vwni
+endif
+ifdef COMPILER_OPTIONS
+override FPCOPT+=$(COMPILER_OPTIONS)
+endif
+ifdef COMPILER_UNITDIR
+override FPCOPT+=$(addprefix -Fu,$(COMPILER_UNITDIR))
+endif
+ifdef COMPILER_LIBRARYDIR
+override FPCOPT+=$(addprefix -Fl,$(COMPILER_LIBRARYDIR))
+endif
+ifdef COMPILER_OBJECTDIR
+override FPCOPT+=$(addprefix -Fo,$(COMPILER_OBJECTDIR))
+endif
+ifdef COMPILER_INCLUDEDIR
+override FPCOPT+=$(addprefix -Fi,$(COMPILER_INCLUDEDIR))
+endif
+ifdef CROSSBINDIR
+override FPCOPT+=-FD$(CROSSBINDIR)
+endif
+ifdef COMPILER_TARGETDIR
+override FPCOPT+=-FE$(COMPILER_TARGETDIR)
+ifeq ($(COMPILER_TARGETDIR),.)
+override TARGETDIRPREFIX=
+else
+override TARGETDIRPREFIX=$(COMPILER_TARGETDIR)/
+endif
+endif
+ifdef COMPILER_UNITTARGETDIR
+override FPCOPT+=-FU$(COMPILER_UNITTARGETDIR)
+ifeq ($(COMPILER_UNITTARGETDIR),.)
+override UNITTARGETDIRPREFIX=
+else
+override UNITTARGETDIRPREFIX=$(COMPILER_UNITTARGETDIR)/
+endif
+else
+ifdef COMPILER_TARGETDIR
+override COMPILER_UNITTARGETDIR=$(COMPILER_TARGETDIR)
+override UNITTARGETDIRPREFIX=$(TARGETDIRPREFIX)
+endif
+endif
+ifdef CREATESHARED
+override FPCOPT+=-Cg
+ifeq ($(CPU_TARGET),i386)
+override FPCOPT+=-Aas
+endif
+endif
+ifeq ($(findstring 2.0.,$(FPC_VERSION)),)
+ifeq ($(OS_TARGET),linux)
+ifeq ($(CPU_TARGET),x86_64)
+override FPCOPT+=-Cg
+endif
+endif
+endif
+ifdef LINKSHARED
+endif
+ifdef GCCLIBDIR
+override FPCOPT+=-Fl$(GCCLIBDIR)
+endif
+ifdef OTHERLIBDIR
+override FPCOPT+=$(addprefix -Fl,$(OTHERLIBDIR))
+endif
+ifdef OPT
+override FPCOPT+=$(OPT)
+endif
+ifdef FPCOPTDEF
+override FPCOPT+=$(addprefix -d,$(FPCOPTDEF))
+endif
+ifdef CFGFILE
+override FPCOPT+=@$(CFGFILE)
+endif
+ifdef USEENV
+override FPCEXTCMD:=$(FPCOPT)
+override FPCOPT:=!FPCEXTCMD
+export FPCEXTCMD
+endif
+override AFULL_TARGET=$(CPU_TARGET)-$(OS_TARGET)
+override AFULL_SOURCE=$(CPU_SOURCE)-$(OS_SOURCE)
+ifneq ($(AFULL_TARGET),$(AFULL_SOURCE))
+override ACROSSCOMPILE=1
+endif
+ifdef ACROSSCOMPILE
+override FPCOPT+=$(CROSSOPT)
+endif
+override COMPILER:=$(FPC) $(FPCOPT)
+ifeq (,$(findstring -s ,$(COMPILER)))
+EXECPPAS=
+else
+ifeq ($(FULL_SOURCE),$(FULL_TARGET))
+ifdef RUNBATCH
+EXECPPAS:=@$(RUNBATCH) $(PPAS)
+else
+EXECPPAS:=@$(PPAS)
+endif
+endif
+endif
+.PHONY: fpc_units
+ifneq ($(TARGET_UNITS)$(TARGET_IMPLICITUNITS),)
+override ALLTARGET+=fpc_units
+override UNITPPUFILES=$(addsuffix $(PPUEXT),$(TARGET_UNITS))
+override IMPLICITUNITPPUFILES=$(addsuffix $(PPUEXT),$(TARGET_IMPLICITUNITS))
+override INSTALLPPUFILES+=$(UNITPPUFILES) $(IMPLICITUNITPPUFILES)
+override CLEANPPUFILES+=$(UNITPPUFILES) $(IMPLICITUNITPPUFILES)
+endif
+fpc_units: $(COMPILER_UNITTARGETDIR) $(UNITPPUFILES)
+ifdef TARGET_RSTS
+override RSTFILES=$(addsuffix $(RSTEXT),$(TARGET_RSTS))
+override CLEANRSTFILES+=$(RSTFILES)
+endif
+.PHONY: fpc_all fpc_smart fpc_debug fpc_release fpc_shared
+$(FPCMADE): $(ALLDEPENDENCIES) $(ALLTARGET)
+ @$(ECHOREDIR) Compiled > $(FPCMADE)
+fpc_all: $(FPCMADE)
+fpc_smart:
+ $(MAKE) all LINKSMART=1 CREATESMART=1
+fpc_debug:
+ $(MAKE) all DEBUG=1
+fpc_release:
+ $(MAKE) all RELEASE=1
+.SUFFIXES: $(EXEEXT) $(PPUEXT) $(OEXT) .pas .lpr .dpr .pp .rc .res
+$(COMPILER_UNITTARGETDIR):
+ $(MKDIRTREE) $(COMPILER_UNITTARGETDIR)
+$(COMPILER_TARGETDIR):
+ $(MKDIRTREE) $(COMPILER_TARGETDIR)
+%$(PPUEXT): %.pp
+ $(COMPILER) $<
+ $(EXECPPAS)
+%$(PPUEXT): %.pas
+ $(COMPILER) $<
+ $(EXECPPAS)
+%$(EXEEXT): %.pp
+ $(COMPILER) $<
+ $(EXECPPAS)
+%$(EXEEXT): %.pas
+ $(COMPILER) $<
+ $(EXECPPAS)
+%$(EXEEXT): %.lpr
+ $(COMPILER) $<
+ $(EXECPPAS)
+%$(EXEEXT): %.dpr
+ $(COMPILER) $<
+ $(EXECPPAS)
+%.res: %.rc
+ windres -i $< -o $@
+vpath %.pp $(COMPILER_SOURCEDIR) $(COMPILER_INCLUDEDIR)
+vpath %.pas $(COMPILER_SOURCEDIR) $(COMPILER_INCLUDEDIR)
+vpath %.lpr $(COMPILER_SOURCEDIR) $(COMPILER_INCLUDEDIR)
+vpath %.dpr $(COMPILER_SOURCEDIR) $(COMPILER_INCLUDEDIR)
+vpath %.inc $(COMPILER_INCLUDEDIR)
+vpath %$(OEXT) $(COMPILER_UNITTARGETDIR)
+vpath %$(PPUEXT) $(COMPILER_UNITTARGETDIR)
+.PHONY: fpc_shared
+override INSTALLTARGET+=fpc_shared_install
+ifndef SHARED_LIBVERSION
+SHARED_LIBVERSION=$(FPC_VERSION)
+endif
+ifndef SHARED_LIBNAME
+SHARED_LIBNAME=$(PACKAGE_NAME)
+endif
+ifndef SHARED_FULLNAME
+SHARED_FULLNAME=$(SHAREDLIBPREFIX)$(SHARED_LIBNAME)-$(SHARED_LIBVERSION)$(SHAREDLIBEXT)
+endif
+ifndef SHARED_LIBUNITS
+SHARED_LIBUNITS:=$(TARGET_UNITS) $(TARGET_IMPLICITUNITS)
+override SHARED_LIBUNITS:=$(filter-out $(INSTALL_BUILDUNIT),$(SHARED_LIBUNITS))
+endif
+fpc_shared:
+ifdef HASSHAREDLIB
+ $(MAKE) all CREATESHARED=1 LINKSHARED=1 CREATESMART=1
+ifneq ($(SHARED_BUILD),n)
+ $(PPUMOVE) -q $(SHARED_LIBUNITS) -i$(COMPILER_UNITTARGETDIR) -o$(SHARED_FULLNAME) -d$(COMPILER_UNITTARGETDIR)
+endif
+else
+ @$(ECHO) Shared Libraries not supported
+endif
+fpc_shared_install:
+ifneq ($(SHARED_BUILD),n)
+ifneq ($(SHARED_LIBUNITS),)
+ifneq ($(wildcard $(COMPILER_UNITTARGETDIR)/$(SHARED_FULLNAME)),)
+ $(INSTALL) $(COMPILER_UNITTARGETDIR)/$(SHARED_FULLNAME) $(INSTALL_SHAREDDIR)
+endif
+endif
+endif
+.PHONY: fpc_install fpc_sourceinstall fpc_exampleinstall
+ifdef INSTALL_UNITS
+override INSTALLPPUFILES+=$(addsuffix $(PPUEXT),$(INSTALL_UNITS))
+endif
+ifdef INSTALL_BUILDUNIT
+override INSTALLPPUFILES:=$(filter-out $(INSTALL_BUILDUNIT)$(PPUEXT),$(INSTALLPPUFILES))
+endif
+ifdef INSTALLPPUFILES
+override INSTALLPPULINKFILES:=$(subst $(PPUEXT),$(OEXT),$(INSTALLPPUFILES)) $(addprefix $(STATICLIBPREFIX),$(subst $(PPUEXT),$(STATICLIBEXT),$(INSTALLPPUFILES))) $(addprefix $(IMPORTLIBPREFIX),$(subst $(PPUEXT),$(STATICLIBEXT),$(INSTALLPPUFILES)))
+ifneq ($(UNITTARGETDIRPREFIX),)
+override INSTALLPPUFILES:=$(addprefix $(UNITTARGETDIRPREFIX),$(notdir $(INSTALLPPUFILES)))
+override INSTALLPPULINKFILES:=$(wildcard $(addprefix $(UNITTARGETDIRPREFIX),$(notdir $(INSTALLPPULINKFILES))))
+endif
+override INSTALL_CREATEPACKAGEFPC=1
+endif
+ifdef INSTALLEXEFILES
+ifneq ($(TARGETDIRPREFIX),)
+override INSTALLEXEFILES:=$(addprefix $(TARGETDIRPREFIX),$(notdir $(INSTALLEXEFILES)))
+endif
+endif
+fpc_install: all $(INSTALLTARGET)
+ifdef INSTALLEXEFILES
+ $(MKDIR) $(INSTALL_BINDIR)
+ifdef UPXPROG
+ -$(UPXPROG) $(INSTALLEXEFILES)
+endif
+ $(INSTALLEXE) $(INSTALLEXEFILES) $(INSTALL_BINDIR)
+endif
+ifdef INSTALL_CREATEPACKAGEFPC
+ifdef FPCMAKE
+ifdef PACKAGE_VERSION
+ifneq ($(wildcard Makefile.fpc),)
+ $(FPCMAKE) -p -T$(CPU_TARGET)-$(OS_TARGET) Makefile.fpc
+ $(MKDIR) $(INSTALL_UNITDIR)
+ $(INSTALL) Package.fpc $(INSTALL_UNITDIR)
+endif
+endif
+endif
+endif
+ifdef INSTALLPPUFILES
+ $(MKDIR) $(INSTALL_UNITDIR)
+ $(INSTALL) $(INSTALLPPUFILES) $(INSTALL_UNITDIR)
+ifneq ($(INSTALLPPULINKFILES),)
+ $(INSTALL) $(INSTALLPPULINKFILES) $(INSTALL_UNITDIR)
+endif
+ifneq ($(wildcard $(LIB_FULLNAME)),)
+ $(MKDIR) $(INSTALL_LIBDIR)
+ $(INSTALL) $(LIB_FULLNAME) $(INSTALL_LIBDIR)
+ifdef inUnix
+ ln -sf $(LIB_FULLNAME) $(INSTALL_LIBDIR)/$(LIB_NAME)
+endif
+endif
+endif
+ifdef INSTALL_FILES
+ $(MKDIR) $(INSTALL_DATADIR)
+ $(INSTALL) $(INSTALL_FILES) $(INSTALL_DATADIR)
+endif
+fpc_sourceinstall: distclean
+ $(MKDIR) $(INSTALL_SOURCEDIR)
+ $(COPYTREE) $(BASEDIR)/* $(INSTALL_SOURCEDIR)
+fpc_exampleinstall: $(addsuffix _distclean,$(TARGET_EXAMPLEDIRS))
+ifdef HASEXAMPLES
+ $(MKDIR) $(INSTALL_EXAMPLEDIR)
+endif
+ifdef EXAMPLESOURCEFILES
+ $(COPY) $(EXAMPLESOURCEFILES) $(INSTALL_EXAMPLEDIR)
+endif
+ifdef TARGET_EXAMPLEDIRS
+ $(COPYTREE) $(addsuffix /*,$(TARGET_EXAMPLEDIRS)) $(INSTALL_EXAMPLEDIR)
+endif
+.PHONY: fpc_clean fpc_cleanall fpc_distclean
+ifdef EXEFILES
+override CLEANEXEFILES:=$(addprefix $(TARGETDIRPREFIX),$(CLEANEXEFILES))
+endif
+ifdef CLEAN_UNITS
+override CLEANPPUFILES+=$(addsuffix $(PPUEXT),$(CLEAN_UNITS))
+endif
+ifdef CLEANPPUFILES
+override CLEANPPULINKFILES:=$(subst $(PPUEXT),$(OEXT),$(CLEANPPUFILES)) $(addprefix $(STATICLIBPREFIX),$(subst $(PPUEXT),$(STATICLIBEXT),$(CLEANPPUFILES))) $(addprefix $(IMPORTLIBPREFIX),$(subst $(PPUEXT),$(STATICLIBEXT),$(CLEANPPUFILES)))
+ifdef DEBUGSYMEXT
+override CLEANPPULINKFILES+=$(subst $(PPUEXT),$(DEBUGSYMEXT),$(CLEANPPUFILES))
+endif
+override CLEANPPUFILES:=$(addprefix $(UNITTARGETDIRPREFIX),$(CLEANPPUFILES))
+override CLEANPPULINKFILES:=$(wildcard $(addprefix $(UNITTARGETDIRPREFIX),$(CLEANPPULINKFILES)))
+endif
+fpc_clean: $(CLEANTARGET)
+ifdef CLEANEXEFILES
+ -$(DEL) $(CLEANEXEFILES)
+endif
+ifdef CLEANPPUFILES
+ -$(DEL) $(CLEANPPUFILES)
+endif
+ifneq ($(CLEANPPULINKFILES),)
+ -$(DEL) $(CLEANPPULINKFILES)
+endif
+ifdef CLEANRSTFILES
+ -$(DEL) $(addprefix $(UNITTARGETDIRPREFIX),$(CLEANRSTFILES))
+endif
+ifdef CLEAN_FILES
+ -$(DEL) $(CLEAN_FILES)
+endif
+ifdef LIB_NAME
+ -$(DEL) $(LIB_NAME) $(LIB_FULLNAME)
+endif
+ -$(DEL) $(FPCMADE) Package.fpc $(PPAS) script.res link.res $(FPCEXTFILE) $(REDIRFILE)
+ -$(DEL) *$(ASMEXT) *_ppas$(BATCHEXT)
+fpc_cleanall: $(CLEANTARGET)
+ifdef CLEANEXEFILES
+ -$(DEL) $(CLEANEXEFILES)
+endif
+ifdef COMPILER_UNITTARGETDIR
+ifdef CLEANPPUFILES
+ -$(DEL) $(CLEANPPUFILES)
+endif
+ifneq ($(CLEANPPULINKFILES),)
+ -$(DEL) $(CLEANPPULINKFILES)
+endif
+ifdef CLEANRSTFILES
+ -$(DEL) $(addprefix $(UNITTARGETDIRPREFIX),$(CLEANRSTFILES))
+endif
+endif
+ -$(DELTREE) units
+ -$(DEL) *$(OEXT) *$(PPUEXT) *$(RSTEXT) *$(ASMEXT) *$(STATICLIBEXT) *$(SHAREDLIBEXT) *$(PPLEXT)
+ifneq ($(PPUEXT),.ppu)
+ -$(DEL) *.o *.ppu *.a
+endif
+ -$(DELTREE) *$(SMARTEXT)
+ -$(DEL) fpcmade.* Package.fpc $(PPAS) script.res link.res $(FPCEXTFILE) $(REDIRFILE)
+ -$(DEL) *_ppas$(BATCHEXT)
+ifdef AOUTEXT
+ -$(DEL) *$(AOUTEXT)
+endif
+ifdef DEBUGSYMEXT
+ -$(DEL) *$(DEBUGSYMEXT)
+endif
+fpc_distclean: cleanall
+.PHONY: fpc_baseinfo
+override INFORULES+=fpc_baseinfo
+fpc_baseinfo:
+ @$(ECHO)
+ @$(ECHO) == Package info ==
+ @$(ECHO) Package Name..... $(PACKAGE_NAME)
+ @$(ECHO) Package Version.. $(PACKAGE_VERSION)
+ @$(ECHO)
+ @$(ECHO) == Configuration info ==
+ @$(ECHO)
+ @$(ECHO) FPC.......... $(FPC)
+ @$(ECHO) FPC Version.. $(FPC_VERSION)
+ @$(ECHO) Source CPU... $(CPU_SOURCE)
+ @$(ECHO) Target CPU... $(CPU_TARGET)
+ @$(ECHO) Source OS.... $(OS_SOURCE)
+ @$(ECHO) Target OS.... $(OS_TARGET)
+ @$(ECHO) Full Source.. $(FULL_SOURCE)
+ @$(ECHO) Full Target.. $(FULL_TARGET)
+ @$(ECHO) SourceSuffix. $(SOURCESUFFIX)
+ @$(ECHO) TargetSuffix. $(TARGETSUFFIX)
+ @$(ECHO)
+ @$(ECHO) == Directory info ==
+ @$(ECHO)
+ @$(ECHO) Required pkgs... $(REQUIRE_PACKAGES)
+ @$(ECHO)
+ @$(ECHO) Basedir......... $(BASEDIR)
+ @$(ECHO) FPCDir.......... $(FPCDIR)
+ @$(ECHO) CrossBinDir..... $(CROSSBINDIR)
+ @$(ECHO) UnitsDir........ $(UNITSDIR)
+ @$(ECHO) PackagesDir..... $(PACKAGESDIR)
+ @$(ECHO)
+ @$(ECHO) GCC library..... $(GCCLIBDIR)
+ @$(ECHO) Other library... $(OTHERLIBDIR)
+ @$(ECHO)
+ @$(ECHO) == Tools info ==
+ @$(ECHO)
+ @$(ECHO) As........ $(AS)
+ @$(ECHO) Ld........ $(LD)
+ @$(ECHO) Ar........ $(AR)
+ @$(ECHO) Rc........ $(RC)
+ @$(ECHO)
+ @$(ECHO) Mv........ $(MVPROG)
+ @$(ECHO) Cp........ $(CPPROG)
+ @$(ECHO) Rm........ $(RMPROG)
+ @$(ECHO) GInstall.. $(GINSTALL)
+ @$(ECHO) Echo...... $(ECHO)
+ @$(ECHO) Shell..... $(SHELL)
+ @$(ECHO) Date...... $(DATE)
+ @$(ECHO) FPCMake... $(FPCMAKE)
+ @$(ECHO) PPUMove... $(PPUMOVE)
+ @$(ECHO) Upx....... $(UPXPROG)
+ @$(ECHO) Zip....... $(ZIPPROG)
+ @$(ECHO)
+ @$(ECHO) == Object info ==
+ @$(ECHO)
+ @$(ECHO) Target Loaders........ $(TARGET_LOADERS)
+ @$(ECHO) Target Units.......... $(TARGET_UNITS)
+ @$(ECHO) Target Implicit Units. $(TARGET_IMPLICITUNITS)
+ @$(ECHO) Target Programs....... $(TARGET_PROGRAMS)
+ @$(ECHO) Target Dirs........... $(TARGET_DIRS)
+ @$(ECHO) Target Examples....... $(TARGET_EXAMPLES)
+ @$(ECHO) Target ExampleDirs.... $(TARGET_EXAMPLEDIRS)
+ @$(ECHO)
+ @$(ECHO) Clean Units......... $(CLEAN_UNITS)
+ @$(ECHO) Clean Files......... $(CLEAN_FILES)
+ @$(ECHO)
+ @$(ECHO) Install Units....... $(INSTALL_UNITS)
+ @$(ECHO) Install Files....... $(INSTALL_FILES)
+ @$(ECHO)
+ @$(ECHO) == Install info ==
+ @$(ECHO)
+ @$(ECHO) DateStr.............. $(DATESTR)
+ @$(ECHO) ZipName.............. $(ZIPNAME)
+ @$(ECHO) ZipPrefix............ $(ZIPPREFIX)
+ @$(ECHO) ZipCrossPrefix....... $(ZIPCROSSPREFIX)
+ @$(ECHO) ZipSuffix............ $(ZIPSUFFIX)
+ @$(ECHO) FullZipName.......... $(FULLZIPNAME)
+ @$(ECHO) Install FPC Package.. $(INSTALL_FPCPACKAGE)
+ @$(ECHO)
+ @$(ECHO) Install base dir..... $(INSTALL_BASEDIR)
+ @$(ECHO) Install binary dir... $(INSTALL_BINDIR)
+ @$(ECHO) Install library dir.. $(INSTALL_LIBDIR)
+ @$(ECHO) Install units dir.... $(INSTALL_UNITDIR)
+ @$(ECHO) Install source dir... $(INSTALL_SOURCEDIR)
+ @$(ECHO) Install doc dir...... $(INSTALL_DOCDIR)
+ @$(ECHO) Install example dir.. $(INSTALL_EXAMPLEDIR)
+ @$(ECHO) Install data dir..... $(INSTALL_DATADIR)
+ @$(ECHO)
+ @$(ECHO) Dist destination dir. $(DIST_DESTDIR)
+ @$(ECHO) Dist zip name........ $(DIST_ZIPNAME)
+ @$(ECHO)
+.PHONY: fpc_info
+fpc_info: $(INFORULES)
+.PHONY: fpc_makefile fpc_makefiles fpc_makefile_sub1 fpc_makefile_sub2 \
+ fpc_makefile_dirs
+fpc_makefile:
+ $(FPCMAKE) -w -T$(OS_TARGET) Makefile.fpc
+fpc_makefile_sub1:
+ifdef TARGET_DIRS
+ $(FPCMAKE) -w -T$(OS_TARGET) $(addsuffix /Makefile.fpc,$(TARGET_DIRS))
+endif
+ifdef TARGET_EXAMPLEDIRS
+ $(FPCMAKE) -w -T$(OS_TARGET) $(addsuffix /Makefile.fpc,$(TARGET_EXAMPLEDIRS))
+endif
+fpc_makefile_sub2: $(addsuffix _makefile_dirs,$(TARGET_DIRS) $(TARGET_EXAMPLEDIRS))
+fpc_makefile_dirs: fpc_makefile_sub1 fpc_makefile_sub2
+fpc_makefiles: fpc_makefile fpc_makefile_dirs
+all: fpc_all
+debug: fpc_debug
+smart: fpc_smart
+release: fpc_release
+units: fpc_units
+examples:
+shared: fpc_shared
+install: fpc_install
+sourceinstall: fpc_sourceinstall
+exampleinstall: fpc_exampleinstall
+distinstall:
+zipinstall:
+zipsourceinstall:
+zipexampleinstall:
+zipdistinstall:
+clean: fpc_clean
+distclean: fpc_distclean
+cleanall: fpc_cleanall
+info: fpc_info
+makefiles: fpc_makefiles
+.PHONY: all debug smart release units examples shared install sourceinstall exampleinstall distinstall zipinstall zipsourceinstall zipexampleinstall zipdistinstall clean distclean cleanall info makefiles
+ifneq ($(wildcard fpcmake.loc),)
+include fpcmake.loc
+endif
+.NOTPARALLEL:
diff --git a/packages/fcl-web/src/jsonrpc/Makefile.fpc b/packages/fcl-web/src/jsonrpc/Makefile.fpc
new file mode 100644
index 0000000000..bbe278e9fc
--- /dev/null
+++ b/packages/fcl-web/src/jsonrpc/Makefile.fpc
@@ -0,0 +1,26 @@
+#
+# Makefile.fpc for FCL Web components
+#
+
+[package]
+main=fcl-web
+version=2.5.1
+
+[target]
+units=fpjsonrpc webjsonrpc fpextdirect
+
+[require]
+packages=fcl-base fcl-xml fcl-json
+
+[compiler]
+options=-S2h
+
+[install]
+fpcpackage=y
+
+[default]
+fpcdir=../../../..
+
+
+[rules]
+.NOTPARALLEL:
diff --git a/packages/fcl-web/src/jsonrpc/fpextdirect.pp b/packages/fcl-web/src/jsonrpc/fpextdirect.pp
new file mode 100644
index 0000000000..b080b86f90
--- /dev/null
+++ b/packages/fcl-web/src/jsonrpc/fpextdirect.pp
@@ -0,0 +1,416 @@
+unit fpextdirect;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+ Classes, SysUtils, fpjson, fpjsonrpc, webjsonrpc, httpdefs,websession;
+
+Const
+ DefaultExtDirectOptions = DefaultDispatchOptions + [jdoRequireClass];
+
+Type
+ { TCustomExtDirectDispatcher }
+
+ TCustomExtDirectDispatcher = Class(TCustomJSONRPCDispatcher)
+ private
+ FAPIType: String;
+ FNameSpace: String;
+ FURL: String;
+ function GetNameSpace: String;
+ function isNameSpaceStored: boolean;
+ Protected
+ function FormatResult(const AClassName, AMethodName: TJSONStringType;
+ const Params, ID, Return: TJSONData): TJSONData; override;
+ // 'tid'
+ Class Function TransactionProperty : String; override;
+ // 'method'
+ Class Function MethodProperty : String; override;
+ // 'action'
+ Class Function ClassNameProperty : String; override;
+ // 'data'
+ Class Function ParamsProperty : String; override;
+ // Add session support
+ Function FindHandler(Const AClassName,AMethodName : TJSONStringType;AContext : TJSONRPCCallContext; Out FreeObject : TComponent) : TCustomJSONRPCHandler; override;
+ // Create API
+ Function DoAPI : TJSONData; virtual;
+ // Namespace for API description. Must be set. Default 'FPWeb'
+ Property NameSpace : String Read GetNameSpace Write FNameSpace Stored isNameSpaceStored;
+ // URL property for router. Must be set
+ Property URL : String Read FURL Write FURL;
+ // "type". By default: 'remoting'
+ Property APIType : String Read FAPIType Write FAPIType;
+ Public
+ // Override to set additional opions.
+ Constructor Create(AOwner : TComponent); override;
+ // Return API description object
+ Function API: TJSONData;
+ // Return API Description including namespace, as a string
+ Function APIAsString : String;
+ end;
+
+ { TExtDirectDispatcher }
+
+ TExtDirectDispatcher = Class(TCustomExtDirectDispatcher)
+ Published
+ Property NameSpace;
+ Property URL;
+ Property APIType;
+ Property OnStartBatch;
+ Property OnDispatchRequest;
+ Property OnFindHandler;
+ Property OnEndBatch;
+ Property Options;
+ end;
+
+ { TCustomExtDirectContentProducer }
+
+ TCustomExtDirectContentProducer = Class(TCustomJSONRPCContentProducer)
+ Protected
+ Function GetIDProperty : String; override;
+ Procedure DoGetContent(ARequest : TRequest; Content : TStream; Var Handled : Boolean); override;
+ end;
+
+ { TExtDirectContentProducer }
+
+ TExtDirectContentProducer = Class(TCustomExtDirectContentProducer)
+ private
+ FDispatcher: TCustomExtDirectDispatcher;
+ procedure SetDispatcher(const AValue: TCustomExtDirectDispatcher);
+ Protected
+ Function GetDispatcher : TCustomJSONRPCDispatcher; override;
+ procedure Notification(AComponent: TComponent; Operation: TOperation);override;
+ Published
+ Property Dispatcher : TCustomExtDirectDispatcher Read FDispatcher Write SetDispatcher;
+ end;
+
+ { TCustomExtDirectModule }
+
+ TCustomExtDirectModule = Class(TJSONRPCDispatchModule)
+ private
+ FAPIPath: String;
+ FDispatcher: TCustomExtDirectDispatcher;
+ FOptions: TJSONRPCDispatchOptions;
+ FRequest: TRequest;
+ FResponse: TResponse;
+ FRouterPath: String;
+ procedure SetDispatcher(const AValue: TCustomExtDirectDispatcher);
+ Protected
+ // Create API
+ procedure CreateAPI(ADispatcher: TCustomExtDirectDispatcher; ARequest: TRequest; AResponse: TResponse); virtual;
+ Function CreateDispatcher : TCustomExtDirectDispatcher; virtual;
+ Property Dispatcher : TCustomExtDirectDispatcher Read FDispatcher Write SetDispatcher;
+ Property DispatchOptions : TJSONRPCDispatchOptions Read FOptions Write FOptions default DefaultDispatchOptions;
+ procedure Notification(AComponent: TComponent; Operation: TOperation);override;
+ Public
+ Constructor CreateNew(AOwner : TComponent; CreateMode : Integer); override;
+ Procedure HandleRequest(ARequest : TRequest; AResponse : TResponse); override;
+ // Access to request
+ Property Request: TRequest Read FRequest;
+ // Access to response
+ Property Response: TResponse Read FResponse;
+ // API path/action. Append to BaseURL to get API. Default 'API'
+ Property APIPath : String Read FAPIPath Write FAPIPath;
+ // Router path/action. Append to baseURL to get router. Default 'router'
+ Property RouterPath : String Read FRouterPath Write FRouterPath;
+ end;
+
+ TExtDirectModule = Class(TCustomExtDirectModule)
+ Published
+ Property APIPath;
+ Property RouterPath;
+ end;
+
+implementation
+
+Resourcestring
+ SErrInvalidPath = 'Invalid path';
+
+{ TCustomExtDirectDispatcher }
+Const
+ DefaultNameSpace = 'FPWeb';
+
+function TCustomExtDirectDispatcher.GetNameSpace: String;
+begin
+ Result:=FNameSpace;
+ If (Result='') then
+ Result:=DefaultNameSpace
+end;
+
+function TCustomExtDirectDispatcher.isNameSpaceStored: boolean;
+begin
+ Result:=NameSpace<>DefaultNameSpace;
+end;
+
+function TCustomExtDirectDispatcher.FormatResult(Const AClassName, AMethodName: TJSONStringType;
+Const Params,ID, Return : TJSONData) : TJSONData;
+
+begin
+ Result:=Inherited FormatResult(AClassName,AMethodName,Params,ID,Return);
+ TJSONObject(Result).Add('type','rpc');
+ TJSONObject(Result).Add('action',AClassName);
+ TJSONObject(Result).Add('method',AMethodName);
+end;
+
+class function TCustomExtDirectDispatcher.TransactionProperty: String;
+begin
+ Result:='tid';
+end;
+
+class function TCustomExtDirectDispatcher.MethodProperty: String;
+begin
+ Result:='method';
+end;
+
+class function TCustomExtDirectDispatcher.ClassNameProperty: String;
+begin
+ Result:='action';
+end;
+
+class function TCustomExtDirectDispatcher.ParamsProperty: String;
+begin
+ Result:='data';
+end;
+
+function TCustomExtDirectDispatcher.FindHandler(const AClassName,
+ AMethodName: TJSONStringType; AContext: TJSONRPCCallContext; out
+ FreeObject: TComponent): TCustomJSONRPCHandler;
+begin
+ Result:=inherited FindHandler(AClassName, AMethodName, AContext, FreeObject);
+ If (AContext is TJSONRPCSessionContext) and (FreeObject is TCustomJSONRPCModule) then
+ TCustomJSONRPCModule(FreeObject).Session:=TJSONRPCSessionContext(AContext).Session;
+end;
+
+function TCustomExtDirectDispatcher.DoAPI: TJSONData;
+
+Var
+ A,D : TJSONObject;
+ R : TJSONArray;
+ N : TJSONStringType;
+ H : TCustomJSONRPCHandler;
+ I,J : Integer;
+ M : TCustomJSONRPCHandlerManager;
+ HD : TJSONRPCHandlerDef;
+
+begin
+ D:=TJSONObject.Create;
+ try
+ D.Add('url',URL);
+ D.Add('type',APIType);
+ A:=TJSONObject.Create;
+ D.Add('actions',A);
+ R:=Nil;
+ N:='';
+ If (jdoSearchOwner in Options) and Assigned(Owner) then
+ begin
+ for I:=Owner.ComponentCount-1 downto 0 do
+ If Owner.Components[i] is TCustomJSONRPCHandler then
+ begin
+ If (R=Nil) then
+ begin
+ N:=Owner.Name;
+ R:=TJSONArray.Create;
+ A.Add(N,R);
+ end;
+ H:=Owner.Components[i] as TCustomJSONRPCHandler;
+ R.Add(TJSONObject.Create(['name',H.Name,'len',H.ParamDefs.Count]));
+ end;
+ end;
+ If (jdoSearchRegistry in Options) then
+ begin
+ M:=JSONRPCHandlerManager;
+ For I:=M.HandlerCount-1 downto 0 do
+ begin
+ HD:=M.HandlerDefs[i];
+ If (R=Nil) or (CompareText(N,HD.HandlerClassName)<>0) then
+ begin
+ N:=HD.HandlerClassName;
+ J:=A.IndexOf(R);
+ If (J=-1) then
+ begin
+ R:=TJSONArray.Create;
+ A.Add(N,R);
+ end
+ else
+ R:=A.Items[i] as TJSONArray;
+ end;
+ R.Add(TJSONObject.Create(['name',HD.HandlerMethodName,'len',HD.ArgumentCount]));
+ end;
+ end;
+ Result:=D;
+ except
+ FreeAndNil(D);
+ Raise;
+ end;
+end;
+
+constructor TCustomExtDirectDispatcher.Create(AOwner: TComponent);
+
+Var
+ O : TJSONRPCDispatchOptions;
+
+begin
+ inherited Create(AOwner);
+ Options:=DefaultExtDirectOptions;
+ APIType:='remoting';
+end;
+
+function TCustomExtDirectDispatcher.API: TJSONData;
+begin
+ Result:=DoAPI;
+end;
+
+function TCustomExtDirectDispatcher.APIAsString: String;
+
+Var
+ A : TJSONData;
+
+begin
+ A:=API;
+ try
+ Result:=NameSpace + ' = ' + A.AsJSON + ';';
+ finally
+ A.Free;
+ end;
+end;
+
+
+{ TCustomExtDirectContentProducer }
+
+function TCustomExtDirectContentProducer.GetIDProperty: String;
+begin
+ Result:='tid';
+end;
+
+procedure TCustomExtDirectContentProducer.DoGetContent(ARequest: TRequest;
+ Content: TStream; var Handled: Boolean);
+
+Var
+ A,R: String;
+
+begin
+ A:=ARequest.GetNextPathInfo;
+ If (A<>'router') then
+ begin
+ R:=TCustomExtDirectDispatcher(GetDispatcher).APIAsString;
+ Content.WriteBuffer(R[1],Length(R));
+ Handled:=True;
+ end
+ else
+ inherited DoGetContent(ARequest, Content, Handled);
+end;
+
+{ TExtDirectContentProducer }
+
+procedure TExtDirectContentProducer.SetDispatcher(
+ const AValue: TCustomExtDirectDispatcher);
+begin
+ if FDispatcher=AValue then exit;
+ If Assigned(FDispatcher) then
+ FDispatcher.RemoveFreeNotification(Self);
+ FDispatcher:=AValue;
+ If Assigned(FDispatcher) then
+ FDispatcher.FreeNotification(Self);
+end;
+
+function TExtDirectContentProducer.GetDispatcher: TCustomJSONRPCDispatcher;
+begin
+ Result:=FDispatcher;
+end;
+
+procedure TExtDirectContentProducer.Notification(AComponent: TComponent;
+ Operation: TOperation);
+begin
+ inherited Notification(AComponent, Operation);
+ If (Operation=opRemove) and (AComponent=FDispatcher) then
+ FDispatcher:=Nil;
+end;
+
+{ TCustomExtDirectModule }
+
+procedure TCustomExtDirectModule.SetDispatcher(
+ const AValue: TCustomExtDirectDispatcher);
+begin
+ if FDispatcher=AValue then exit;
+ If Assigned(FDispatcher) then
+ FDispatcher.RemoveFreeNotification(Self);
+ FDispatcher:=AValue;
+ If Assigned(FDispatcher) then
+ FDispatcher.FreeNotification(Self);
+end;
+
+function TCustomExtDirectModule.CreateDispatcher: TCustomExtDirectDispatcher;
+
+Var
+ E : TExtDirectDispatcher;
+
+begin
+ E:=TExtDirectDispatcher.Create(Self);
+ E.Options:=DispatchOptions;
+ E.URL:=IncludeHTTPPathDelimiter(BaseURL)+RouterPath;
+ Result:=E
+end;
+
+procedure TCustomExtDirectModule.Notification(AComponent: TComponent;
+ Operation: TOperation);
+begin
+ inherited Notification(AComponent, Operation);
+ If (Operation=opRemove) and (AComponent=FDispatcher) then
+ FDispatcher:=Nil;
+end;
+
+constructor TCustomExtDirectModule.CreateNew(AOwner: TComponent;
+ CreateMode: Integer);
+begin
+ inherited CreateNew(AOwner, CreateMode);
+ FOptions:=DefaultDispatchOptions+[jdoSearchRegistry];
+end;
+
+procedure TCustomExtDirectModule.CreateAPI(ADispatcher : TCustomExtDirectDispatcher; ARequest: TRequest; AResponse: TResponse);
+
+
+begin
+ AResponse.Content:=ADispatcher.APIAsString;
+ AResponse.ContentLength:=Length(AResponse.Content);
+
+end;
+
+procedure TCustomExtDirectModule.HandleRequest(ARequest: TRequest;
+ AResponse: TResponse);
+
+Var
+ Disp : TCustomExtDirectDispatcher;
+ Req,res : TJSONData;
+ R : String;
+
+begin
+ If (Dispatcher=Nil) then
+ Dispatcher:=CreateDispatcher;
+ Disp:=Dispatcher as TCustomExtDirectDispatcher;
+ R:=ARequest.QueryFields.Values['action'];
+ If (R='') then
+ ARequest.GetNextPathInfo;
+ If (CompareText(R,APIPath)=0) then
+ begin
+ CreateAPI(Disp,ARequest,AResponse);
+ AResponse.SendResponse;
+ end
+ else if (CompareText(R,RouterPath)=0) then
+ begin
+ Res:=DispatchRequest(ARequest,Disp);
+ try
+ If Assigned(Res) then
+ AResponse.Content:=Res.AsJSON;
+ AResponse.SendResponse;
+ finally
+ Res.Free;
+ end;
+ AResponse.SendResponse;
+ end
+ else
+ JSONRPCError(SErrInvalidPath);
+end;
+
+end.
+
diff --git a/packages/fcl-web/src/jsonrpc/fpjsonrpc.pp b/packages/fcl-web/src/jsonrpc/fpjsonrpc.pp
new file mode 100644
index 0000000000..028d19791e
--- /dev/null
+++ b/packages/fcl-web/src/jsonrpc/fpjsonrpc.pp
@@ -0,0 +1,1230 @@
+unit fpjsonrpc;
+
+{$mode objfpc}{$H+}
+{$inline on}
+
+interface
+
+uses
+ Classes, SysUtils, fpjson;
+
+Type
+
+{ ---------------------------------------------------------------------
+ JSON-RPC Handler support
+ ---------------------------------------------------------------------}
+
+ { TJSONParamDef }
+
+ TJSONParamDef = Class(TCollectionItem)
+ private
+ FName: TJSONStringType;
+ FRequired: Boolean;
+ FType: TJSONtype;
+ procedure SetName(const AValue: TJSONStringType);
+ public
+ Constructor Create(ACollection : TCollection); override;
+ Published
+ Property Name : TJSONStringType Read FName Write SetName;
+ Property DataType : TJSONtype Read FType Write FType default jtString;
+ Property Required : Boolean Read FRequired Write FRequired default True;
+ end;
+
+ { TJSONParamDefs }
+
+ TJSONParamDefs = Class(TCollection)
+ private
+ function GetP(AIndex : Integer): TJSONParamDef;
+ procedure SetP(AIndex : Integer; const AValue: TJSONParamDef);
+ Public
+ Function AddParamDef(Const AName : TJSONStringType; AType : TJSONType = jtString) : TJSONParamDef;
+ Function IndexOfParamDef(Const AName : TJSONStringType) : Integer;
+ Function FindParamDef(Const AName : TJSONStringType) : TJSONParamDef;
+ Function ParamDefByName(Const AName : TJSONStringType) : TJSONParamDef;
+ Property ParamDefs[AIndex : Integer] : TJSONParamDef Read GetP Write SetP; default;
+ end;
+
+ { TCustomJSONRPCHandler }
+ TJSONParamErrorEvent = Procedure (Sender : TObject; Const E : Exception; Var Fatal : boolean) of Object;
+ TJSONRPCOption = (jroCheckParams,jroObjectParams,jroArrayParams);
+ TJSONRPCOptions = set of TJSONRPCOption;
+
+ TJSONRPCCallContext = Class(TObject);
+
+ TCustomJSONRPCHandler = Class(TComponent)
+ private
+ FAfterExecute: TNotifyEvent;
+ FBeforeExecute: TNotifyEvent;
+ FOnParamError: TJSONParamErrorEvent;
+ FOptions: TJSONRPCOptions;
+ FParamDefs: TJSONParamDefs;
+ procedure SetParamDefs(const AValue: TJSONParamDefs);
+ Protected
+ function CreateParamDefs: TJSONParamDefs; virtual;
+ Procedure DoCheckParams(Const Params : TJSONData); virtual;
+ Function DoExecute(Const Params : TJSONData; AContext : TJSONRPCCallContext): TJSONData; virtual;
+ Property BeforeExecute : TNotifyEvent Read FBeforeExecute Write FBeforeExecute;
+ Property AfterExecute : TNotifyEvent Read FAfterExecute Write FAfterExecute;
+ Property OnParamError :TJSONParamErrorEvent Read FOnParamError Write FONParamError;
+ Property Options : TJSONRPCOptions Read FOptions Write FOptions;
+ Public
+ Constructor Create(AOwner : TComponent); override;
+ Destructor Destroy; override;
+ Procedure CheckParams(Const Params : TJSONData);
+ Function Execute(Const Params : TJSONData; AContext : TJSONRPCCallContext = Nil) : TJSONData;
+ Property ParamDefs : TJSONParamDefs Read FParamDefs Write SetParamDefs;
+ end;
+ TCustomJSONRPCHandlerClass = Class of TCustomJSONRPCHandler;
+
+ TJSONRPCEvent = Procedure (Sender : TObject; Const Params : TJSONData; Out Res : TJSONData) of object;
+
+ { TJSONRPCHandler }
+
+ TJSONRPCHandler = Class(TCustomJSONRPCHandler)
+ private
+ FOnExecute: TJSONRPCEvent;
+ protected
+ Function DoExecute(Const Params : TJSONData; AContext : TJSONRPCCallContext): TJSONData; override;
+ Published
+ Property OnExecute : TJSONRPCEvent Read FOnExecute Write FOnExecute;
+ Property BeforeExecute;
+ Property AfterExecute;
+ Property OnParamError;
+ Property Options;
+ end;
+
+ { TJSONRPCEcho }
+
+ TJSONRPCEcho = Class(TCustomJSONRPCHandler)
+ Protected
+ Function DoExecute(Const Params : TJSONData;AContext : TJSONRPCCallContext): TJSONData; override;
+ end;
+
+{ ---------------------------------------------------------------------
+ JSON-RPC dispatcher support
+ ---------------------------------------------------------------------}
+
+ TJSONRPCDispatchOption = (jdoSearchRegistry, // Check JSON Handler registry
+ jdoSearchOwner, // Check owner (usually webmodule) for request handler
+ jdoJSONRPC1, // Allow JSON RPC-1
+ jdoJSONRPC2, // Allow JSON RPC-2
+ jdoRequireClass, // Require class name (as in Ext.Direct)
+ jdoNotifications, // Allow JSON Notifications
+ jdoStrictNotifications // Error if notification returned result. Default is to discard result.
+ );
+ TJSONRPCDispatchOptions = set of TJSONRPCDispatchOption;
+
+Const
+ DefaultDispatchOptions = [jdoSearchOwner,jdoJSONRPC1,jdoJSONRPC2,jdoNotifications];
+
+Type
+ TDispatchRequestEvent = Procedure(Sender : TObject; Const AClassName,AMethod : TJSONStringType; Const Params : TJSONData) of object;
+ TFindRPCHandlerEvent = Procedure(Sender : TObject; Const AClassName,AMethod : TJSONStringType; Out Handler : TCustomJSONRPCHandler) of object;
+
+ { TCustomJSONRPCDispatcher }
+
+ TCustomJSONRPCDispatcher = Class(TComponent)
+ private
+ FFindHandler: TFindRPCHandlerEvent;
+ FOnDispatchRequest: TDispatchRequestEvent;
+ FOnEndBatch: TNotifyEvent;
+ FOnStartBatch: TNotifyEvent;
+ FOptions: TJSONRPCDispatchOptions;
+ Protected
+ // Find handler. If none found, nil is returned. Executes OnFindHandler if needed.
+ // On return 'DoFree' must be set to indicate that the hand
+ Function FindHandler(Const AClassName,AMethodName : TJSONStringType;AContext : TJSONRPCCallContext; Out FreeObject : TComponent) : TCustomJSONRPCHandler; virtual;
+ // Execute method. Finds handler, and returns response.
+ Function ExecuteMethod(Const AClassName, AMethodName : TJSONStringType; Params,ID : TJSONData; AContext : TJSONRPCCallContext) : TJSONData; virtual;
+ // Check and Execute a single request. Exceptions are caught and converted to request error object.
+ function ExecuteRequest(ARequest: TJSONData;AContext : TJSONRPCCallContext): TJSONData;
+ // Execute requests, returns responses in same format as requests (single or array)
+ Function DoExecute(Requests : TJSONData;AContext : TJSONRPCCallContext) : TJSONData; virtual;
+ // Check if single request corresponds to specs.
+ // Returns an error object if an error was found.
+ // if request is OK, then transaction id, classname, method and params *must* be returned.
+ // The returned transaction id, method, classname and params will be ignored if there is an error.
+ function CheckRequest(Request: TJSONData; Out AClassName, AMethodName : TJSONStringType; Out ID, Params : TJSONData): TJSONData; virtual;
+ // Check if requests are OK (check if JSON2 is allowed for array).
+ Function CheckRequests(Requests : TJSONData) : TJSONData; virtual;
+ // Format result of a single request. Result is returned to the client, possibly in an array if multiple requests were received in batch.
+ Function FormatResult(const AClassName, AMethodName: TJSONStringType; const Params, ID, Return: TJSONData) : TJSONData; virtual;
+ // Hooks for user.
+ Property OnStartBatch : TNotifyEvent Read FOnStartBatch Write FOnStartBatch;
+ Property OnDispatchRequest : TDispatchRequestEvent Read FOnDispatchRequest Write FOnDispatchRequest;
+ Property OnFindHandler : TFindRPCHandlerEvent Read FFindHandler Write FFindHandler;
+ Property OnEndBatch : TNotifyEvent Read FOnEndBatch Write FOnEndBatch;
+ Property Options : TJSONRPCDispatchOptions Read FOptions Write FOptions default DefaultDispatchOptions;
+ Class Function MethodProperty : String; virtual;
+ Class Function ClassNameProperty : String; virtual;
+ Class Function ParamsProperty : String; virtual;
+ Public
+ Constructor Create(AOwner : TComponent); override;
+ Class Function TransactionProperty : String; virtual;
+ Function Execute(Requests : TJSONData;AContext : TJSONRPCCallContext = Nil) : TJSONData;
+ end;
+
+ TJSONRPCDispatcher = Class(TCustomJSONRPCDispatcher)
+ Published
+ Property OnStartBatch;
+ Property OnDispatchRequest;
+ Property OnFindHandler;
+ Property OnEndBatch;
+ Property Options;
+ end;
+
+
+{ ---------------------------------------------------------------------
+ Factory support
+ ---------------------------------------------------------------------}
+
+
+ { TJSONRPCHandlerDef }
+
+ TDataModuleClass = Class of TDataModule; // For the time being. As of rev 15343 it is in classes unit
+
+ TBeforeCreateJSONRPCHandlerEvent = Procedure (Sender : TObject; Var AClass : TCustomJSONRPCHandlerClass) of object;
+ TJSONRPCHandlerEvent = Procedure (Sender : TObject; AHandler : TCustomJSONRPCHandler) of object;
+
+ TJSONRPCHandlerDef = Class(TCollectionItem)
+ private
+ FAfterCreate: TJSONRPCHandlerEvent;
+ FArgumentCount: Integer;
+ FBeforeCreate: TBeforeCreateJSONRPCHandlerEvent;
+ FPClass: TCustomJSONRPCHandlerClass;
+ FDataModuleClass : TDataModuleClass;
+ FHandlerMethodName: TJSONStringType;
+ FHandlerClassName: TJSONStringType;
+ procedure CheckNames(const AClassName, AMethodName: TJSONStringType);
+ procedure SetFPClass(const AValue: TCustomJSONRPCHandlerClass);
+ procedure SetHandlerClassName(const AValue: TJSONStringType);
+ procedure SetHandlerMethodName(const AValue: TJSONStringType);
+ protected
+ Function CreateInstance(AOwner : TComponent; Out AContainer : TComponent) : TCustomJSONRPCHandler; virtual;
+ Property DataModuleClass : TDataModuleClass Read FDataModuleClass;
+ Public
+ Property HandlerClassName : TJSONStringType Read FHandlerClassName Write SetHandlerClassName;
+ Property HandlerMethodName : TJSONStringType Read FHandlerMethodName Write SetHandlerMethodName;
+ Property HandlerClass : TCustomJSONRPCHandlerClass Read FPClass Write SetFPClass;
+ Property BeforeCreate : TBeforeCreateJSONRPCHandlerEvent Read FBeforeCreate Write FBeforeCreate;
+ Property AfterCreate : TJSONRPCHandlerEvent Read FAfterCreate Write FAfterCreate;
+ Property ArgumentCount : Integer Read FArgumentCount Write FArgumentCount;
+ end;
+
+ { TJSONRPCHandlerDefs }
+
+ TJSONRPCHandlerDefs = Class(TCollection)
+ private
+ function GetH(Index : Integer): TJSONRPCHandlerDef;
+ procedure SetH(Index : Integer; const AValue: TJSONRPCHandlerDef);
+ Public
+ Function IndexOfHandler(Const AClassName,AMethodName : TJSONStringType) : Integer;
+ Function AddHandler(Const AClassName,AMethodName : TJSONStringType) : TJSONRPCHandlerDef; overload;
+ Function AddHandler(Const AClassName,AMethodName : TJSONStringType; AClass : TCustomJSONRPCHandlerClass) : TJSONRPCHandlerDef; overload;
+ Property HandlerDefs[Index : Integer] : TJSONRPCHandlerDef Read GetH Write SetH; default;
+ end;
+
+ { TCustomJSONRPCHandlerManager }
+
+ TCustomJSONRPCHandlerManager = Class(TComponent)
+ Private
+ FRegistering: Boolean;
+ Protected
+ procedure Initialize; virtual;
+ // Handler support
+ Procedure RemoveHandlerDef(Const Index : Integer); virtual; abstract;
+ function AddHandlerDef(Const AClassName,AMethodName : TJSONStringType) : TJSONRPCHandlerDef; virtual; abstract;
+ function IndexOfHandlerDef(Const AClassName,AMethodName : TJSONStringType) : Integer; virtual; abstract;
+ function GetHandlerDef(Index : Integer): TJSONRPCHandlerDef; virtual; abstract;
+ function GetHandlerDefCount: Integer; virtual; abstract;
+ Public
+ // Handler support
+ Procedure UnregisterHandler(Const AClassName, AMethodName : TJSONStringType);
+ Procedure RegisterDatamodule(Const AClass : TDatamoduleClass; Const AHandlerClassName : TJSONStringType);
+ Function RegisterHandler(Const AMethodName : TJSONStringType; AClass : TCustomJSONRPCHandlerClass; AArgumentCount : Integer = 0) : TJSONRPCHandlerDef; overload;
+ Function RegisterHandler(Const AClassName,AMethodName : TJSONStringType; AClass : TCustomJSONRPCHandlerClass; AArgumentCount : Integer = 0) : TJSONRPCHandlerDef; overload;
+ Function FindHandlerDefByName(Const AClassName,AMethodName : TJSONStringType) : TJSONRPCHandlerDef;
+ Function GetHandlerDefByName(Const AClassName,AMethodName : TJSONStringType) : TJSONRPCHandlerDef;
+ Function GetHandler(Const ADef : TJSONRPCHandlerDef; AOwner : TComponent; Out AContainer : TComponent): TCustomJSONRPCHandler;
+ Function GetHandler(Const AClassName,AMethodName : TJSONStringType; AOwner : TComponent; Out AContainer : TComponent): TCustomJSONRPCHandler;
+ Procedure GetClassNames (List : TStrings); // Should be a stringlist of TJSONStringType
+ Procedure GetMethodsOfClass(Const AClassName : TJSONStringType; List : TStrings); // Should be a stringlist of TJSONStringType
+ // properties
+ Property Registering : Boolean Read FRegistering;
+ Property HandlerCount : Integer Read GetHandlerDefCount;
+ Property HandlerDefs[Index : Integer] : TJSONRPCHandlerDef Read GetHandlerDef;
+ end;
+ TCustomJSONRPCHandlerManagerClass = Class of TCustomJSONRPCHandlerManager;
+
+ { TJSONRPCHandlerManager }
+
+ TJSONRPCHandlerManager = Class(TCustomJSONRPCHandlerManager)
+ Private
+ FHandlerDefs : TJSONRPCHandlerDefs;
+ Protected
+ Procedure RemoveHandlerDef(Const Index : Integer); override;
+ function AddHandlerDef(Const AClassName,AMethodName : TJSONStringType) : TJSONRPCHandlerDef; override;
+ function IndexOfHandlerDef(Const AClassName,AMethodName : TJSONStringType) : Integer; override;
+ function GetHandlerDef(Index : Integer): TJSONRPCHandlerDef; override;
+ function GetHandlerDefCount: Integer; override;
+ Public
+ Constructor Create(AOwner : TComponent); override;
+ Destructor Destroy; override;
+ end;
+
+
+{ ---------------------------------------------------------------------
+ Auxiliary stuff
+ ---------------------------------------------------------------------}
+
+
+ EJSONRPC = Class(Exception);
+ TJSONErrorObject = Class(TJSONObject);
+
+// Raise EJSONRPC exceptions.
+Procedure JSONRPCError(Msg : String);
+Procedure JSONRPCError(Fmt : String; Args : Array of const);
+
+// Create an 'Error' object for an error response.
+function CreateJSONErrorObject(Const AMessage : String; Const ACode : Integer) : TJSONObject;
+
+// Create a JSON RPC 2 error response object containing an 'Error' object.
+// Result is of type TJSONErrorObject
+function CreateJSON2ErrorResponse(Const AMessage : String; Const ACode : Integer; ID : TJSONData = Nil; idname : TJSONStringType = 'id' ) : TJSONObject;
+function CreateJSON2ErrorResponse(Const AFormat : String; Args : Array of const; Const ACode : Integer; ID : TJSONData = Nil; idname : TJSONStringType = 'id') : TJSONObject;
+// Examines Req (request) and returns Error or an array of clones of Error)
+Function CreateErrorForRequest(Const Req,Error : TJSONData) : TJSONData;
+
+// Return TCustomJSONRPCHandlerManager instance to use for managing JSON-RPC handler.
+
+Function JSONRPCHandlerManager : TCustomJSONRPCHandlerManager;
+
+// Class that will be created. Must be set before first call to JSONRPCHandlerManager.
+Var
+ JSONRPCHandlerManagerClass : TCustomJSONRPCHandlerManagerClass = TJSONRPCHandlerManager;
+
+
+Const
+ // JSON RPC 2.0 error codes
+ EJSONRPCParseError = -32700;
+ EJSONRPCInvalidRequest = -32600;
+ EJSONRPCMethodNotFound = -32601;
+ EJSONRPCInvalidParams = -32602;
+ EJSONRPCInternalError = -32603;
+
+
+resourcestring
+ SErrDuplicateParam = 'Duplicate JSON-RPC Parameter name';
+ SErrUnknownParamDef = 'Unknown parameter definition: "%s"';
+ SErrParams = 'Error checking JSON-RPC parameters: "%s"';
+ SErrParamsMustBeArrayorObject = 'Parameters must be passed in an object or an array.';
+ SErrParamsMustBeObject = 'Parameters must be passed in an object.';
+ SErrParamsMustBeArray = 'Parameters must be passed in an array.';
+ SErrRequestMustBeObject = 'JSON-RPC Request must be an object.';
+ SErrNoIDProperty = 'No "id" property found in request.';
+ SErrInvalidIDProperty = 'Type of "id" property is not correct.';
+ SErrNoJSONRPCProperty = 'No "jsonrpc" property in request.';
+ SErrInvalidJSONRPCProperty = 'Type or value of "jsonrpc" property is not correct.';
+ SErrNoMethodName = 'Cannot determine method: No "%s" property found in request.';
+ SErrNoClassName = 'Cannot determine class: No "%s" property found in request.';
+ SErrNoParams = 'Cannot determine parameters: No "%s" property found in request.';
+ SErrInvalidMethodType = 'Type of "%s" property in request is not correct.';
+ SErrInvalidClassNameType = 'Type of "%s" property in request is not correct.';
+ SErrJSON2NotAllowed = 'JSON RPC 2 calls are not allowed.';
+ SErrJSON1NotAllowed = 'JSON RPC 1 calls are not allowed.';
+ SErrNoResponse = 'No response received from non-notification method "%s".';
+ SErrResponseFromNotification = 'A response was received from a notification method "%s".';
+ SErrInvalidMethodName = 'No method "%s" was found.';
+ SErrInvalidClassMethodName = 'No class "%s" with method "%s" was found.';
+ SErrDuplicateJSONRPCClassHandlerName = 'Duplicate JSON-RPC handler for class "%s" with method "%s".';
+ SErrDuplicateJSONRPCHandlerName = 'Duplicate JSON-RPC handler for method "%s".';
+ SErrUnknownJSONRPCClassMethodHandler = 'Unknown JSON-RPC handler for class "%s", method "%s".';
+ SErrUnknownJSONRPCMethodHandler = 'Unknown JSON-RPC handler for method "%s".';
+ SErrDuplicateRPCCLassMethodHandler = 'Duplicate JSON-RPC handler for class "%s", method "%s".';
+ SErrDuplicateRPCMethodHandler = 'Duplicate JSON-RPC handler for method "%s".';
+ SErrNoDispatcher = 'No method dispatcher available to handle request.';
+
+
+implementation
+
+function CreateJSONErrorObject(Const AMessage : String; Const ACode : Integer) : TJSONObject;
+
+begin
+ Result:=TJSONObject.Create(['code',ACode,'message',AMessage])
+end;
+
+function CreateJSON2ErrorResponse(Const AMessage : String; Const ACode : Integer; ID : TJSONData = Nil; idname : TJSONStringType = 'id' ) : TJSONObject;
+
+begin
+ If (ID=Nil) then
+ ID:=TJSONNull.Create;
+ Result:=TJSONErrorObject.Create(['jsonrpc','2.0','error',CreateJSONErrorObject(AMessage,ACode),idname,ID]);
+end;
+
+function CreateJSON2ErrorResponse(Const AFormat : String; Args : Array of const; Const ACode : Integer; ID : TJSONData = Nil; idname : TJSONStringType = 'id' ) : TJSONObject;
+
+begin
+ If (ID=Nil) then
+ ID:=TJSONNull.Create;
+ Result:=TJSONErrorObject.Create(['jsonrpc','2.0','error',CreateJSONErrorObject(Format(AFormat,Args),ACode),idname,ID]);
+end;
+
+Function CreateErrorForRequest(Const Req,Error : TJSONData) : TJSONData;
+
+Var
+ I : Integer;
+
+begin
+ if Req is TJSONArray then
+ begin
+ Result:=TJSONArray.Create;
+ TJSONArray(Result).Add(Error);
+ For I:=1 to TJSONArray(Req).Count-1 do
+ TJSONArray(Result).Add(Error.Clone);
+ end
+ else
+ Result:=Error;
+end;
+
+
+Var
+ TheHandler : TCustomJSONRPCHandlerManager;
+
+function JSONRPCHandlerManager: TCustomJSONRPCHandlerManager;
+begin
+ If (TheHandler=Nil) then
+ TheHandler:=JSONRPCHandlerManagerClass.Create(Nil);
+ JSONRPCHandlerManager:=TheHandler;
+end;
+
+Procedure JSONRPCError(Msg : String);
+
+begin
+ Raise EJSONRPC.Create(Msg);
+end;
+
+Procedure JSONRPCError(Fmt : String; Args : Array of const);
+
+begin
+ Raise EJSONRPC.CreateFmt(Fmt,Args);
+end;
+
+{ TJSONParamDef }
+
+procedure TJSONParamDef.SetName(const AValue: TJSONStringType);
+begin
+ if FName=AValue then exit;
+ If Assigned(Collection) and (Collection is TJSONParamDefs) then
+ if (Collection as TJSONParamDefs).FindParamDef(AValue)<>Nil then
+ JSONRPCError(SErrDuplicateParam,[AValue]);
+ FName:=AValue;
+end;
+
+constructor TJSONParamDef.Create(ACollection: TCollection);
+begin
+ inherited Create(ACollection);
+ FType:=jtString;
+ FRequired:=True;
+end;
+
+{ TJSONParamDefs }
+
+function TJSONParamDefs.GetP(AIndex : Integer): TJSONParamDef;
+begin
+ Result:=TJSONParamDef(Items[AIndex]);
+end;
+
+procedure TJSONParamDefs.SetP(AIndex : Integer; const AValue: TJSONParamDef);
+begin
+ Items[AIndex]:=AValue;
+end;
+
+function TJSONParamDefs.AddParamDef(const AName: TJSONStringType; AType: TJSONType
+ ): TJSONParamDef;
+begin
+ Result:=Add as TJSONParamDef;
+ try
+ Result.Name:=AName;
+ Result.DataType:=Atype;
+ except
+ FReeAndNil(Result);
+ Raise;
+ end;
+end;
+
+function TJSONParamDefs.IndexOfParamDef(const AName: TJSONStringType): Integer;
+begin
+ Result:=Count-1;
+ While (Result>=0) and (CompareText(AName,GetP(result).Name)<>0) do
+ Dec(Result);
+end;
+
+function TJSONParamDefs.FindParamDef(const AName: TJSONStringType): TJSONParamDef;
+
+Var
+ I : integer;
+
+begin
+ I:=IndexOfParamDef(AName);
+ If (I=-1) then
+ Result:=Nil
+ else
+ Result:=GetP(I);
+end;
+
+function TJSONParamDefs.ParamDefByName(const AName: TJSONStringType): TJSONParamDef;
+begin
+ Result:=FindParamDef(AName);
+ If (Result=Nil) then
+ JSONRPCError(SErrUnknownParamDef,[AName]);
+end;
+
+{ TCustomJSONRPCHandler }
+
+procedure TCustomJSONRPCHandler.CheckParams(const Params: TJSONData);
+
+Var
+ B : Boolean;
+
+begin
+ Try
+ DoCheckParams(Params);
+ Except
+ On E : Exception do
+ begin
+ B:=True;
+ If Assigned(FonParamError) then
+ FonParamError(Self,E,B);
+ If B then
+ Raise;
+ end;
+ end;
+end;
+
+procedure TCustomJSONRPCHandler.SetParamDefs(const AValue: TJSONParamDefs);
+begin
+ if FParamDefs=AValue then exit;
+ FParamDefs.Assign(AValue);
+end;
+
+procedure TCustomJSONRPCHandler.DoCheckParams(const Params: TJSONData);
+begin
+ If (jroObjectParams in Options) and Not (Params is TJSONobject) then
+ JSONRPCError(SErrParams,[SErrParamsMustBeObject]);
+ If (jroArrayParams in Options) and Not (Params is TJSONArray) then
+ JSONRPCError(SErrParams,[SErrParamsMustBeArray]);
+end;
+
+function TCustomJSONRPCHandler.DoExecute(Const Params: TJSONData;AContext : TJSONRPCCallContext): TJSONData;
+begin
+ Result:=Nil;
+end;
+
+constructor TCustomJSONRPCHandler.Create(AOwner: TComponent);
+begin
+ inherited Create(AOwner);
+ FParamDefs:=CreateParamDefs;
+end;
+
+destructor TCustomJSONRPCHandler.Destroy;
+begin
+ FreeAndNil(FParamDefs);
+ inherited Destroy;
+end;
+
+function TCustomJSONRPCHandler.CreateParamDefs : TJSONParamDefs;
+
+begin
+ Result:=TJSONParamDefs.Create(TJSONParamDef);
+end;
+
+function TCustomJSONRPCHandler.Execute(Const Params: TJSONData;AContext : TJSONRPCCallContext = Nil): TJSONData;
+begin
+ If Assigned(FBeforeExecute) then
+ FBeforeExecute(Self);
+ if (jroCheckParams in Options) then
+ CheckParams(Params);
+ Result:=DoExecute(Params,AContext);
+ If Assigned(FAfterExecute) then
+ FAfterExecute(Self);
+end;
+
+{ TJSONRPCHandler }
+
+function TJSONRPCHandler.DoExecute(const Params: TJSONData;AContext : TJSONRPCCallContext): TJSONData;
+begin
+ If Assigned(FOnExecute) then
+ FOnExecute(Self,Params,Result);
+end;
+
+{ TJSONRPCEcho }
+
+function TJSONRPCEcho.DoExecute(const Params: TJSONData;AContext : TJSONRPCCallContext): TJSONData;
+
+Var
+ I : Integer;
+ A : TJSONArray;
+ S : TJSONStringType;
+
+begin
+ If Params is TJSONArray then
+ begin
+ A:=Params as TJSONArray;
+ S:='';
+ For I:=0 to A.Count-1 do
+ begin
+ if (S<>'') then
+ S:=S+' ';
+ S:=S+A.Items[i].AsString;
+ end;
+ end
+ else If Params.JSONType in [jtObject,jtNumber] then
+ S:=Params.AsJSON
+ else
+ S:=Params.AsString;
+ Result:=TJSONString.Create(S);
+end;
+
+{ TCustomJSONRPCDispatcher }
+
+function TCustomJSONRPCDispatcher.FindHandler(const AClassName, AMethodName: TJSONStringType;AContext : TJSONRPCCallContext;Out FreeObject : TComponent): TCustomJSONRPCHandler;
+
+Var
+ C : TComponent;
+ D : TJSONRPCHandlerDef;
+
+
+begin
+ Result:=Nil;
+ FreeObject:=Nil;
+ If Assigned(Owner) and ((AClassName='') or (CompareText(AClassName,Owner.name)=0)) then
+ begin
+ C:=Owner.FindComponent(AMethodName);
+ If C is TCustomJSONRPCHandler then
+ Result:=TCustomJSONRPCHandler(C);
+ end;
+ If (Result=Nil) and (jdoSearchRegistry in Options) then
+ begin
+ D:=JSONRPCHandlerManager.FindHandlerDefByName(AClassName,AMethodName);
+ If Assigned(D) then
+ Result:=JSONRPCHandlerManager.GetHandler(D,Self,FreeObject);
+ end;
+ If (Result=Nil) and Assigned(FFindHandler) then
+ begin
+ FFindhandler(Self,AClassName,AMethodName,Result);
+ FreeObject:=Nil
+ end;
+end;
+
+function TCustomJSONRPCDispatcher.ExecuteMethod(Const AClassName,AMethodName: TJSONStringType;
+ Params,ID: TJSONData;AContext : TJSONRPCCallContext): TJSONData;
+
+Var
+ H : TCustomJSONRPCHandler;
+ FreeObject : TComponent;
+
+begin
+ H:=FindHandler(AClassName,AMethodName,AContext,FreeObject);
+ If (H=Nil) then
+ if (AClassName='') then
+ Exit(CreateJSON2ErrorResponse(SErrInvalidMethodName,[AMethodName],EJSONRPCMethodNotFound,ID.Clone,transactionProperty))
+ else
+ Exit(CreateJSON2ErrorResponse(SErrInvalidClassMethodName,[AClassName,AMethodName],EJSONRPCMethodNotFound,ID.Clone,transactionProperty));
+ try
+ If Assigned(FOndispatchRequest) then
+ FOndispatchRequest(Self,AClassName,AMethodName,Params);
+ Result:=H.Execute(Params,AContext);
+ finally
+ If Assigned(FreeObject) then
+ FreeAndNil(FreeObject);
+ end;
+end;
+
+function TCustomJSONRPCDispatcher.FormatResult(Const AClassName, AMethodName: TJSONStringType;
+Const Params,ID, Return : TJSONData) : TJSONData;
+
+begin
+ Result:=TJSONObject.Create(['result',Return,'error',TJSonNull.Create,transactionproperty,ID.Clone]);
+ if jdoJSONRPC2 in options then
+ TJSONObject(Result).Add('jsonrpc','2.0');
+end;
+
+function TCustomJSONRPCDispatcher.ExecuteRequest(ARequest: TJSONData;AContext : TJSONRPCCallContext): TJSONData;
+
+Var
+ C,M : TJSONStringType;
+ Id,P : TJSONData;
+
+
+begin
+ Result:=Nil;
+ try
+ Result:=CheckRequest(ARequest,C,M,ID,P);
+ If (Result=Nil) then
+ begin
+ Result:=ExecuteMethod(C,M,P,ID,AContext);
+ // Do some sanity checks.
+ If (Result=Nil) then
+ begin
+ // No response, and a response was expected.
+ if (ID<>Nil) or not (jdoNotifications in Options) then
+ Result:=CreateJSON2ErrorResponse(SErrNoResponse,[M],EJSONRPCInternalError,ID,transactionProperty);
+ end
+ else
+ begin
+ // A response was received, and no response was expected.
+ if ((ID=Nil) or (ID is TJSONNull)) and (jdoStrictNotifications in Options) then
+ Result:=CreateJSON2ErrorResponse(SErrResponseFromNotification,[M],EJSONRPCInternalError,ID,transactionProperty);
+ If (ID=Nil) or (ID is TJSONNull) then // Notification method, discard result.
+ FreeAndNil(Result);
+ end;
+ end;
+ If Assigned(Result) and not (Result is TJSONErrorObject) then
+ begin
+ Result:=FormatResult(C,M,P,ID,Result);
+ end;
+ except
+ // Something went really wrong if we end up here.
+ On E : Exception do
+ begin
+ If (Result<>Nil) then
+ FreeAndNil(Result);
+ If Assigned(ID) then
+ Result:=CreateJSON2ErrorResponse(E.Message,EJSONRPCInternalError,ID.Clone,transactionproperty)
+ else
+ Result:=CreateJSON2ErrorResponse(E.Message,EJSONRPCInternalError,Nil,transactionproperty)
+ end;
+ end;
+end;
+
+function TCustomJSONRPCDispatcher.DoExecute(Requests: TJSONData;AContext : TJSONRPCCallContext): TJSONData;
+
+Var
+ A : TJSONArray;
+ Res : TJSONData;
+ I : Integer;
+
+begin
+ Result:=Nil;
+ If Requests is TJSONArray then
+ begin
+ A:=Requests as TJSONArray;
+ Result:=TJSONArray.Create();
+ For I:=0 to A.Count-1 do
+ begin
+ Res:=ExecuteRequest(A[i],AContext);
+ If (Res<>Nil) then
+ TJSONArray(Result).Add(Res);
+ end;
+ end
+ else
+ Result:=ExecuteRequest(Requests,ACOntext);
+end;
+
+
+function TCustomJSONRPCDispatcher.CheckRequest(Request: TJSONData; Out AClassName,AMethodName : TJSONStringType; Out ID, Params : TJSONData): TJSONData;
+
+Var
+ O : TJSONObject;
+ I : Integer;
+ D : TJSONData;
+ OJ2 : Boolean;
+
+
+begin
+ AMethodName:='';
+ AClassName:='';
+ ID:=Nil;
+ Params:=Nil;
+ Result:=Nil;
+ If Not (Request is TJSONObject) then
+ Exit(CreateJSON2ErrorResponse(SErrRequestMustBeObject,EJSONRPCInvalidRequest,Nil,transactionproperty));
+ O:=TJSONObject(Request);
+ // Get ID object, if it exists.
+ I:=O.IndexOfName(TransactionProperty);
+ If (I<>-1) then
+ ID:=O.Items[i];
+ // Check ID
+ If (ID=Nil) and not (jdoNotifications in Options) then
+ Exit(CreateJSON2ErrorResponse(SErrNoIDProperty,EJSONRPCInvalidRequest,Nil,transactionproperty));
+ OJ2:=(jdoJSONRPC2 in Options) and not (jdoJSONRPC1 in Options);
+ If OJ2 then
+ begin
+ if Assigned(ID) and not (ID.JSONType in [jtNull,jtString,jtNumber]) then
+ Exit(CreateJSON2ErrorResponse(SErrINvalidIDProperty,EJSONRPCInvalidRequest,Nil,transactionproperty));
+ // Check presence and value of jsonrpc property
+ I:=O.IndexOfName('jsonrpc');
+ If (I=-1) then
+ Exit(CreateJSON2ErrorResponse(SErrNoJSONRPCProperty,EJSONRPCInvalidRequest,ID,transactionproperty));
+ If (O.Items[i].JSONType<>jtString) or (O.Items[i].AsString<>'2.0') then
+ Exit(CreateJSON2ErrorResponse(SErrInvalidJSONRPCProperty,EJSONRPCInvalidRequest,ID,transactionproperty));
+ end;
+ // Get method name, if it exists.
+ I:=O.IndexOfName(MethodProperty);
+ If (I<>-1) then
+ D:=O.Items[i]
+ else
+ Exit(CreateJSON2ErrorResponse(SErrNoMethodName,[MethodProperty],EJSONRPCInvalidRequest,ID,transactionproperty));
+ // Check if it is a string
+ if Not (D is TJSONString) then
+ Exit(CreateJSON2ErrorResponse(SErrInvalidMethodType,[MethodProperty],EJSONRPCInvalidRequest,ID,transactionproperty));
+ AMethodName:=D.AsString;
+ If (AMethodName='') then
+ Exit(CreateJSON2ErrorResponse(SErrNoMethodName,[MethodProperty],EJSONRPCInvalidRequest,ID,transactionproperty));
+ // Get class name, if it exists and is required
+ If (ClassNameProperty<>'') then
+ begin
+ I:=O.IndexOfName(ClassNameProperty);
+ If (I<>-1) then
+ D:=O.Items[i]
+ else if (jdoRequireClass in options) then
+ Exit(CreateJSON2ErrorResponse(SErrNoClassName,[ClassNameProperty],EJSONRPCInvalidRequest,ID,transactionproperty));
+ // Check if it is a string
+ if Not (D is TJSONString) then
+ Exit(CreateJSON2ErrorResponse(SErrInvalidClassNameType,[ClassNameProperty],EJSONRPCInvalidRequest,ID,transactionproperty));
+ AClassName:=D.AsString;
+ If (AMethodName='') and (jdoRequireClass in options) then
+ Exit(CreateJSON2ErrorResponse(SErrNoClassName,[ClassNameProperty],EJSONRPCInvalidRequest,ID,transactionproperty));
+ end;
+ // Get params, if they exist
+ I:=O.IndexOfName(ParamsProperty);
+ If (I<>-1) then
+ D:=O.Items[i]
+ else
+ Exit(CreateJSON2ErrorResponse(SErrNoParams,[ParamsProperty],EJSONRPCInvalidParams,ID,transactionproperty));
+ if OJ2 then
+ begin
+ // Allow array or object
+ If Not (D.JSONType in [jtArray,jtObject]) then
+ Exit(CreateJSON2ErrorResponse(SErrParamsMustBeArrayorObject,EJSONRPCInvalidParams,ID,transactionproperty));
+ end
+ else if not (jdoJSONRPC2 in Options) then
+ begin
+ // Allow only array
+ If Not (D.JSONType in [jtArray]) then
+ Exit(CreateJSON2ErrorResponse(SErrParamsMustBeArray,EJSONRPCInvalidParams,ID,transactionproperty));
+ end;
+ Params:=D;
+end;
+
+function TCustomJSONRPCDispatcher.CheckRequests(Requests: TJSONData): TJSONData;
+
+Var
+ A : TJSONArray;
+ O : TJSONObject;
+ ID : TJSONData;
+ I,J : Integer;
+
+begin
+ Result:=Nil;
+ If (Requests is TJSONArray) then
+ begin
+ A:=Requests as TJSONArray;
+ If Not (jdoJSONRPC2 in Options) then
+ begin
+ Result:=TJSONArray.Create;
+ For I:=0 to A.Count-1 do
+ begin
+ ID:=Nil;
+ If (A.Items[i] is TJSONObject) then
+ begin
+ O:=A.Objects[i];
+ J:=O.IndexOfName('id');
+ if (J<>-1) then
+ ID:=O.Items[J].Clone;
+ end;
+ TJSONArray(Result).Add(CreateJSON2ErrorResponse(SErrJSON2NotAllowed,EJSONRPCInvalidRequest,ID,transactionproperty));
+ end;
+ end;
+ end
+ else
+ If not (Requests is TJSONObject) then
+ Result:=CreateJSON2ErrorResponse(SErrRequestMustBeObject,EJSONRPCInvalidRequest,Nil,transactionproperty);
+end;
+
+class function TCustomJSONRPCDispatcher.TransactionProperty: String;
+begin
+ Result:='id'; // Do not localize
+end;
+
+class function TCustomJSONRPCDispatcher.MethodProperty: String;
+begin
+ Result:='method'; // Do not localize
+end;
+
+class function TCustomJSONRPCDispatcher.ClassNameProperty: String;
+begin
+ Result:=''; // Do not localize
+end;
+
+class function TCustomJSONRPCDispatcher.ParamsProperty: String;
+begin
+ Result:='params'; // Do not localize
+end;
+
+constructor TCustomJSONRPCDispatcher.Create(AOwner: TComponent);
+begin
+ inherited Create(AOwner);
+ FOptions:=DefaultDispatchOptions;
+end;
+
+function TCustomJSONRPCDispatcher.Execute(Requests: TJSONData;AContext : TJSONRPCCallContext = Nil): TJSONData;
+begin
+ If Assigned(FOnStartBatch) then
+ FOnStartBatch(Self);
+ Result:=CheckRequests(Requests);
+ if (Result=Nil) then // Form is OK and allowed.
+ Result:=DoExecute(Requests,AContext);
+ If Assigned(FOnEndBatch) then
+ FOnEndBatch(Self);
+end;
+
+{ TJSONRPCHandlerDef }
+
+procedure TJSONRPCHandlerDef.SetFPClass(const AValue: TCustomJSONRPCHandlerClass
+ );
+begin
+ FPClass:=AValue;
+end;
+
+procedure TJSONRPCHandlerDef.CheckNames(Const AClassName,AMethodName : TJSONStringType);
+
+Var
+ I : Integer;
+
+begin
+ If Assigned(Collection) and (Collection is TJSONRPCHandlerDefs) then
+ begin
+ I:=TJSONRPCHandlerDefs(Collection).IndexOfHandler(AClassName,AMethodName);
+ If (I<>-1) and (Collection.Items[i]<>Self) then
+ if (AClassName<>'') then
+ JSONRPCError(SErrDuplicateJSONRPCClassHandlerName,[AClassName,AMethodName])
+ else
+ JSONRPCError(SErrDuplicateJSONRPCHandlerName,[AClassName,AMethodName]);
+ end;
+end;
+
+procedure TJSONRPCHandlerDef.SetHandlerClassName(const AValue: TJSONStringType);
+begin
+ if FHandlerClassName=AValue then exit;
+ CheckNames(AValue,HandlerMethodName);
+ FHandlerClassName:=AValue;
+end;
+
+procedure TJSONRPCHandlerDef.SetHandlerMethodName(const AValue: TJSONStringType
+ );
+begin
+ if FHandlerMethodName=AValue then exit;
+ CheckNames(HandlerClassName,AValue);
+ FHandlerMethodName:=AValue;
+end;
+
+function TJSONRPCHandlerDef.CreateInstance(AOwner: TComponent; out
+ AContainer: TComponent): TCustomJSONRPCHandler;
+
+Var
+ AClass : TCustomJSONRPCHandlerClass;
+ DM : TDataModule;
+ C : TComponent;
+
+begin
+ Result:=Nil;
+ {$ifdef wmdebug}SendDebug(Format('Creating instance for %s',[Self.ProviderName]));{$endif}
+ If Assigned(FDataModuleClass) then
+ begin
+ {$ifdef wmdebug}SendDebug(Format('Creating datamodule from class %d ',[Ord(Assigned(FDataModuleClass))]));{$endif}
+ DM:=FDataModuleClass.Create(AOwner);
+ {$ifdef wmdebug}SendDebug(Format('Created datamodule from class %s ',[DM.ClassName]));{$endif}
+ C:=DM.FindComponent(FHandlerMethodName);
+ If (C<>Nil) and (C is TCustomJSONRPCHandler) then
+ Result:=TCustomJSONRPCHandler(C)
+ else
+ begin
+ FreeAndNil(DM);
+ JSONRPCError(SErrUnknownJSONRPCMethodHandler,[FHandlerMethodName]);
+ end;
+ end
+ else
+ DM:=TDataModule.CreateNew(AOwner,0);
+ AContainer:=DM;
+ If (Result=Nil) then
+ begin
+ {$ifdef wmdebug}SendDebug(Format('Creating from class pointer %d ',[Ord(Assigned(FPClass))]));{$endif}
+ AClass:=FPCLass;
+ If Assigned(FBeforeCreate) then
+ FBeforeCreate(Self,AClass);
+ Result:=AClass.Create(AContainer);
+ end;
+ If Assigned(FAfterCreate) then
+ FAfterCreate(Self,Result);
+end;
+
+{ TJSONRPCHandlerDefs }
+
+function TJSONRPCHandlerDefs.GetH(Index: Integer): TJSONRPCHandlerDef;
+begin
+ Result:=TJSONRPCHandlerDef(Items[Index]);
+end;
+
+procedure TJSONRPCHandlerDefs.SetH(Index: Integer;
+ const AValue: TJSONRPCHandlerDef);
+begin
+ Items[Index]:=AValue;
+end;
+
+function TJSONRPCHandlerDefs.AddHandler(const AClassName,
+ AMethodName: TJSONStringType): TJSONRPCHandlerDef;
+begin
+ If (IndexOfHandler(AClassName,AMethodName)<>-1) then
+ If (AClassName<>'') then
+ JSONRPCError(SErrDuplicateJSONRPCClassHandlerName,[AClassName,AMethodName])
+ else
+ JSONRPCError(SErrDuplicateJSONRPCHandlerName,[AMethodName]);
+ Result:=TJSONRPCHandlerDef(Add);
+ Result.FHandlerClassName:=AClassName;
+ Result.FHandlerMethodName:=AMethodName;
+end;
+
+function TJSONRPCHandlerDefs.AddHandler(const AClassName,
+ AMethodName: TJSONStringType; AClass: TCustomJSONRPCHandlerClass
+ ): TJSONRPCHandlerDef;
+begin
+ Result:=AddHandler(AClassName,AMethodName);
+ Result.HandlerClass:=AClass;
+end;
+
+function TJSONRPCHandlerDefs.IndexOfHandler(const AClassName,
+ AMethodName: TJSONStringType): Integer;
+
+ Function IsMatch(Index : Integer) : Boolean; inline;
+
+ Var
+ D : TJSONRPCHandlerDef;
+
+ begin
+ D:=GetH(Index);
+ Result:=((AClassName='') or
+ (CompareText(D.HandlerClassName,AClassName)=0)) and
+ (CompareText(AMethodName,D.HandlerMethodName)=0)
+ end;
+
+begin
+ Result:=Count-1;
+ While (Result>=0) and Not IsMatch(Result) do
+ Dec(Result)
+end;
+
+{ TCustomJSONRPCHandlerManager }
+
+procedure TCustomJSONRPCHandlerManager.Initialize;
+begin
+ // Do nothing
+end;
+
+procedure TCustomJSONRPCHandlerManager.UnregisterHandler(const AClassName,
+ AMethodName: TJSONStringType);
+
+Var
+ I : Integer;
+
+begin
+ I:=IndexOfHandlerDef(AClassName,AMethodName);
+ If (I<>-1) then
+ RemoveHandlerDef(I)
+ else
+ If (AClassName<>'') then
+ JSONRPCError(SErrUnknownJSONRPCClassMethodHandler,[AClassName,AMethodName])
+ else
+ JSONRPCError(SErrUnknownJSONRPCMethodHandler,[AMethodName]);
+end;
+
+procedure TCustomJSONRPCHandlerManager.RegisterDatamodule(
+ const AClass: TDatamoduleClass; const AHandlerClassName: TJSONStringType);
+
+Var
+ DM : TDatamodule;
+ I,J : Integer;
+ C : TComponent;
+ D : TJSONRPCHandlerDef;
+ B : Boolean;
+ CN : TJSONStringType;
+
+begin
+ B:=FRegistering;
+ try
+ FRegistering:=True;
+ DM:=AClass.Create(Self);
+ try
+ If (AHandlerClassName='') then
+ CN:=DM.Name
+ else
+ CN:=AHandlerClassName;
+ For I:=0 to DM.ComponentCount-1 do
+ begin
+ C:=DM.Components[i];
+ if C is TCustomJSONRPCHandler then
+ begin
+ J:=IndexOfHandlerDef(CN,C.Name);
+ If (J<>-1) then
+ JSONRPCError(SErrDuplicateRPCCLassMethodHandler,[CN,C.Name]);
+ D:=AddHandlerDef(CN,C.Name);
+ D.ArgumentCount:=TCustomJSONRPCHandler(C).ParamDefs.Count;
+ {$ifdef wmdebug}SendDebug('Registering provider '+C.Name);{$endif}
+ D.FDataModuleClass:=TDataModuleClass(DM.ClassType);
+ end;
+ end;
+ finally
+ DM.Free;
+ end;
+ finally
+ FRegistering:=B;
+ end;
+end;
+
+function TCustomJSONRPCHandlerManager.RegisterHandler(
+ const AMethodName: TJSONStringType;
+ AClass: TCustomJSONRPCHandlerClass;
+ AArgumentCount : Integer = 0): TJSONRPCHandlerDef;
+
+begin
+ Result:=RegisterHandler('',AMethodName,AClass,AArgumentCount);
+end;
+
+function TCustomJSONRPCHandlerManager.RegisterHandler(
+ const AClassName,AMethodName: String;
+ AClass: TCustomJSONRPCHandlerClass;
+ AArgumentCount : Integer = 0): TJSONRPCHandlerDef;
+
+Var
+ I : Integer;
+ B : Boolean;
+
+begin
+ B:=FRegistering;
+ try
+ FRegistering:=True;
+ I:=IndexOfHandlerDef(AClassName,AMethodname);
+ If (I<>-1) then
+ If (AClassName<>'') then
+ JSONRPCError(SErrDuplicateRPCCLassMethodHandler,[AClassName,AMethodName])
+ else
+ JSONRPCError(SErrDuplicateRPCMethodHandler,[AMethodName]);
+ Result:=AddHandlerDef(AClassName,AMEthodName);
+ Result.HandlerClass:=AClass;
+ Result.ArgumentCount:=AArgumentCount;
+ finally
+ FRegistering:=B;
+ end;
+end;
+
+function TCustomJSONRPCHandlerManager.FindHandlerDefByName(const AClassName,
+ AMethodName: TJSONStringType): TJSONRPCHandlerDef;
+
+Var
+ I : integer;
+
+begin
+ I:=IndexOfHandlerDef(AClassName,AMethodName);
+ If (I=-1) then
+ Result:=Nil
+ else
+ Result:=GetHandlerDef(I);
+end;
+
+function TCustomJSONRPCHandlerManager.GetHandlerDefByName(const AClassName,
+ AMethodName: TJSONStringType): TJSONRPCHandlerDef;
+begin
+ Result:=FindHandlerDefByName(AClassName,AMethodName);
+ If (Result=Nil) then
+ If (AClassName<>'') then
+ JSONRPCError(SErrUnknownJSONRPCClassMethodHandler,[AClassName,AMethodName])
+ else
+ JSONRPCError(SErrUnknownJSONRPCMethodHandler,[AMethodName]);
+end;
+
+function TCustomJSONRPCHandlerManager.GetHandler(
+ const ADef: TJSONRPCHandlerDef; AOwner: TComponent; out AContainer: TComponent
+ ): TCustomJSONRPCHandler;
+
+Var
+ O : TComponent;
+
+begin
+ If AOwner=Nil then
+ O:=Self
+ else
+ O:=AOwner;
+ Result:=ADef.CreateInstance(O,AContainer);
+end;
+
+function TCustomJSONRPCHandlerManager.GetHandler(const AClassName,
+ AMethodName: TJSONStringType; AOwner: TComponent; out AContainer: TComponent
+ ): TCustomJSONRPCHandler;
+
+Var
+ D : TJSONRPCHandlerDef;
+
+begin
+ D:=GetHandlerDefByname(AClassName,AMEthodName);
+ Result:=GetHandler(D,AOwner,AContainer);
+end;
+
+procedure TCustomJSONRPCHandlerManager.GetClassNames(List: TStrings);
+begin
+
+end;
+
+procedure TCustomJSONRPCHandlerManager.GetMethodsOfClass(
+ const AClassName: TJSONStringType; List: TStrings);
+begin
+
+end;
+
+{ TJSONRPCHandlerManager }
+
+procedure TJSONRPCHandlerManager.RemoveHandlerDef(const Index: Integer);
+begin
+ FHandlerDefs.Delete(Index);
+end;
+
+function TJSONRPCHandlerManager.AddHandlerDef(const AClassName,
+ AMethodName: TJSONStringType): TJSONRPCHandlerDef;
+begin
+ Result:=FHandlerDefs.AddHandler(AClassName,AMethodName);
+end;
+
+function TJSONRPCHandlerManager.IndexOfHandlerDef(const AClassName,
+ AMethodName: TJSONStringType): Integer;
+begin
+ Result:=FHandlerDefs.IndexOfHandler(AClassName,AMethodName);
+end;
+
+function TJSONRPCHandlerManager.GetHandlerDef(Index: Integer
+ ): TJSONRPCHandlerDef;
+begin
+ Result:=FHandlerDefs[Index];
+end;
+
+function TJSONRPCHandlerManager.GetHandlerDefCount: Integer;
+begin
+ Result:=FHandlerDefs.Count;
+end;
+
+constructor TJSONRPCHandlerManager.Create(AOwner: TComponent);
+begin
+ inherited Create(AOwner);
+ FHandlerDefs:=TJSONRPCHandlerDefs.Create(TJSONRPCHandlerDef);
+end;
+
+destructor TJSONRPCHandlerManager.Destroy;
+begin
+ FreeAndNil(FHandlerDefs);
+ inherited Destroy;
+end;
+
+
+Initialization
+Finalization
+ FreeAndNil(TheHandler);
+end.
+
diff --git a/packages/fcl-web/src/jsonrpc/readme.txt b/packages/fcl-web/src/jsonrpc/readme.txt
new file mode 100644
index 0000000000..338ccf0b36
--- /dev/null
+++ b/packages/fcl-web/src/jsonrpc/readme.txt
@@ -0,0 +1,189 @@
+
+The JSON-RPC support for FPC consists out of 2 units:
+
+fpjsonrpc: a set of components suitable for executing requests.
+webjsonrpc: Handles all HTTP transport and content handling for the JSON-RPC requests.
+fpextdirect: implements a Ext.Direct variant of JSON-RPC;
+ It includes HTTP transport an content handling.
+
+The fpjsonrpc unit implements support for JSON-RPC: it implements versions
+1.0 and 2.0 of the protocol, and has provisions for Ext.Direct-style RPC.
+
+It introduces the following classes:
+
+TCustomJSONRPCHandler = Class(TComponent)
+ The main method of this class is
+ Function Execute(Const Params : TJSONData; AContext : TJSONRPCCallContext = Nil) : TJSONData;
+ it executes a JSON-RPC call. The parameters to the call are in the Params
+ parameter, the AContext parameter can be used by dispatching mechanisms to
+ provide information about the context of the call (HTTP session etc.)
+ Property ParamDefs : TJSONParamDefs Read FParamDefs Write SetParamDefs;
+ Describes the parameters to the call. If 'Options' contains jroCheckParams,
+ then the types (and names, if appropriate) of the parameters will be checked.
+
+TJSONRPCHandler = Class(TCustomJSONRPCHandler)
+ A descendent which delegates the execution of the RPC call to an Event Handler.
+ Typically, one will drop an instance of TJSONRPCHandler on a webmodule.
+ Note that it does not provide context information in the event handler.
+
+TCustomJSONRPCDispatcher = Class(TComponent)
+ A request dispatching mechanism. It receives a JSON-encoded RPC request or a batch of
+ requests:
+ Function Execute(Requests : TJSONData; AContext : TJSONRPCCallContext = Nil) : TJSONData;
+ For each request in the batch, it will examine the 'method' and 'class'
+ of the request and will search for a TCustomJSONRPCHandler instance that
+ can execute the call, and pass the call on to that instance. It also
+ passes the context to the handler.
+
+ If jsoSearchOwner is in OPtions, then it will look on the Owner (usually a
+ TDatamodule descendent) for a TCustomJSONRPCHandler instance whose name
+ matches 'method' in the request, and will invoke its 'Execute' method.
+
+ if jdoSearchRegistry is in Options, then the JSONRPCHandlerManager factory
+ is queryied for an instance of TCustomJSONRPCHandler that can handle the
+ call. This instance is freed after the call ends.
+
+ The dispatcher can check the validity of the request and responses
+ based on the Options property:
+ jdoJSONRPC1, // Allow JSON RPC-1
+ jdoJSONRPC2, // Allow JSON RPC-2
+ jdoRequireClass, // Require class name (as in Ext.Direct)
+ jdoNotifications, // Allow JSON Notifications
+ jdoStrictNotifications // Error if notification returned result. Default is to discard result.
+
+TJSONRPCDispatcher = Class(TCustomJSONRPCDispatcher)
+ A descendent of TCustomJSONRPCDispatcher that publishes some events and
+ properties:
+
+ OnStartBatch : Called before a batch is started
+ OnFindHandler : Called when no handler is found, can be used to construct custom method handlers.
+ OnDispatchRequest : Called before the request is dispatched to the handler.
+ OnEndBatch : called after the batch has been processed.
+
+ Most methods of this component can be overridden to provide customized
+ behaviour.
+
+
+TCustomJSONRPCHandlerManager = Class(TComponent)
+
+ A class that implements a TCustomJSONRPCHandler factory: definitions of TCustomJSONRPCHandler classes are kept.
+ classes must be registered using one of the calls:
+ Function RegisterHandler(Const AMethodName : TJSONStringType; AClass : TCustomJSONRPCHandlerClass; AArgumentCount : Integer = 0) : TJSONRPCHandlerDef;
+ Function RegisterHandler(Const AClassName,AMethodName : TJSONStringType; AClass : TCustomJSONRPCHandlerClass; AArgumentCount : Integer = 0) :TJSONRPCHandlerDef;
+
+ There is also support for registering a datamodule with TCustomJSONRPCHandler instances:
+
+ Procedure RegisterDatamodule(Const AClass : TDatamoduleClass; Const AHandlerClassName : TJSONStringType);
+
+ This will create an instance of the datamodule, register all TCustomJSONRPCHandler instances on the datamodule
+ with the datamodule name as the classname is AHandlerClassName is empty, and the TCustomJSONRPCHandler instance
+ name as the method name. After registration, the module is freed.
+
+A global instance of TCustomJSONRPCHandlerManager is available through the
+
+ Function JSONRPCHandlerManager : TCustomJSONRPCHandlerManager;
+
+function. By default, an instance of TJSONRPCHandlerManager is created.
+
+This instance is used by the dispatcher classes to search for a TCustomJSONRPCHandler instance.
+
+The webjsonrpc unit implements HTTP transport and content handling for the json-rpc mechanism.
+It introduces the following classes:
+
+TCustomJSONRPCContentProducer = Class(THTTPContentProducer)
+
+ Handles a HTTP request, extracts the JSON-RPC request from it, and returns the result in the HTTP response.
+ It needs a dispatcher instance, which must be provided by a descendent.
+
+TJSONRPCContentProducer = Class(TCustomJSONRPCContentProducer)
+ Publishes a Dispatcher property, which must be set by the programmer.
+ All requests will be dispatched to this instance
+
+TJSONRPCSessionContext = Class(TJSONRPCCallContext)
+ JSON-RPC call context which gives access to the HTTP Session object.
+
+TSessionJSONRPCDispatcher = Class(TCustomJSONRPCDispatcher)
+ JSON-RPC dispatcher which initializes the call context if the handler is
+ located on a websession module.
+
+TJSONRPCDispatchModule = Class(TSessionHTTPModule)
+ Webmodule which knows how to dispatch a request and create session information for it.
+
+TCustomJSONRPCModule = Class(TJSONRPCDispatchModule)
+ It completely handles a JSON-RPC request over HTTP.
+ It creates a dispatcher if needed to handle the request.
+ The dispatcher is by default of type TSessionJSONRPCDispatcher
+
+TJSONRPCModule= Class(TCustomJSONRPCModule)
+ A webmodule which can be registered in the fcl-web module registry.
+ Publishes a property Dispatcher to dispatch a request, if set, this
+ dispatcher will be used.
+ Publishes a property DispatchOptions; If the module creates a dispatcher,
+ it will be passed these properties.
+
+The fpextdirect unit contains the following classes:
+
+TCustomExtDirectDispatcher = Class(TCustomJSONRPCDispatcher)
+ A JSON-RPC dispatcher that conforms to Ext.Direct specifications.
+ It sets the default Options to require a class name.
+ It handles HTTP sessions just as TSessionJSONRPCDispatcher does.
+
+TExtDirectDispatcher = Class(TCustomExtDirectDispatcher)
+ Simply publishes all properties.
+
+TCustomExtDirectContentProducer = Class(TCustomJSONRPCContentProducer)
+ A content producer that knows how to handle the 'API' request. It
+ assumes the path is something like /myapp/extdirect/api. All other
+ paths are treated as actual method calls.
+
+TCustomExtDirectModule = Class(TJSONRPCDispatchModule)
+ Handles JSON-RPC requests. It has 2 properties APIPath and RouterPath
+ which determine how the request is handled:
+ /modulepath/APIPath will create the API response.
+ /modulepath/RouterPath will route the JSON-RPC request.
+
+TExtDirectModule = Class(TCustomExtDirectModule)
+ Publishes the properties introduced in TCustomExtDirectModule.
+
+There are 4 ways to handle JSON-RPC in fcl-web:
+1. Manual:
+ A. Drop one or more TJSONRPCHandler components on a webmodule.
+ B. Implement the OnExecute handlers of the TJSONRPCHandler components
+ C. Handle the request in a OnRequest handler of an webaction and/or webmodule.
+ This means
+ 1. converting the request to JSONData.
+ 2. Extracting the method(s) and (their) parameters from the data.
+ 3. locating The TJSONRPCHandler.
+ 4. Passing the parameters to the Execute method of the handler.
+ 5. Convert the result to JSON and send it back.
+
+2. Using a TJSONRPCDispatcher:
+ A. Drop one or more TJSONRPCHandler components on a webmodule.
+ B. Implement the OnExecute handlers of the TJSONRPCHandler components
+ C. Handle the request in a OnRequest handler of an webaction and/or webmodule.
+ This means
+ 1. converting the request to JSONData.
+ 4. Passing the parameters to the Execute method of the handler
+ 5. Convert the result to JSON and send it back.
+
+3. Using a TJSONRPCContentProducer:
+ A. Drop one or more TJSONRPCHandler components on a webmodule.
+ B. Implement the OnExecute handlers of the TJSONRPCHandler components.
+ C. Handle the request in a OnRequest handler of an webaction and/or webmodule.
+ 1. Return the content of the TJSONRPCContentProducer.
+
+4. Using a TJSONRPCModule
+ A. Drop one or more TJSONRPCHandler on a TJSONRPCModule.
+ B. Implement the OnExecute handlers of the TJSONRPCHandler components.
+
+For large applicaions, TJSONRPCHandler instances can be dropped on
+datamodules or TJSONRPCModules, and the datamodule and/or TJSONRPCModules
+must be registered using
+ JSONRpcHandlerManager.RegisterModule(TMyModule,'myclassname');
+if TJSONRPCModules are used, only 1 must be registered as a webmodule
+to handle the request. It will dispatch the request to the other instances
+if needed.
+
+Note: if a request contains no class name, then the handler is searched
+using the first matching method name. If 2 modules implement the same
+method name, then the first match is used.
diff --git a/packages/fcl-web/src/jsonrpc/webjsonrpc.pp b/packages/fcl-web/src/jsonrpc/webjsonrpc.pp
new file mode 100644
index 0000000000..a62781f1f7
--- /dev/null
+++ b/packages/fcl-web/src/jsonrpc/webjsonrpc.pp
@@ -0,0 +1,309 @@
+unit webjsonrpc;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+ Classes, SysUtils, fpjson, fpjsonrpc, httpdefs, fphttp, jsonparser, websession;
+
+Type
+{ ---------------------------------------------------------------------
+ HTTP handling and content producing methods
+ ---------------------------------------------------------------------}
+
+ { TCustomJSONRPCContentProducer }
+
+ TCustomJSONRPCContentProducer = Class(THTTPContentProducer)
+ Protected
+ Function GetIDProperty : String; virtual;
+ Procedure DoGetContent(ARequest : TRequest; Content : TStream; Var Handled : Boolean); override;
+ Function GetDispatcher : TCustomJSONRPCDispatcher; virtual; abstract;
+ end;
+
+ { TJSONRPCContentProducer }
+
+ TJSONRPCContentProducer = Class(TCustomJSONRPCContentProducer)
+ private
+ FDispatcher: TCustomJSONRPCDispatcher;
+ procedure SetDispatcher(const AValue: TCustomJSONRPCDispatcher);
+ Protected
+ Function GetDispatcher : TCustomJSONRPCDispatcher; override;
+ procedure Notification(AComponent: TComponent; Operation: TOperation);override;
+ Published
+ Property Dispatcher : TCustomJSONRPCDispatcher Read FDispatcher Write SetDispatcher;
+ end;
+
+
+ { TJSONRPCSessionContext }
+
+ TJSONRPCSessionContext = Class(TJSONRPCCallContext)
+ private
+ FSession: TCustomSession;
+ Public
+ Constructor CreateSession(ASession : TCustomSession);
+ Property Session : TCustomSession Read FSession;
+ end;
+
+ { TSessionJSONRPCDispatcher }
+
+ TSessionJSONRPCDispatcher = Class(TCustomJSONRPCDispatcher)
+ Protected
+ Function FindHandler(Const AClassName,AMethodName : TJSONStringType;AContext : TJSONRPCCallContext; Out FreeObject : TComponent) : TCustomJSONRPCHandler; override;
+ Published
+ Property OnStartBatch;
+ Property OnDispatchRequest;
+ Property OnFindHandler;
+ Property OnEndBatch;
+ Property Options;
+ end;
+
+ { TJSONRPCDispatchModule }
+
+ TJSONRPCDispatchModule = Class(TSessionHTTPModule)
+ protected
+ Function CreateContext : TJSONRPCSessionContext;
+ Function DispatchRequest(Const ARequest : TRequest; ADispatcher : TCustomJSONRPCDispatcher) : TJSONData;
+ end;
+
+ { TCustomJSONRPCModule }
+
+ TCustomJSONRPCModule = Class(TJSONRPCDispatchModule)
+ private
+ FDispatcher: TCustomJSONRPCDispatcher;
+ FOptions: TJSONRPCDispatchOptions;
+ FRequest: TRequest;
+ FResponse: TResponse;
+ procedure SetDispatcher(const AValue: TCustomJSONRPCDispatcher);
+ Protected
+ Function CreateDispatcher : TCustomJSONRPCDispatcher; virtual;
+ procedure Notification(AComponent: TComponent; Operation: TOperation);override;
+ Property Dispatcher : TCustomJSONRPCDispatcher Read FDispatcher Write SetDispatcher;
+ Property DispatchOptions : TJSONRPCDispatchOptions Read FOptions Write FOptions default DefaultDispatchOptions;
+ Public
+ Constructor CreateNew(AOwner : TComponent; CreateMode : Integer); override;
+ Procedure HandleRequest(ARequest : TRequest; AResponse : TResponse); override;
+ // Access to request
+ Property Request: TRequest Read FRequest;
+ // Access to response
+ Property Response: TResponse Read FResponse;
+ end;
+
+ { TJSONRPCDataModule }
+
+ TJSONRPCModule = Class(TCustomJSONRPCModule)
+ Published
+ Property Dispatcher;
+ Property DispatchOptions;
+ end;
+
+implementation
+{ TCustomJSONRPCContentProducer }
+
+function TCustomJSONRPCContentProducer.GetIDProperty: String;
+begin
+ Result:='id';
+end;
+
+
+procedure TCustomJSONRPCContentProducer.DoGetContent(ARequest: TRequest;
+ Content: TStream; var Handled: Boolean);
+
+Var
+ Disp : TCustomJSONRPCDispatcher;
+ P : TJSONParser;
+ Req,res : TJSONData;
+ R : String;
+
+begin
+ Disp:=Self.GetDispatcher;
+ P:= TJSONParser.Create(ARequest.Content);
+ try
+ Res:=Nil;
+ Req:=Nil;
+ try
+ try
+ Req:=P.Parse;
+ If (Disp<>Nil) then
+ Res:=Disp.Execute(Req,Nil)
+ else // No dispatcher, create error(s)
+ Res:=CreateErrorForRequest(Req,CreateJSON2ErrorResponse(SErrNoDispatcher,EJSONRPCInternalError,Nil,GetIDProperty));
+ except
+ On E : Exception Do
+ begin
+ Res:=CreateJSON2ErrorResponse(E.Message,EJSONRPCParseError,Nil,GetIDProperty);
+ end;
+ end;
+ try
+ If Assigned(Res) then
+ begin
+ R:=Res.AsJSON;
+ Content.WriteBuffer(R[1],Length(R));
+ end;
+ Handled:=True;
+ finally
+ FreeAndNil(Res);
+ end;
+ finally
+ Req.Free;
+ end;
+ finally
+ P.Free;
+ end;
+end;
+
+{ TJSONRPCContentProducer }
+
+procedure TJSONRPCContentProducer.SetDispatcher(
+ const AValue: TCustomJSONRPCDispatcher);
+begin
+ if FDispatcher=AValue then exit;
+ If Assigned(FDispatcher) then
+ FDispatcher.RemoveFreeNotification(Self);
+ FDispatcher:=AValue;
+ If Assigned(FDispatcher) then
+ FDispatcher.FreeNotification(Self);
+end;
+
+function TJSONRPCContentProducer.GetDispatcher: TCustomJSONRPCDispatcher;
+begin
+ Result:=FDispatcher;
+end;
+
+procedure TJSONRPCContentProducer.Notification(AComponent: TComponent;
+ Operation: TOperation);
+begin
+ inherited Notification(AComponent, Operation);
+ If (Operation=opRemove) and (AComponent=FDispatcher) then
+ FDispatcher:=Nil;
+end;
+
+{ TCustomJSONRPCModule }
+
+procedure TCustomJSONRPCModule.SetDispatcher(
+ const AValue: TCustomJSONRPCDispatcher);
+begin
+ if FDispatcher=AValue then exit;
+ If Assigned(FDispatcher) then
+ FDispatcher.RemoveFreeNotification(Self);
+ FDispatcher:=AValue;
+ If Assigned(FDispatcher) then
+ FDispatcher.FreeNotification(Self);
+end;
+
+function TCustomJSONRPCModule.CreateDispatcher: TCustomJSONRPCDispatcher;
+
+Var
+ S : TSessionJSONRPCDispatcher;
+
+begin
+ S:=TSessionJSONRPCDispatcher.Create(Self);
+ S.Options:=DispatchOptions;
+ Result:=S;
+end;
+
+procedure TCustomJSONRPCModule.Notification(AComponent: TComponent;
+ Operation: TOperation);
+begin
+ inherited Notification(AComponent, Operation);
+ If (Operation=opRemove) and (AComponent=FDispatcher) then
+ FDispatcher:=Nil;
+end;
+
+constructor TCustomJSONRPCModule.CreateNew(AOwner: TComponent;
+ CreateMode: Integer);
+begin
+ inherited CreateNew(AOwner, CreateMode);
+ FOptions:=DefaultDispatchOptions+[jdoSearchRegistry];
+end;
+
+
+
+procedure TCustomJSONRPCModule.HandleRequest(ARequest: TRequest;
+ AResponse: TResponse);
+
+Var
+ Disp : TCustomJSONRPCDispatcher;
+ res : TJSONData;
+
+begin
+ If (Dispatcher=Nil) then
+ Dispatcher:=CreateDispatcher;
+ Disp:=Dispatcher;
+ Res:=DispatchRequest(ARequest,Disp);
+ try
+ If Assigned(Res) then
+ begin
+ AResponse.Content:=Res.AsJSON;
+ AResponse.ContentLength:=Length(AResponse.Content);
+ end;
+ AResponse.SendResponse;
+ finally
+ Res.Free;
+ end;
+end;
+
+{ TJSONRPCSessionContext }
+
+constructor TJSONRPCSessionContext.CreateSession(ASession: TCustomSession);
+begin
+ FSession:=ASession;
+end;
+
+{ TJSONRPCDispatchModule }
+
+function TJSONRPCDispatchModule.CreateContext: TJSONRPCSessionContext;
+begin
+ If CreateSession then
+ Result:=TJSONRPCSessionContext.CreateSession(Session)
+ else
+ Result:=TJSONRPCSessionContext.CreateSession(Nil);
+end;
+
+Function TJSONRPCDispatchModule.DispatchRequest(const ARequest: TRequest;
+ ADispatcher: TCustomJSONRPCDispatcher): TJSONData;
+var
+ P : TJSONParser;
+ Req : TJSONData;
+ C : TJSONRPCSessionContext;
+
+
+begin
+ P:= TJSONParser.Create(ARequest.Content);
+ try
+ Result:=Nil;
+ Req:=Nil;
+ try
+ try
+ Req:=P.Parse;
+ C:=CreateContext;
+ try
+ Result:=ADispatcher.Execute(Req,C);
+ finally
+ C.Free;
+ end;
+ except
+ On E : Exception Do
+ Result:=CreateJSON2ErrorResponse(E.Message,EJSONRPCParseError,Nil,ADispatcher.TransactionProperty);
+ end;
+ finally
+ Req.Free;
+ end;
+ finally
+ P.Free;
+ end;
+end;
+
+{ TSessionJSONRPCDispatcher }
+
+function TSessionJSONRPCDispatcher.FindHandler(const AClassName,
+ AMethodName: TJSONStringType; AContext: TJSONRPCCallContext; out
+ FreeObject: TComponent): TCustomJSONRPCHandler;
+begin
+ Result:=Inherited FindHandler(AClassName,AMethodName,AContext,FreeObject);
+ If (AContext is TJSONRPCSessionContext) and (FreeObject is TCustomJSONRPCModule) then
+ TCustomJSONRPCModule(FreeObject).Session:=TJSONRPCSessionContext(AContext).Session;
+end;
+
+end.
+