wrapper_3.5.22_src/build32.sh 100755 0 0 324 12224722007 13123 0 ustar 0 0 #!/bin/sh
BUILDFILE="`pwd`/`dirname $0`/build.xml"
echo "--------------------"
echo "Wrapper Build System"
echo "using $BUILDFILE"
echo "--------------------"
"$ANT_HOME/bin/ant" -f "$BUILDFILE" -Dbits=32 $@
wrapper_3.5.22_src/build64.sh 100755 0 0 324 12224722006 13127 0 ustar 0 0 #!/bin/sh
BUILDFILE="`pwd`/`dirname $0`/build.xml"
echo "--------------------"
echo "Wrapper Build System"
echo "using $BUILDFILE"
echo "--------------------"
"$ANT_HOME/bin/ant" -f "$BUILDFILE" -Dbits=64 $@
wrapper_3.5.22_src/build/ 40755 0 0 0 12224722007 12343 5 ustar 0 0 wrapper_3.5.22_src/doc/ 40755 0 0 0 12224722016 12011 5 ustar 0 0 wrapper_3.5.22_src/src/ 40755 0 0 0 12224722007 12033 5 ustar 0 0 wrapper_3.5.22_src/src/bin/ 40755 0 0 0 12224722010 12575 5 ustar 0 0 wrapper_3.5.22_src/src/c/ 40755 0 0 0 12224722016 12255 5 ustar 0 0 wrapper_3.5.22_src/src/conf/ 40755 0 0 0 12224722016 12760 5 ustar 0 0 wrapper_3.5.22_src/src/java/ 40755 0 0 0 12224722005 12752 5 ustar 0 0 wrapper_3.5.22_src/src/java/org/ 40755 0 0 0 12224722005 13541 5 ustar 0 0 wrapper_3.5.22_src/src/java/org/tanukisoftware/ 40755 0 0 0 12224722005 16607 5 ustar 0 0 wrapper_3.5.22_src/src/java/org/tanukisoftware/wrapper/ 40755 0 0 0 12224722017 20272 5 ustar 0 0 wrapper_3.5.22_src/src/java/org/tanukisoftware/wrapper/demo/ 40755 0 0 0 12224722017 21216 5 ustar 0 0 wrapper_3.5.22_src/src/java/org/tanukisoftware/wrapper/demo/html/ 40755 0 0 0 12224722017 22162 5 ustar 0 0 wrapper_3.5.22_src/src/java/org/tanukisoftware/wrapper/event/ 40755 0 0 0 12224722017 21413 5 ustar 0 0 wrapper_3.5.22_src/src/java/org/tanukisoftware/wrapper/jmx/ 40755 0 0 0 12224722017 21070 5 ustar 0 0 wrapper_3.5.22_src/src/java/org/tanukisoftware/wrapper/resources/ 40755 0 0 0 12224722017 22304 5 ustar 0 0 wrapper_3.5.22_src/src/java/org/tanukisoftware/wrapper/security/ 40755 0 0 0 12224722017 22141 5 ustar 0 0 wrapper_3.5.22_src/src/java/org/tanukisoftware/wrapper/test/ 40755 0 0 0 12224722020 21243 5 ustar 0 0 wrapper_3.5.22_src/src/java/org/tanukisoftware/wrapper/test2/ 40755 0 0 0 12224722017 21333 5 ustar 0 0 wrapper_3.5.22_src/src/test/ 40755 0 0 0 12224722007 13012 5 ustar 0 0 wrapper_3.5.22_src/src/test/org/ 40755 0 0 0 12224722007 13601 5 ustar 0 0 wrapper_3.5.22_src/src/test/org/tanukisoftware/ 40755 0 0 0 12224722007 16647 5 ustar 0 0 wrapper_3.5.22_src/src/test/org/tanukisoftware/wrapper/ 40755 0 0 0 12224722020 20322 5 ustar 0 0 wrapper_3.5.22_src/README_de.txt 100644 0 0 13724 12224722020 13531 0 ustar 0 0 -----------------------------------------------------------------------------
Java Service Wrapper Community Edition 3.5.22
Copyright (C) 1999-2013 Tanuki Software, Ltd. All Rights Reserved.
http://wrapper.tanukisoftware.com
-----------------------------------------------------------------------------
Zusammenfassung:
1. Was ist der Java Service Wrapper?
2. Dokumentation
3. Installation
4. Lizenzoptionen
5. Wie zu erwerben?
6. Aktualisieren
7. FAQ
8. Support
9. Systemvoraussetzungen
1. Was ist der Java Service Wrapper?
-----------------------------------------------------------------------------
Der Java Service Wrapper ist eine Anwendung die aus dem Wunsch heraus erstellt
worden ist, eine Vielzahl von Java bedingten Problem und Einschränkungen zu
beheben.
Einige der Möglichkeiten des Wrappers sind:
* Eine Javaanwendung als Windows Dienst und Unix Daemon zu starten
* Erhöhung der Zuverlässigkeit von Javaanwendungen.
* Automatische Crash-, Stillstand- und Deadlock-Erkennung und Wiederherstellung
* On Demand Neustarts
* Standard, Out-of-the-Box Scripting
* Flexible Cross-Platform Konfiguration
* Vereinfachung der Installation von Javaanwenungen
* Logging
* Und vieles mehr...
Bitte gehen Sie auf unsere Downloadseite für mehr Details:
=> http://wrapper.tanukisoftware.com/doc/german/download.jsp
Für weitere Informationen gehen Sie bitte auf:
=> http://wrapper.tanukisoftware.com/doc/german/introduction.html
2. Dokumentation
-----------------------------------------------------------------------------
Bitte besuchen Sie die vollständige Dokumentation auf unserer Webseite.
Hier sind ein paar Wege zum Anfangen.
* Komplette Dokumentation finden sie online:
=> http://wrapper.tanukisoftware.com/doc/german/
* Wie Sie Ihrer Anwendung mit dem Java Service Wrapper integrieren
=> http://wrapper.tanukisoftware.com/doc/german/integrate.html
* Konfigurationseigenschaften
=> http://wrapper.tanukisoftware.com/doc/german/properties.html
* HOWTOs
=> http://wrapper.tanukisoftware.com/doc/german/howto.html
* Javadocs, für fortgeschrittene Benutzer
=> http://wrapper.tanukisoftware.com/doc/german/javadocs.html
* Tanuki Software, Ltd. Firmenseite:
=> http://www.tanukisoftware.com/
3. Installation
-----------------------------------------------------------------------------
Wenn Sie das hier lesen, heißt das, dass Sie bereits unsere Software entpackt
haben.
Die Standard und Professional Editionen des Java Service Wrappers beinhalten
bereits eine zeitlich beschränkte aber vollfunktionstüchtige Triallizenz, die
es Ihnen erlaubt den Wrapper unbegrenzt oft zu starten und jeweils für 15 Minuten
zu laufen. Dies ist für einfache, ungezwungene erste Tests gedacht.
Sie können ebenfalls kostenlos eine 1monatige Triallizenz beantragen, die wie
eine Serverlizenz funktioniert und auf einem Server Ihrer Wahl verwendet werden
kann. Triallizenzen können auf folgender Seite beantragt werden:
=> http://wrapper.tanukisoftware.com/doc/german/requestTrial.jsp
Dauerhafte Lizenzen können desweiteren auf der folgenden Seite erworben werden:
=> http://wrapper.tanukisoftware.com/doc/german/accountLicenses.jsp
The Community Edition benötigt keinerlei Lizenz!
Sollten Sie bereits eine Lizenz erworben haben, können Sie den Lizenzschlüssel
auf der folgendenen Seiten erstellen und herunterladen:
Für Serverlizenzen:
=> http://wrapper.tanukisoftware.com/doc/german/accountServerLicenses.jsp
Für Entwicklerlizenzen:
=> http://wrapper.tanukisoftware.com/doc/german/accountDevLicenses.jsp
Abhängig von der Art der Javaanwendung, bedarf es verschiedene Arten, wie Sie
die Anwendung mit dem Wrapper zu integrieren. Die Integrationsschritte finden
Sie auf folgender Seite:
=> http://wrapper.tanukisoftware.com/doc/german/integrate.html
4. Lizenzoptionen
-----------------------------------------------------------------------------
Der Java Service Wrapper ist verfügbar unter 3 verschiedenen Lizenzen:
* Entwicklerlizenz Vereinbarung (Kommerziell)
* Serverlizenz Vereinbarung (Kommerziell)
* Communitylizenz Vereinbarung (GPL2)
Für mehr Informationen besuchen Sie bitte die Lizenzübersicht auf unserer
Seite:
=> http://wrapper.tanukisoftware.com/doc/german/licenseOverview.html
5. Wie zu erwerben?
-----------------------------------------------------------------------------
Sollten Sie interessiert sein and den Features der Standard bzw. Professional
Edition, so können Sie diese hier online erwerben:
=> http://wrapper.tanukisoftware.com/doc/german/accountLicenses.jsp
6. Aktualisieren
-----------------------------------------------------------------------------
Sie finden die aktuellste version des Wrappers auf unserer Downloadseite:
=> http://wrapper.tanukisoftware.com/doc/german/download.jsp
Für die Anleitung gehen Sie bitte auf diese Seite:
=> http://wrapper.tanukisoftware.com/doc/german/howto-upgrade.html
7. FAQ
-----------------------------------------------------------------------------
Bitte gehen Sie auf den FAQ-bereich unserer Seite:
=> http://wrapper.tanukisoftware.com/doc/german/faq.html
Desweiteren haben wir auch eine Troubleshooting, HOWTOs und
Fragen & Antwortenseite:
=> http://wrapper.tanukisoftware.com/doc/german/troubleshooting.html
=> http://wrapper.tanukisoftware.com/doc/german/howto.html
=> http://wrapper.tanukisoftware.com/doc/german/qna.html
8. Support
-----------------------------------------------------------------------------
Bitte gehen Sie auf unsere Supportseite:
=> http://wrapper.tanukisoftware.com/doc/german/support.jsp
9. Systemvoraussetzungen
-----------------------------------------------------------------------------
Eine vollständige Liste der unterstützten Plattformen und Systemvoraussetzungen
können Sie auf der folgenden Seite finden:
=> http://wrapper.tanukisoftware.com/doc/german/supported-platforms.html
-----------------------------------------------------------------------------
Copyright (C) 1999-2013 Tanuki Software, Ltd. All Rights Reserved.
wrapper_3.5.22_src/README_en.txt 100644 0 0 12773 12224722020 13546 0 ustar 0 0 -----------------------------------------------------------------------------
Java Service Wrapper Community Edition 3.5.22
Copyright (C) 1999-2013 Tanuki Software, Ltd. All Rights Reserved.
http://wrapper.tanukisoftware.com
-----------------------------------------------------------------------------
Summary:
1. What is the Java Service Wrapper?
2. Documentation
3. Installation
4. License Options
5. How to buy
6. Getting Updates
7. FAQ
8. Support
9. System Requirements
1. What is the Java Service Wrapper?
-----------------------------------------------------------------------------
The Java Service Wrapper is an application which has evolved out of a desire
to solve a number of problems common to many Java applications.
Some of the Wrapper's features are:
* Run a Java application as a Windows Service or Unix Daemon
* Java Application Reliability
* Automatic Crash, Freeze, and Deadlock Detection and Recovery
* On Demand Restarts
* Standard, Out of the Box Scripting
* Flexible Cross Platform Configuration
* Ease Application Installations
* Logging
* Many more...
See our download page for a more detailed feature list.
=> http://wrapper.tanukisoftware.com/doc/english/download.jsp
For more information please visit
=> http://wrapper.tanukisoftware.com/doc/english/introduction.html
2. Documentation
-----------------------------------------------------------------------------
Please visit our website for full documentation.
Here are some ways to get you started.
* Complete documentation can be found online:
=> http://wrapper.tanukisoftware.com/
* How to integrate the Java Service Wrapper with an Application
=> http://wrapper.tanukisoftware.com/doc/english/integrate.html
* Configuration Properties
=> http://wrapper.tanukisoftware.com/doc/english/properties.html
* HOWTOs
=> http://wrapper.tanukisoftware.com/doc/english/howto.html
* Javadocs, for advanced users
=> http://wrapper.tanukisoftware.com/doc/english/javadocs.html
* Tanuki Software, Ltd. Corporate site:
=> http://www.tanukisoftware.com/
3. Installation
-----------------------------------------------------------------------------
If you are reading this it means you successfully unpacked this software.
The Standard and Professional Editions of the Java Service Wrapper ship with
a time limited, but full featured, trial license key which allows you to run
the Wrapper as many times as you want for up to 15 minutes. This is meant
for quick no hassle testing.
You can also request a FREE 1 month trial license which allows you to run the
Wrapper for a full month on a single server. Trial licenes can be obtained
at the following URL:
=> http://wrapper.tanukisoftware.com/doc/english/requestTrial.jsp
Permantent licenses can also be purchased at the following URL:
=> http://wrapper.tanukisoftware.com/doc/english/accountLicenses.jsp
The Community Edition does not require a license key.
If you have already purchased a license, you can generate and download your
license key by logging on and viewing your License Management Page.
For Server Licenses:
=> http://wrapper.tanukisoftware.com/doc/english/accountServerLicenses.jsp
For Development Licenses:
=> http://wrapper.tanukisoftware.com/doc/english/accountDevLicenses.jsp
Depending on the specific type of Java application that will be run with the
Wrapper, there are a few integration options available:
=> http://wrapper.tanukisoftware.com/doc/english/integrate.html
4. License Options
-----------------------------------------------------------------------------
The Java Service Wrapper is made available in under three licenses.
* Development License Agreement (Commercial)
* Server License Agreement (Commercial)
* Community License Agreement (GPL2)
For more information, please browse our license overview:
=> http://wrapper.tanukisoftware.com/doc/english/licenseOverview.html
5. How to buy
-----------------------------------------------------------------------------
If you are interested in the features available with our Standard or
Professional Editions, licenses can be purchased online:
=> http://wrapper.tanukisoftware.com/doc/english/accountLicenses.jsp
6. Getting Updates
-----------------------------------------------------------------------------
You can always find the latest Wrapper release on our download page:
=> http://wrapper.tanukisoftware.com/doc/english/download.jsp
We also offer an upgrade guide:
=> http://wrapper.tanukisoftware.com/doc/english/howto-upgrade.html
7. FAQ
-----------------------------------------------------------------------------
Please see our general FAQ page:
=> http://wrapper.tanukisoftware.com/doc/english/faq.html
We also offer Troubleshooting, HOWTOs, and a Question & Answers page:
=> http://wrapper.tanukisoftware.com/doc/english/troubleshooting.html
=> http://wrapper.tanukisoftware.com/doc/english/howto.html
=> http://wrapper.tanukisoftware.com/doc/english/qna.html
8. Support
-----------------------------------------------------------------------------
Please see the following page for support options:
=> http://wrapper.tanukisoftware.com/doc/english/support.jsp
9. System Requirements
-----------------------------------------------------------------------------
A full list of supported platforms and system requirements can be found
online:
=> http://wrapper.tanukisoftware.com/doc/english/supported-platforms.html
-----------------------------------------------------------------------------
Copyright (C) 1999-2013 Tanuki Software, Ltd. All Rights Reserved.
wrapper_3.5.22_src/README_es.txt 100644 0 0 15413 12224722020 13545 0 ustar 0 0 -----------------------------------------------------------------------------
Java Service Wrapper Community Edition 3.5.22
Copyright (C) 1999-2013 Tanuki Software, Ltd. All Rights Reserved.
http://wrapper.tanukisoftware.com
-----------------------------------------------------------------------------
Resumen:
1. ¿Qué es el Java Service Wrapper?
2. Documentación
3. Instalación
4. Tipos de Licencia
5. ¿Cómo comprar?
6. Actualizaciones
7. FAQ
8. Soport Técnico
9. Requisitos del Sistema
1. ¿Qué es el Java Service Wrapper?
-----------------------------------------------------------------------------
El Java Service Wrapper es una aplicación que ha evolucionado con el deseo de
resolver una seria de problemas comúnes encontrados en aplicaciones Java.
Alguna de nuestras características son:
* Correr aplicaciones Java como Servicio de Windows o Demonio de Unix
* Fiabilidad en Aplicaciones Java
* Detección y recuperación automática cuando se presenta un tipo de Crash,
congelamiento o bloqueo (Deadlock)
* Reinicios de la JVM en demanda
* Scripts listos para implementar una forma de instalación estándar.
* Configuración flexible en varias plataformas
* Instalaciones más fáciles
* Y muchas más...
Por favor visite nuestra página de Descargas para una lista más detallada.
=> http://wrapper.tanukisoftware.com/doc/english/download.jsp
(Sólo Inglés)
Para más información por favor visite
=> http://wrapper.tanukisoftware.com/doc/english/introduction.html
(Sólo Inglés)
2. Documentación
-----------------------------------------------------------------------------
Por favor visite nuestro sitio web para ver toda nuestra documentación.
Aquí hay algunas maneras de empezar.
* La documentación completa puede ser encontrada en línea en:
=> http://wrapper.tanukisoftware.com/
(Sólo Inglés)
* ¿Cómo integrar el Java Service Wrapper con mi aplicación?
=> http://wrapper.tanukisoftware.com/doc/english/integrate.html
(Sólo Inglés)
* Configuración de Propiedades
=> http://wrapper.tanukisoftware.com/doc/english/properties.html
(Sólo Inglés)
* HOWTOs
=> http://wrapper.tanukisoftware.com/doc/english/howto.html
(Sólo Inglés)
* Javadocs, para usuarios avanzados
=> http://wrapper.tanukisoftware.com/doc/english/javadocs.html
(Sólo Inglés)
* Sitio de la compañia - Tanuki Software, Ltd.:
=> http://www.tanukisoftware.com/
3. Instalación
-----------------------------------------------------------------------------
Si usted está leyendo esto, quiere decir que ha podido desempacar exitosamente
nuestro software.
Las ediciones estándar y profesionales del Java Service Wrapper son
distribuidas con una licencia de prueba limitada, con todas las características
habilitadas pero sólo cuenta con una duración de 15 minutos.
Usted puede ejectuar nuestro software tantas veces quiera, esto le ofrece una
manera rápida y sencilla de probar el Java Service Wrapper.
Usted tambien puede adquirir una licencia gratuita de prueba válida por un mes.
Esta licencia le permite ejecturar nuestro programa en un servidor, sin ningún
límite de tiempo de ejecución y con todas las características habilitadas.
La licencia de prueba puede ser adquirida en:
=> http://wrapper.tanukisoftware.com/doc/english/requestTrial.jsp
(Sólo Inglés)
Para adquirir una licencia permanente, usted la puede comprar en:
=> http://wrapper.tanukisoftware.com/doc/english/accountLicenses.jsp
(Sólo Inglés)
La edición para la comunidad (Community Edition) no require una licencia.
Si usted ya compró una licencia, por favor genere su licencia en nuestro
sitio web, para esto usted necesita entrar los datos de su cuenta con la que
adquirio el producto.
Para administrar licencias tipo servidor (Server), por favor visite:
=> http://wrapper.tanukisoftware.com/doc/english/accountServerLicenses.jsp
(Sólo Inglés)
Para administrar licencias tipo desarrollo (Development), por favor visite:
=> http://wrapper.tanukisoftware.com/doc/english/accountDevLicenses.jsp
(Sólo Inglés)
Como cada aplicación Java es diferente, nosotros ofrecemos varios tipos
de integración, por favor visite:
=> http://wrapper.tanukisoftware.com/doc/english/integrate.html
(Sólo Inglés)
4. Tipos de Licencia
-----------------------------------------------------------------------------
El Java Service Wrapper está disponible bajo tres licencias.
* Licencia de Desarrollo (Comercial) (Development License)
* Licencia para Servidores (Comercial) (Server License)
* Licencia para la Comunidad (GPL2) (Community License)
Para más información, por favor visite nuestra página de licencias en:
=> http://wrapper.tanukisoftware.com/doc/english/licenseOverview.html
(Sólo Inglés)
5. ¿Cómo comprar?
-----------------------------------------------------------------------------
Si está interesado en características solo disponibles para nuestras
ediciones Estándar y Profesional, usted necesita comprar una licencia.
Usted puede comprarlas en línea visitando:
=> http://wrapper.tanukisoftware.com/doc/english/accountLicenses.jsp
(Sólo Inglés)
6. Actualizaciones
-----------------------------------------------------------------------------
Usted siempre puede encontrar la versión más reciente en:
=> http://wrapper.tanukisoftware.com/doc/english/download.jsp
(Sólo Inglés)
Nosotros también ofrecemos una guía para actualizar nuestro software en:
=> http://wrapper.tanukisoftware.com/doc/english/howto-upgrade.html
(Sólo Inglés)
7. FAQ
-----------------------------------------------------------------------------
Para ver nuestro FAQ general, por favor visite:
=> http://wrapper.tanukisoftware.com/doc/english/faq.html
(Sólo Inglés)
Solución de problems, HOWTOs o nuestra sección de Preguntas y Respuestas
=> http://wrapper.tanukisoftware.com/doc/english/troubleshooting.html
=> http://wrapper.tanukisoftware.com/doc/english/howto.html
=> http://wrapper.tanukisoftware.com/doc/english/qna.html
(Sólo Inglés)
8. Soporte Técnico
-----------------------------------------------------------------------------
Por favor visite nuestra página de soporte para más opciones.
Usted puede ver las opciones disponibles en:
=> http://wrapper.tanukisoftware.com/doc/english/support.jsp
(Sólo Inglés)
9. Requisitos del Sistema
-----------------------------------------------------------------------------
La lista completa de plataformas soportadas y requisitos necesarios puede ser
encontrada en:
=> http://wrapper.tanukisoftware.com/doc/english/supported-platforms.html
(Sólo Inglés)
-----------------------------------------------------------------------------
Copyright (C) 1999-2013 Tanuki Software, Ltd. All Rights Reserved.
wrapper_3.5.22_src/README_ja.txt 100644 0 0 17015 12224722020 13530 0 ustar 0 0 -----------------------------------------------------------------------------
Java Service Wrapper Community Edition 3.5.22
Copyright (C) 1999-2013 Tanuki Software, Ltd. All Rights Reserved.
http://wrapper.tanukisoftware.com
-----------------------------------------------------------------------------
概要:
1. Java Service Wrapperとは?
2. ドキュメンテーション
3. インストール
4. ライセンスの種類
5. ライセンス購入方法
6. アップデート方法
7. よくある質問FAQ
8. サポート
9. システム要件
1. Java Service Wrapperとは?
-----------------------------------------------------------------------------
Java Service Wrapperは、多くのJavaアプリケーションによくある問題を解決したい
という多くの要望に応えて登場したアプリケーションです。
主なWrapperの特徴:
* WindowsサービスやUnixデーモンとしてJavaアプリケーションを動かす
* 信頼性のあるJavaアプリケーション
* クラッシュ、フリーズ、デッドロックなど自動検知および自動リカバリー
* オン・デマンドによる再起動
* 簡単にすぐ使えるスクリプトつき
* クロスプラットフォームに対応した柔軟なコンフィギュレーション
* アプリケーションの簡単インストール
* ログ
* もっと詳しく...
さらに詳しい特徴などはダウンロード・ページをご覧ください。
=> http://wrapper.tanukisoftware.com/doc/japanese/download.jsp
さらに詳しくはこちらもご覧ください。
=> http://wrapper.tanukisoftware.com/doc/japanese/introduction.html
2. ドキュメンテーション
-----------------------------------------------------------------------------
完全なドキュメンテーションをご覧になりたい場合にはウェブサイトをご覧ください。
「始めるには?」を簡単にご紹介します。
* オンラインで完全なドキュメンテーションをご覧になれます:
=> http://wrapper.tanukisoftware.com/doc/japanese/
* JavaアプリケーションをJava Service Wrapperとインテグレーションする方法:
=> http://wrapper.tanukisoftware.com/doc/japanese/integrate.html
* コンフィギュレーション・プロパティ一覧:
=> http://wrapper.tanukisoftware.com/doc/japanese/properties.html
* HOWTO(ハウツー):
=> http://wrapper.tanukisoftware.com/doc/japanese/howto.html
* Javadocs(上級レベルのユーザー向け):
=> http://wrapper.tanukisoftware.com/doc/japanese/javadocs.html
* タヌキソフトウェア有限会社サイト:
=> http://www.tanukisoftware.com/ja/
3. インストール
-----------------------------------------------------------------------------
これを読む前にソフトウェアをダウンロードで入手して解凍してスタンバイください。
Java Service Wrapperのスタンダード版やプロフェッショナル版には、時間制限つきの
トライアル・ライセンスを同梱してあり、全ての機能を利用できます。
このライセンスキーでは1回の稼働が最長15分までに制限されていますが、
回数に関係なく何度でも利用が可能です。簡単にクイックテストなど便利に使えます。
さらに長時間の利用を希望であれば、1台のサーバー上で使える1カ月の無料トライアル
ライセンスもご用意しています。
1カ月トライアル・ライセンスは次のページからリクエストすることができます:
=> http://wrapper.tanukisoftware.com/doc/japanese/requestTrial.jsp
永久ライセンスを購入されるには:
=> http://wrapper.tanukisoftware.com/doc/japanese/accountLicenses.jsp
Java Service Wrapperコミュニティー版にはライセンスキーは不要です。
既にライセンスを購入済みの方は、サイトにログインして、ライセンス管理ページで
ライセンスキーを生成することができます。
ライセンス管理(サーバーライセンス)ページ:
=> http://wrapper.tanukisoftware.com/doc/japanese/accountServerLicenses.jsp
ライセンス管理(開発ライセンス)ページ:
=> http://wrapper.tanukisoftware.com/doc/japanese/accountDevLicenses.jsp
Java Service Wrapperで動かすJavaアプリケーションの種類により、
いくつかインテグレーション方法があります:
=> http://wrapper.tanukisoftware.com/doc/japanese/integrate.html
4. ライセンスの種類
-----------------------------------------------------------------------------
Java Service Wrapperの利用には3つのライセンスがあります。
* 開発ライセンス契約 (商用ライセンス)
* サーバーライセンス契約 (商用ライセンス)
* コミュニティーライセンス契約 (GPL2ライセンス)
さらに詳しくは、ライセンス概要をご覧ください:
=> http://wrapper.tanukisoftware.com/doc/japanese/licenseOverview.html
5. ライセンス購入方法
-----------------------------------------------------------------------------
Java Service Wrapperスタンダード版あるいはプロフェッショナル版の機能を
ご利用になるには、オンラインでライセンスを購入することが可能です。
=> http://wrapper.tanukisoftware.com/doc/japanese/accountLicenses.jsp
銀行振り込みを希望される場合は sales@tanukisoftware までお問い合わせ願います。
銀行情報をご連絡いたします。
代理店、ディストリビューター経由からの購入も可能です。
=> http://www.tanukisoftware.com/ja/distributors.php
6. アップデート方法
-----------------------------------------------------------------------------
最新のJava Service Wrapperリリースはいつでもダウンロード・ページで入手できます:
=> http://wrapper.tanukisoftware.com/doc/japanese/download.jsp
最新版へのアップデート手順ガイド:
=> http://wrapper.tanukisoftware.com/doc/japanese/howto-upgrade.html
7. よくある質問FAQ
-----------------------------------------------------------------------------
よくある質問FAQページも便利に活用いただけることと思います:
=> http://wrapper.tanukisoftware.com/doc/japanese/faq.html
その他、トラブルシューティング、HOWTO, 質問と回答など各ページもご活用ください:
=> http://wrapper.tanukisoftware.com/doc/japanese/troubleshooting.html
=> http://wrapper.tanukisoftware.com/doc/japanese/howto.html
=> http://wrapper.tanukisoftware.com/doc/japanese/qna.html
8. サポート
-----------------------------------------------------------------------------
皆様が快適にユーザーサポートを受けられるよう、いくつかオプションをご用意して
います。サポートの詳細については弊社のサポートページをご覧ください:
=> http://wrapper.tanukisoftware.com/doc/japanese/support.jsp
9. システム要件
-----------------------------------------------------------------------------
サポートされているプラットフォームやシステム要件など完全なリストを
オンラインでご用意していますのでご参照ください:
=> http://wrapper.tanukisoftware.com/doc/japanese/supported-platforms.html
-----------------------------------------------------------------------------
Copyright (C) 1999-2013 Tanuki Software, Ltd. All Rights Reserved.
wrapper_3.5.22_src/build-tests.xml 100644 0 0 307540 12224722016 14373 0 ustar 0 0
wrapper.java.classpath.1=../lib/wrapper.jar
wrapper.console.format=PM
wrapper.console.format=PM
wrapper.console.format=PM
]]>
wrapper.java.additional.1=
wrapper.java.additional.1=-verbose:gc
wrapper.java.additional.1=
]]>
wrapper.syslog.loglevel=NONE
wrapper.syslog.loglevel=NONE
wrapper.java.additional.1=
wrapper.syslog.loglevel=NONE
wrapper.syslog.loglevel=NONE
wrapper.java.additional.1=
wrapper.java.classpath.1=../lib/wrapper.jar
wrapper.java.classpath.1=../lib/wrapper.jar
wrapper.java.classpath.1=../lib/wrapper.jar
]]>
-Dparam=param
-Dparam="Hello World."
-Dparam="Hello World."
#encoding=UTF-8
-Dparam=param
# This is a comment.
-Dparam1=param1 # This is another comment.
-Dparam2=##param2
-Dparam3="#param3"
wrapper.java.additional.1=
wrapper.java.additional.1=
wrapper.java.additional.1=
setlocal
the needs of your application
wrapper_3.5.22_src/build.xml 100644 0 0 330721 12224722016 13230 0 ustar 0 0
wrapper.check.deadlock.interval=60
wrapper.java.classpath.1=../lib/wrapper.jar
# Wrapper Properties
wrapper.java.classpath.1=../lib/wrapper.jar
# Out Of Memory detection.
**********************************************************
* Pre-release distributions can only be generated using *
* Java 1.4 JVMs to guarantee that the resulting jars *
* will run on all platforms. *
* This is a ${java.specification.version} JVM. *
**********************************************************
<html><body>
The javadocs for this application are found in $WRAPPER_HOME/jdoc.tar.gz. Please extract this
archive into the $WRAPPER_HOME directory.<p>The javadocs could not be included directly in the
original tar distribution due to a lack of support for long path names in some tar implementations.
</body></html>
**********************************************************
* An intermediate pre-release distribution has been *
* created in the dist directory. This file can be *
* expanded on any system to quickly produce a native *
* release by running "build<64/32> release". *
* *
* Alternately a release can be generated for the current *
* platform by running "build<64/32> release" now. *
* *
* Intermediate pre-release distributions: *
* ${dist.dir}/${intermfile}.zip
* ${dist.dir}/${intermfile}.tar.gz
**********************************************************
**********************************************************
* You must first either run the pre-release task in a *
* full source distribution or run within an intermediate *
* pre-release distribution. *
**********************************************************
ERROR:
**************************************************************************
* The password for the CodeSigning Certificate is not set.
* Please define it on the commandline: ant -Dwrapper.cert.password="..."
**************************************************************************
ERROR:
****************************************************************************
* Please specify the path for SignTool in default.properties (signtool.dir).
****************************************************************************
ERROR:
************************************************************************************************************
* The directory specified in signtool.dir (${signtool.dir}) does not exist/or does not contain signtool.exe.
* Please verify the folder contains the file!!
************************************************************************************************************
ERROR:
****************************************************************************
* Please specify the path to the certificate in default.properties (cert.dir).
****************************************************************************
ERROR:
************************************************************************************************************
* The directory specified in cert.dir (${cert.dir}) does not exist/or does not contain the certificate codesigncert.pfx.
* Please verify the folder contains the file!!
************************************************************************************************************
# Wrapper Properties
wrapper.java.classpath.1=../lib/wrapper.jar
# Out Of Memory detection.
**********************************************************
* A native release distribution has been created in the *
* dist directory. *
* *
* Release distribution: *
* ${dist.dir}/${releasefile}.zip
**********************************************************
# Wrapper Properties
wrapper.java.classpath.1=../lib/wrapper.jar
# Out Of Memory detection.
<html><body>
The javadocs for this application are found in $WRAPPER_HOME/jdoc.tar.gz. Please extract this
archive into the $WRAPPER_HOME directory.<p>The javadocs could not be included directly in the
original tar distribution due to a lack of support for long path names in some tar implementations.
</body></html>
**********************************************************
* A native release distribution has been created in the *
* dist directory. *
* *
* Release distribution: *
* ${dist.dir}/${releasefile}.tar.gz
**********************************************************
wrapper.check.deadlock.interval=60
wrapper.java.classpath.1=../lib/wrapper.jar
# Wrapper Properties
wrapper.java.classpath.1=../lib/wrapper.jar
<html><body>
The javadocs for this application are found in $WRAPPER_HOME/jdoc.tar.gz. Please extract this
archive into the $WRAPPER_HOME directory.<p>The javadocs could not be included directly in the
original tar distribution due to a lack of support for long path names in some tar implementations.
</body></html>
**********************************************************
* A delta-pack release distribution has been created in *
* the dist directory. *
* *
* Release distributions: *
* ${dist.dir}/${deltareleasefile}.zip
* ${dist.dir}/${deltareleasefile}.tar.gz
**********************************************************
wrapper_3.5.22_src/build32.bat 100644 0 0 366 12224722010 13254 0 ustar 0 0 @echo off
setlocal
set BUILDFILE=%~dp0%build.xml
echo --------------------
echo Wrapper Build System
echo using %BUILDFILE%
echo --------------------
call "%ANT_HOME%\bin\ant.bat" -f "%BUILDFILE%" -Dbits=32 %1 %2 %3 %4 %5 %6 %7 %8
wrapper_3.5.22_src/build64.bat 100644 0 0 363 12224722010 13256 0 ustar 0 0 @echo off
setlocal
set BUILDFILE=%~dp0%build.xml
echo --------------------
echo Wrapper Build System
echo using %BUILDFILE%
echo --------------------
call "%ANT_HOME%\bin\ant.bat" -f "%BUILDFILE%" -Dbits=64 %1 %2 %3 %4 %5 %6 %7 %8
wrapper_3.5.22_src/default.properties 100644 0 0 6616 12224722016 15114 0 ustar 0 0 # -------------------------------------------------------------------
# B U I L D P R O P E R T I E S
# -------------------------------------------------------------------
# Specifies default property values
# Overridden ant.properties
# Not user-editable; use ant.properties files instead
name = wrapper
Name = Wrapper
long.name = Java Service Wrapper Community ${Version}
Version = 3.5.22
version = ${Version}
version.root = 3.5.22
year = 2013
# NOTE - The version property gets corrupted by the use of Xalan
# so Version is used instead.
app.name = testwrapper
app.caps.name = TestWrapper
app.long.name = Test Wrapper Sample Application
app.desc = Test Wrapper Sample Application Description
# Settings used to configure compile environment
build.debug = on
build.optimize = off
build.deprecation = off
build.compress = false
junit.failonerror = true
# location of intermediate products
build.dir = ${basedir}/build
build.classes = ${build.dir}/classes
build.testclasses = ${build.dir}/testclasses
build.tests = ${build.dir}/tests
dist.dir = ${basedir}/dist
signtool.dir=C:\\Program Files\\Microsoft SDKs\\Windows\\v6.0\\Bin
cert.dir=
# Set the properties for existing directories
bin.dir = ${basedir}/bin
conf.dir = ${basedir}/conf
src.dir = ${basedir}/src
lib.dir = ${basedir}/lib
logs.dir = ${basedir}/logs
doc.dir = ${basedir}/doc
jdoc.dir = ${basedir}/jdoc
test.dir = ${basedir}/test
context.dir = ${src.dir}/documentation
tools.dir = ${basedir}/tools
# --------------------------------------------------
# REQUIRED LIBRARIES
# --------------------------------------------------
# List of possible locations for the visual studio setup scripts
vcvars.v8_32_1=c:\\Program Files\\Microsoft Visual Studio 10.0\\VC\\bin\\vcvars32.bat
vcvars.v8_32_2=d:\\Program Files\\Microsoft Visual Studio 10.0\\VC\\bin\\vcvars32.bat
vcvars.v8_32_3=c:\\Program Files\\Microsoft Visual Studio 9.0\\VC\\bin\\vcvars32.bat
vcvars.v8_32_4=d:\\Program Files\\Microsoft Visual Studio 9.0\\VC\\bin\\vcvars32.bat
vcvars.v8_32_5=c:\\Program Files\\Microsoft Visual Studio 8\\VC\\bin\\vcvars32.bat
vcvars.v8_32_6=d:\\Program Files\\Microsoft Visual Studio 8\\VC\\bin\\vcvars32.bat
vcvars.v8_32_7=C:\\Program Files\\Microsoft Platform SDK for Windows Server 2003 R2\\SetEnv.Cmd
vcvars.v8_32_7.arg.1=/XP32
vcvars.v8_32_7.arg.2=/RETAIL
vcvars.v8_32_8=C:\\Program Files\\Microsoft Platform SDK\\SetEnv.Cmd
vcvars.v8_32_8.arg.1=/XP32
vcvars.v8_32_8.arg.2=/RETAIL
vcvars.v8_x86_64_1=c:\\Program Files (x86)\\Microsoft Visual Studio 9.0\\VC\\bin\\vcvars64.bat
vcvars.v8_x86_64_2=c:\\Program Files\\Microsoft Visual Studio 9\\VC\\bin\\amd64\\vcvarsamd64.bat
vcvars.v8_x86_64_3=c:\\Program Files\\Microsoft Platform SDK for Windows Server 2003 R2\\SetEnv.Cmd
vcvars.v8_x86_64_3.arg.1=/XP64
vcvars.v8_x86_64_3.arg.2=/RETAIL
vcvars.v8_x86_64_4=c:\\Program Files\\Microsoft Platform SDK\\SetEnv.Cmd
vcvars.v8_x86_64_4.arg.1=/XP64
vcvars.v8_x86_64_4.arg.2=/RETAIL
vcvars.v8_x86_64_5=C:\\Program Files\\Microsoft SDKs\\Windows\\v7.1\\Bin\\SetEnv.cmd
vcvars.v8_x86_64_5.arg.1=/x64
vcvars.v8_x86_64_6=c:\\Program Files (x86)\\Microsoft Visual Studio 11.0\\VC\\bin\\x86_amd64\\vcvarsx86_amd64.bat
vcvars.v8_ia_64_1=c:\\Program Files\\Microsoft Platform SDK\\SetEnv.Cmd
vcvars.v8_ia_64_1.arg.1=/SRV64
vcvars.v8_ia_64_1.arg.2=/RETAIL
# --------------------------------------------------
# OPTIONAL LIBRARIES
# --------------------------------------------------
wrapper_3.5.22_src/doc/index.html 100644 0 0 703 12224722016 14063 0 ustar 0 0
Java Service Wrapper Documentation
Complete documentation can be found online:
http://wrapper.tanukisoftware.org
Java docs are available online as well:
http://wrapper.tanukisoftware.org/jdoc/index.html
wrapper_3.5.22_src/doc/revisions.txt 100644 0 0 625776 12224722016 14757 0 ustar 0 0 Java Service Wrapper Revision History.
--------------------------------------
3.5.22
* (Standard, Professional) Fix a crash in native code behind WrapperResources
instances which could happen if the system was very low on memory. Since
version 3.5.7.
* (Professional) Fix a couple slow memory leaks in the native code involved
with launching and checking on the status of child processes.
* (Professional) Fix a problem where an attempt to throw a WrapperJNIError
within native code on Z/OS would result in a ClassNotFoundException being
thrown.
* Reviewed the native JNI code and fixed a few potential crashes and memory
leaks which could occur under low memory conditions.
* Modify the way the wrapper.console.direct property works so the Wrapper will
now always downgrade itself to using piped console writing as soon as it has
determined that a physical console does not exist. In 3.5.21 we tried to
predict when the console would not exist and disabling it in advance. There
were cases where this was not correct, resulting in error messages in the
console output.
* Fix a problem where operations like installing a service on Windows 7 and
above which need to be elevated were resulting in an error that the Wrapper
could not write to the console. The actual operation was working correctly
but the console output was incorrect. Since 3.5.21.
* Move the check that the jar and wrapper versions match earlier in the startup
process so we guarantee that a warning will always be displayed. There were
some errors which could abort the startup process before this warning was
logged.
* (Standard, Professional) Fix a problem where the value of wrapper.lang.folder
was not being recognized if a wrapper.lang value was not set.
* (Standard, Professional) Fix a small memory leak resolving the language to
run the Wrapper with.
* (Professional) Fix a potential buffer overlow reading data from a child
process stderr or stdout if the amount of data available in the pipe is
larger than the buffer length passed in to WrapperProcessInputStream.
read(byte b[], int off, int len).
* (Professional) Fix a problem where reads from a WrapperProcessInputStream
were consuming too much CPU while blocking for data on Windows. Now
correctly being done asynchronously.
* (Professional) Fix a problem where JVM cleanup, including cleanup of child
processes, was not always being done completely if the user requested an
immediate shutdown by pressing CTRL-C twice.
3.5.21
* Add a new 'R' log format which will track the number of milliseconds since
the previous JVM log output. Useful for simple performance checks. See
the wrapper.console.format, wrapper.event.default.email.maillog.format,
wrapper.logdialog.format, and wrapper.logfile.format properties.
* When the ACCESS_VIOLATION testing command of the wrapper.commandfile was used
to kill the Wrapper some log output was not making it into the wrapper.log
file. Add a forced flush just before crashing the Wrapper to make sure
everything makes it into the log file.
* Add a new wrapper.javaio.buffer_size property which makes it possible to
control the size of the internal buffer used to process console output from
the JVM. Also increased the default from the system default to 65536 bytes.
* Renamed the wrapper.use_javaio_thread property to wrapper.javaio.use_thread.
The old property still exists as a deprecated alias.
* Added a new wrapper.console.direct property on Windows which tells the
Wrapper to use Windows APIs to render log output to the console rather than
writing to stdout and stderr. This results in a major speed improvement.
The drawback is that this removes the ability to pipe the output to another
program on the command line. We chose to enable this by default so the
majority of users can take advantage of the speed improvement. If your
application takes advantage of piping on Windows, you will need to disable
this property to regain the old behavior.
* Add a new "wrapperm" logging source on Windows to help differentiate which
log entries are coming from Wrapper invocations used to control the Wrapper
as a service such as starting, stopping, installing, etc. Previously the
log entries from the Wrapper service process and launching process both
used a "wrapper" logging source, which could be confusing.
* On UNIX, modify the way we keep track of whether the process is daemonized or
not. This was done to clean up a bit, but should not effect how the Wrapper
works.
* On Windows, change the timing of when PID files are created when running as
a service so any failures creating them will correctly be reported as a
service error. If the Wrapper was unable to write to a PID file because it
was read-only then the user was presented with a confusing message about
the service timing out on startup. This was in addition to the correct
error being logged.
* Fix a potential problem where internally queued log entries could fail to be
logged on shutdown. The log queue is now always processed as part of the
shutdown process.
* Modify UNIX shell script to remove all existing run level rc files for the
application on both install and remove, rather than only the ones for the
currently configured run level to avoid unexpected behavior due to old rc
files being left around. This only affects platforms which make use of
rc files.
* Add a new RUN_LEVEL variable to the UNIX shell script to make it easy to
configure the run levels when installing as a daemon on various platforms.
* Add new wrapper.logfile.close.timeout and wrapper.logfile.flush.timeout
properties, and deprecate the wrapper.logfile.inactivity.timeout property,
to increase control over when and how the logfile is flushed and closed.
* Add a new PIDFILE_CHECK_PID setting in the UNIX shell script which makes it
possible to control whether or not the script double checks that the pid in
an existing pidfile is actually the pid of the application's Wrapper. This
property makes it possible to disable this check so multiple applications
can be tied to the same pid file.
* Go through and make sure that none of the Wrapper native JNI methods are
called after the WrapperManager shutdown has completed. Doing so was causing
a JVM crash on some Linux JVMs. This was happening when a WrapperResources
instance was finalized by the garbage collector on shutdown.
* (Professional) Fix a problem where processes created by calling the
WrapperManager.exec functions could fail to be registered with the Wrapper
for cleanup if the call was made as the JVM was shutting down. This was
resolved by making sure that JNI calls can not be called after the
WrapperManager shutdown has completed.
* Modify the internal WrapperManager tick thread so it is allowed to complete
once the WrapperManager has fully shutdown. This was the only remaining
reference to the WrapperManager class.
* Add a new wrapper.property_warning.loglevel property which controls the log
level at which the Wrapper will log warnings about undefined but referenced
environment variables, as well as invalid boolean or integer values.
* Update the way environment variables withing property values are parsed to
make it possible to report those are not defined. Each pair of '%'s is now
expected to be part of a variable reference. For example "%AAA%BBB%CCC%",
previosly if "AAA" was not defined, "BBB" would be located, but now only
"AAA" and "CCC" will be recognized as variables.
* Fix a problem on Windows where a non-existent wrapper.working.dir directory
was causing multiple error messages in the log file.
* Modify the way the wrapper.environment.dump property works so it will now
log at the INFO level with the rest of Wrapper output when set to true.
When false however, the output will be logged as DEBUG output if enabled.
Previous versions always logged the output to the INFO log level in either
case.
* Fix a problem on Linux IA64 where the WrapperActionServer was throwing an
IOException when the JVM was shutdown by calling System.exit. It did not
cause any problems other than the message in the log.
* (Professional) Added new "jvm_ping_timeout", "jvm_ping_slow", and
"jvm_ping_response_slow" events to help respond to ping related issues.
* Fix a problem where a value of 0 for wrapper.ping.alert.threshold was not
correctly disabling ping threshold alerts.
* (Professional) Fix a problem where the thread that handles events would
permanently get stuck if the event queue filled up. This was very unlikely
but not impossible if a large number of filter events were triggered in a
very short time. Corrected the problem so it now recovers correctly, but
also increased the queue size to make the overflow even more unlikely.
* (Standard, Professional) Fix a problem where console output of a wrapperw.exe
processes launched when the wrapper.ntservice.console property was TRUE was
not being shown correctly. This issue was introduced in 3.5.19.
3.5.20
* Further improvements to the memory footprint of the Wrapper to minimize the
memory required when logging JVM output consisting of very long lines.
* Fix a minor potential buffer overflow, which could occur if the path of the
first classpath element is larger than 1024 characters. This overflow was
detected during a code review and we have no reports that it actually ever
caused any problems.
* Improve the error message displayed when the Wrapper's configuration file
could not be loaded so that it now includes the name of the file.
* Work around a libc system library bug on some HPUX platforms in which calls
to vswprintf can cause a crash if the expanded string does not fit into the
buffer. Worked around the problem with the help of HP support by making sure
the buffer length followed a rule so that its length was 1+N where N is a
multiple of 8.
* Fix a problem on HPUX platforms where the JVM would sometimes get stuck on
shutdown, when the shutdown was initiated within the JVM, leading to the
Wrapper having to forcibly kill it. This was caused by the Wrapper
attempting to close the backend socket when another read was blocking
attempting to read from the same socket. This was introduced in version
3.5.8.
* Fix a potential log corruption when queued log messages were larger than the
internal buffer size. Found during a code review and is not known to have
actually caused any problems.
* Fix a typo in the shell script which was breaking the 'install' command on
Solaris platforms.
* Fix a potential crash on HPUX platforms if the value of the
wrapper.port.address property had an encoding problem.
3.5.19
* Fix a problem in the batch file, where a space in the path to the Wrapper.exe
file would cause the script to locate the Wrapper.exe file. Introduced in
3.5.18.
* When running as Windows service with hiding the console of the Wrapper will
cause the Wrapper to disable unnecessary logging to the console in order
to enhance performance.
3.5.18
* Fix a problem, where an unclosed percentage character '%' was opening the
chance of a dangling pointer in the additional java parameters. The '%'
character is a special character, specifying an environment variable.
* Added variable _WRAPPER_DIR the batch files to make it possible to specify
any other directory where the Wrapper binary file is located. Until now the
batch file and exe file had to be in the same location. Thanks and credits
go to Geoff.
* Added property wrapper.port.address, which makes it possible to specify a
different address to bind the socket to when using the socket backend
connection between the Wrapper and the JVM. Until now, the socket was
always bound to the localhost loopback interface.
* The script will from now on also use the update-rc.d tool for installing
an application as daemon on Debian. Thanks and credits go to Haifeng.
* Whenever the Wrapper is causing the JVM to be forcibly terminated, the
Wrapper will make sure the JVM has actually been terminated. If it wasn't
after wrapper.jvm_terminate.timeout seconds, a pending restart will be
canceled and the Wrapper exit.
* Reworked the way the Wrapper is processing output from the JVM, in order
to increase performance on huge output on a single line and also reduce
memory usage.
3.5.17
* Add a new wrapper.java.additional.default.stripquotes property to make it
possible to specify the default value of
wrapper.java.additional..stripquotes
* Fix a bug where the timer failed to calculate the fire time when that time
was more than one week in the future. This was possible for weekly timers
which spanned a daylight savings time change which rolled the time back by
an hour in the fall.
* Fix problem in the shell script, where it might fail to remove an installed
daemon after the location of the script has been changed.
* Add additional advice messages when a Windows service fails to be started
due to file access problems involving the Wrapper binary, configuration, or
log files.
* Fix a problem where the dynamic library on MacOSX was not able to load it's
functions.
* Added wrapper.app.parameter_file property, which works similar to the
wrapper.java.additional_file property
* Reduce CPU-consuption of WrapperProcess.waitFor() function
3.5.16
* (Standard, Professional) Retry failed share mappings if the target host or
network is unreachable as that may be a temporary problem.
* (Professional) There was a problem where the IO-redirection of a child
process which got created with the WrapperManager.exec API and used the
feature to run the child process in the logged on users desktop was
only allowing to create a process once per second.
* Include information about the base configuration file in the debug output
when debugging of cacading configuration files has been enabled.
* Add a check in the UNIX script to output a more descriptive error message,
when the user specified in the RUN_AS_USER variable doesn't exist.
* (Standard, Professional) Fix a problem where console log output was not being
displayed correctly when running with the WrapperW.exe binary with the
wrapper.ntservice.console property was set to true.
* (Standard, Professional) Implement the wrapper.ntservice.generate_console
property when using the WrapperW.exe binary so it is now possible to disable
the creation of the hidden console.
* Modify the way the the wrapper.ntservice.generate_console property works so
it is now easier to disable the generation of the console using just this
property.
* Improve the message logged when the the Wrapper attempts to perform a thread
dump without a valid console being available.
* Add new wrapper.ping.alert.threshold and wrapper.ping.alert.loglevel
properties which make it much easier to debug ping timeout issues by asking
the Wrapper to log messages about ping responses which were shorter than the
registered wrapper.ping.timeout, but longer than the threshold.
* Add a new WrapperManager.appearSlow method which makes it easier to test
how the Wrapper behaves when the JVM is being slow to respond to commands.
* Add a new wrapper.disable_tests property which can be used to disable all of
the testing methods of the WrapperManager class. It has always been possible
to control their access with a SecurityManager, but this is simpler for most
applications.
* Update the default wrapper configuration file template so a restart due to a
matched OutOfMemoryError filter will no longer be triggered by default if the
user enables -verbose:class output.
* Fix a problem on UNIX platforms where the Wrapper would fail to start if it
was located on the system PATH. This had been a problem since version 3.3.0
but had gone unnoticed as the Wrapper is not usually referenced in this way.
* Rework the internal flags governing the generation and hiding of the backend
console on Windows so we are able to almost always obtain the console's
window handle.
* Cleanup some startup code to reduce duplication and make sure that more debug
and warning messages are logged after the "Wrapper Started" message.
* Add new wrapper.java.additional_file and
wrapper.java.additional_file.stripquotes properties to make it possible to
specify JVM parameters in a file.
* Add support for Linux on ARM systems.
* Re-Enabled the forced reloading of the SYSTEM (and if set to a specific
account, the user) registry before launching the Wrapper as a service on
Windows XP and 2003. This has been originally disabeld for Windows XP and
2003 since version 3.5.5.
* (Standard, Professional) Fix a problem where the instance class names logged
when a deadlock involving ReentrantLock instances were corrupted. The actual
deadlock detection was working correctly, but this could have lead to other
problems caused by the corruption. A workaround was to set the
wrapper.check.deadlock.output property to SIMPLE.
* (Standard, Professional) Make it possible to completely disable the details
of a deadlock by setting the wrapper.check.deadlock.output property to NONE.
* (Standard, Professional) Object Ids in thread dump reports were not correctly
being logged as 64-bit ids on 64-bit JVMs in some cases.
* Fix a problem where the source code values returned by the
WrapperServiceActionEvent.getSourceCode() method were incorrect. The
constant values were incorrect and have been corrected from this release.
* Add new WrapperServiceActionEvent.getSourceCodeName() and
WrapperServiceActionEvent.getSourceCodeName(int actionSourceCode) methods
which returns a localized name of the source where the event originated.
* Fix a minor problem where a couple uncommon backend packet codes were not
being correctly identified by name in the debug log output. Functionally
they were all working correctly.
* Added property wrapper.ping.timeout.action, which will let you specify an
action in case the timeout triggers. So far the only action was to restart
the JVM.
* Fix a problem where a JVM process was not stopped completely on a UNIX
platform and stayed defunct after a forced kill until the Wrapper process
itself stopped. This was especially noticeable if the JVM is frozen and the
JVM is being killed forcibly.
3.5.15
* Add a new _WRAPPER_CONF_OVERRIDE setting to the Wrapper dedicated command
batch files on Windows so it is now possible to control whether or not the
first parameter is the configuration file name. The ability to specify an
alternate configuration file is now disabled by default as it was confusing
for users who tried to pass other parameters to the JVM.
* Correct a couple log messages in the WrapperManager class which were missing
the correct prefix identifying where they originated.
* Remove some old reflection code needed for Java 1.2.x support as we have
required Java 1.4 since version 3.4.0.
* Remove some code to try to reconnect the backend socket from Java. It has
never been possible to do so without restarting the JVM, and the related
messages were confusing.
* Add a new wrapper.disable_forced_shutdown property to make it possible to
disable the feature to forcibly kill the JVM on shutdown if CTRL-C was
pressed twice.
* Reduce the number of times thread priorities are changed within the
WrapperManager class to simplify the startup and shutdown process.
* Fixed a dangling pointer problem, which could cause undefined behaviour
whenever a property contained an unset environment variable.
* Fix a race condition in the timer thread, which could cause a sigkill
being propagated through the whole process group rather than the timer
thread. This can only happen during the shutdown of the Wrapper.
* When a child process, which got launched by WrapperManager.exec()
failed to start due to a runtime-error (such as missing privileges), the
forked heap persisted and the child process never finished until
shutdown/restart of the JVM. The error only appears on Unix platforms
when using the FORK_EXEC start-type.
* Change log level and message if a certificate check returned a problem,
which is not directly caused by the signature of the Wrapper, but the
signature chain.
* Fix a problem when the silent query command wasn't returning the correct
exit code on windows Vista (and later) when the command was run from an
unelevated console. Thanks to Darren for pointing this out.
* The java system property wrapper.backend.so_timeout was ignored if it
was set to 0, making it not possible to explicitly set the timeout to
be indefinitely.
* Added the properties wrapper.jvm.additional.auto_bits. to
individually turn on/off the feature for the supported platforms.
* Fix a problem where the script was trying to use the 64-bit binaries on
Mac OSX even if the CPU was only a 32-bit architecture. This only affected
versions of Mac OSX greater 10.5.0, the vast majority of those machines are
already 64-bit CPU's.
* The Wrapper when reloading the configuration file, was trying to access
data from the call stack of a function which was actually outside of the
memory range of the stack. This access violation might yield a segmentation
fault. This issue was introduced in 3.5.5. Thanks to Lincoln for helping
finding this problem.
3.5.14
* Fix a problem in the AppCommand.bat.in file where a parenthesis in the
file name of the Wrapper binary would have caused a
"PATH was unexpected at this time" error.
* (Standard, Professional) Fix a problem when using a localized version of
the Wrapper on Windows 64-bit platforms where the Wrapper would continue
to use the default system language even wrapper.lang was used to specify
a different language. Introduced in 3.5.12.
* Fix a problem in the Windows AppCommand.bat.in command based batch file
where the 'status' command was incorrectly being reported as 'query' in the
usage output. The 'status' command had always worked correctly if used.
* Fix a problem on UNIX platforms where some asynchronous messages were
causing a warning message "Coding Error..." to be logged in place of the
intended message. This could be seen if the configured log file did not
have write permissions. Other than the incorrect log message, the Wrapper
worked correctly. Introduced in 3.5.2.
* Fix a problem in the UNIX script where running with upstart wasn't working
correctly when RUN_AS_USER was set.
* Relax security checks when running the 'status' command against the UNIX
shell script so it now allows any user running the script to perform the
read-only check of the pid file.
* Fix a problem with the UNIX script where the 'remove' command was trying to
stop a running application even when the application had not been installed.
* Fix a buffer overflow which could potentially cause a crash during the
installation of a Windows Service when wrapper.ntservice.account was
specified. This was introduced in 3.5.12.
* Fix a heap corruption which could occur on startup and potentially cause a
crash. Only Windows systems, which use the System Event logs, were affected.
Discovered from a code review, there had never been any reports of this
causing problems for users. This could happen if the configured wrapper.log
could not be written to as the Wrapper always tries to write to the Event
Log in such cases. Introduced in 3.5.12.
* Add a new version comparison between the UNIX shell script and Wrapper to
start showing a warning in case of a version mismatch. The check will only
work if the shell script and Wrapper are each of at least version 3.5.14.
* Added a new wrapper.pidfile.strict property which will tell the Wrapper not
to start if the pid file already existed. Defaults to false for backwards
compatibility.
* Make the Java side of the backend socket more resilient in case of a read
or write timeout. The backend socket does not have a timeout set by default
so this should not have been an issue. A couple users reported problems on
specific systems however which led to this fix.
* To aid in the testing of the backend socket timeout, a new
wrapper.backend.so_timeout system property was added to make it possible to
configure the backend socket to use a timeout. See the Javadocs of the
WrapperManager class for details.
3.5.13
* Fix a typo in the script where the environment variable 'TR_BIN' should
actually be 'TREXE'. This was causing the "install" command on UNIX
platforms to fail. Introduced in 3.5.12.
* Fix a heap corruption which could lead to a crash that would occur the
second time an internal buffer used for logging was expanded. The buffer
would be expanded the first time a log line over 2048 characters in length
was encountered. Then the second expansion would happen when a line at
least 1024 characters longer was encountered. Introduced in 3.5.11.
Bug ID #3423108
3.5.12
* Put more descriptive Text in case the Wrapper is using integration method 4,
but the jar file deos not specify the Main-Class correctly in its meta
information.
* Fix a bug when failing to grant the LogOnAsService permission to a domain
user.
* Fix a bug where the ident for the syslog on Unix platforms was broken since
3.5.0. This was because when opening the syslog, the Wrapper was freeing the
memory for pointing to ident. However the string pointer ident will be
retained internally by the Syslog routines. And must not free the memory that
ident points to. Bug #3404978.
* Add a check on the script to make sure the 'tr' command exists on Unix
platforms.
* Improve the parsing of log formats so that format tokens are recocognized
even if they are lower case. This affects the wrapper.console.format,
wrapper.event.default.email.maillog.format, wrapper.logdialog.format, and
wrapper.logfile.format properties.
* The Wrapper parses log formats by looking for known tokens, any invalid
tokens are simply ignored. If the entire format is made up of invalid tokens
then this resulted in the Wrapper logging an empty line, which was not very
useful and caused confusion when encountered. The Wrapper now reverts to the
default log format in such cases. This affects the wrapper.console.format,
wrapper.event.default.email.maillog.format, wrapper.logdialog.format, and
wrapper.logfile.format properties.
* Improve the debug output while loading native libraries to avoid confusion
about the meaning of the warning logged about attempts to load alternately
named native library files.
* Fix a problem on Unix platforms where the default umask was being set to 0000
rather than inheriting it from the parent process when running as a daemon
process. This can be a security problem as log and other files have global
read/write access. Introduced in 3.5.8. Can be worked around by setting
the wrapper.umask property to a safe value.
3.5.11
* Fix a potential crash on Windows caused by a buffer overflow. This has been
a problem since version 3.5.0 and affects configurations which define more
than one wrapper.ntservice.dependency.. Depending on what was in memory,
this did not always result in a crash. It has very reproducible behavior for
a given configuration file.
* Fix a problem on Windows where the Wrapper was taking 15 seconds or longer to
startup on some systems because the WinVerifyTrust system call was having
problems updating the CRL. This had been a problem since the Wrapper
binaries started being signed in version 3.5.7. If the WinVerifyTrust call
takes longer than the configured wrapper.startup_thread.timeout then the
Wrapper will continue to startup without further delay.
* (Standard, Professional) Explicitly remove the certificate of the customized
binary during customization. There were problems resigning the binary with
another certificate otherwise.
* If the Wrapper is unable to write to the configured wrapper.logfile for any
reason then we always fall back to a default log file and then log a message
about the failure. If the default also fails then that is also logged but
the messages would only be logged to the console in most cases. Modify the
Wrapper so we now always send both messages to the syslog or EventLog
regardless of what the wrapper.syslog.loglevel is set to. This is important
to help track down the cause of logfile access problems.
* Starting with version 3.5.0, it was internally possible to print out
multi-line log messages so that all of the lines would always be grouped
together in the log file. This version modifies the logging code slightly so
that such multi-line log output is now logged as a single message in the UNIX
sylog or Windows EventLog.
* Fix a problem where very long lines of output from the JVM would cause the
Wrapper to appear to hang for a while. The first time a single line of
output containing several hundred thousand characters was logged, an internal
buffer was being incrementally increased by 100 characters per cycle. The
Wrapper now increases the size based on last known size to greatly reduce the
number of cycles needed to choose a new buffer size.
* Modify the PAUSE_THREAD command so it is now possible to wait indefinitely.
Only useful for testing the Wrapper.
* Add a new PAUSE_LOGGER command to make it possible to pause the next log
entry. Only useful for testing the Wrapper.
* On UNIX, the stdout/stderr pipe between the JVM and Wrapper was not being
cleaned up correctly. This resulted in a small leak but was otherwise
harmless. The pipes are now cleaned up and initialized for each JVM
instance.
* Fix a problem where the Wrapper could fail to restart the JVM when the
restart request originated in the JVM if the system was experiencing very
heavy IO resulting in long disk IO queues. This was causing the Wrapper's
main loop to block on the write and miss the restart request, causing the
Wrapper to shutdown rather than restart. This could affect all platforms.
On Windows, it could also be reproduced by making a selection in the console
to freeze output and then making a request from within the JVM to restart.
* Add a new WrapperPropertyUtil helper class to make it easer to access Wrapper
property values from within the JVM.
* Fix a bug on some platforms where java log output could get corrupted due to
misuse of a strncpy system function. This function warns that some
implementations do not support overlapping memory copies. The problem could
only be reproduced on a single Linux test machine in lines following an empty
line of output. This problem has existed since 3.4.0.
3.5.10
* Setting wrapper.jvm.port to '0' (zero) will make the JVM to assign an
available port for the backend socket by itself.
* Add warnings in the log file if an integer configuration property value
contains a non-numerical value. Previously, the Wrapper would silently
ignore the problem and use the value of 0 if the number started with an
invalid character, it will now return the default value. If the property
value started with valid numerical characters then those were, and still will
be, used to generate a value, but the invalid characters will be trimmed.
The later is being kept this way to avoid breaking old configurations.
* Add warnings in the log file if a boolean configuration property has any
value other than TRUE or FALSE. It will still return a value of FALSE
for other values to avoid breaking old configurations.
* Add a warning if an invalid value is specified for the wrapper.on_exit.
property.
* Add a new wrapper.log.lf_delay.threshold property which makes it possible
to control how long a partial line of Java log output will be allowed to be
buffered until it is completed with a line feed. If the threshold is
exceeded then the partial line will be logged as a full line resulting in an
extra line feed in the log output. All previous versions would do this
within 1-2 ms. The default is now 500ms.
* (Standard, Professional) Make it possible to customize the manufacturer
through the customize options.
* (Professional) Fix a problem where the Wrapper was sending a CTRL-BREAK
rather than a CTRL-C signal to child processes launched with
WrapperManager.exec when destroying them on Windows. For most child
processes this was not a problem, but if the direct child process was a JVM
then the CTRL-BREAK was triggering a thread dump rather than asking the JVM
to exit. The Wrapper was then timing out and forcibly killing the JVM child
process.
* (Standard, Professional) Fixed a bug, where the timezone ICT when set by
the wrapper.timezone property got misinterpreted as IST.
* (Standard, Professional) Fixed a problem where the UTC offset value in the
wrapper.timezone property was not being parsed correctly on UNIX platforms.
This led to the Wrapper to using an offset UTC0000.
* Take out the warning about unset LANG environment variable on Linux and
AIX systems. On system startup, some systems fail to set the LANG
environment variable. This is not really a problem for the Wrapper and the
warning was causing confusion for users so we decided to remove it.
3.5.9
* (Standard, Professional) Fix a problem on Windows where network adapters
whose names contained "PRO/1000" were being removed from the list of hostids
displayed when "wrapper.exe -h" was run. This did not affect existing server
license key files generated for hostIds reported by 3.5.7 or earlier, or
development license keys. But it did cause the Wrapper to report that no
valid hostIds could be found when the Wrapper was started without a license
file. This was caused by some test code added in 3.5.8 that we failed to
remove.
* Fix a problem where the Wrapper was not correctly yielding control back to
its main loop when very large amounts of continuous output was being logged
from the JVM. Introduced in version 3.4.0. In versions prior to 3.5.8, this
could have caused the JVM to timeout and restart itself. That particular
issue was resolved but the Wrapper process in 3.5.8 would still have been
unresponsive when this was happening. The Wrapper will now always yeild back
to its main loop after 250 milliseconds of continuous logging.
* Fix a problem where the WrapperManager could block trying write debug output
if the current user application was writing very large amounts of output to
the console as well. In extreme circumstances this led to the Wrapper
thinking that the JVM was frozen. This was only an issue if debug output was
enabled.
* Restructured the shell script so all editions now use the same script again.
3.5.8
* (Standard, Professional) Starting with version 3.5.5, we invalidated the use
of all 00ff* hostids on Windows to avoid problems with changing hostids when
users have a Juniper Network Connect network adapter on their system. This
turned out to be too restrictive as Guest OSs running under Parallels also
make use of this hostid range. The Wrapper is now more careful to only
invalidate actual Juniper Network Connect hostids.
* (Standard, Professional) Improve the message shown to the user when the
Wrapper is unable to locate any hostids for a system.
* Fixed a problem with the wrapper script on Solaris, where the option -F was
not available for grep.
* Added Windows version information on the wrapper debug output.
* Added a wrapper.log.warning.threshold property which makes the Wrapper show
a warning whenever it detects that the Wrapper took a long time to record a
log message. This was added to test a reported issue caused by slow IO on
very heavily loaded systems.
* Fix a problem where a filter that requested the JVM to restart would be
ignored if the JVM exited on its own immediately. The Wrapper is now more
consistent so that restart requests from within the JVM or filters will
always take priority over such exit requests. External shutdown requests, or
those from other actions will still behave as they did in the past and
continue to shutdown the Wrapper. The Wrapper also logs messages in debug
output if an outstanding restart request is being preserved or ignored.
* Fixed a problem in the AppCommand.bat batch file which could occur on some
Windows platforms with certain multi-byte system encodings. The script has
been rewritten and questionable parts have been simplified. The functionality
of the script has been preserved.
* Added the environment variable WRAPPER_CONF_DIR, which can be used for
the configuration properties. Feature Request #3160644.
* Made the script exit with the right exit code received when running the
script as different user, specified in RUN_AS_USER. Bug #3185281.
* Fix an access violation which could happen when reporting that the code
signing certificate has failed to been verified.
* Log an error if the backend socket is forcibly closed externally. It had
been getting logged at a debug log level. The message is "An existing
connection was forcibly closed by the remote host. (0x2746)". Because the
message was only logged if debug output was enabled, the JVM would be
restarted with no clear explanation as to what happened. The source of the
socket closure is under investigation.
* (Professional) Added the Java call fireUserEvent to the WrapperManager API.
This enables to fire user event mails, actions without the filter trigger.
* Fix a warning on Mac versions if the configured java command was not a
universal binary. A check was added in 3.4.0 to make sure that the
wrapper.java.command pointed directly to an executable to avoid unexpected
behavior when running a script. The message is only a warning and the
Wrapper continues regardless. Standard ppc, ppc_64, x86_64, i386, as well
as the universal binaries will now all work correctly without a warning.
* The default value of the wrapper.*.umask properties is using the current
umask the process has. Before the default value was always 0022.
* Add a new wrapper.backend.type property that is used to control whether the
Wrapper communicates with the JVM using the traditional "SOCKET" or new
experimental "PIPE". This was added as a workaround to a rare problem where
some Windows machines are closing the socket at an OS level. This was only
ever seen on Windows 2003, but could exist on other Windows versions as well.
* Add a new experimental wrapper.use_javaio_thread property which causes the
Wrapper to handle all java console output in a dedicated thread.
* Add a new WrapperManager.isNativeLibraryOk() method which lets user code
easily test whether or not the native library was loaded and initialized on
startup.
* Add a new PAUSE_THREAD command to the wrapper.commandfile property which
makes it possible to test how the Wrapper behaves when various threads block
or freeze. This was used to simulate and reproduce issues on heavily IO
bound servers.
* Improve the way the Java side of the Wrapper behaves when the Wrapper fails
to ping the JVM for an extended period of time. The JVM used to exit to let
itself resync itself with the JVM. This was causing problems on systems
which were heavily IO bound because the Wrapper could block for a while while
trying to write to the log file and the JVM was exiting. The JVM will now
never exit under such circumstances. The JVM will never become orphaned
because it will still exit almost immediately if the backend socket or pipe
with the Wrapper is ever closed.
* Deprecate the WrapperManager.appearOrphan() method as it is used to simulate
a failure mode which is no longer possible with the Wrapper.
* Changed the way the Wrapper is handling certificate errors regarding the
code signing/timestamping certificate. The Wrapper will now only shutdown
itself if the signature of the binary was not successfully verified because
the binary or signature has been malformed but not if any problem with
the counter-signer has been found. Starting with 3.5.7, the Windows Wrapper
binaries are signed. Some users with locked down Windows 2008 systems had
problems with the Wrapper refusing to start because the Comodo certificate
had been disabled on their system.
* Add a new wrapper.java.detach_started property which makes it possible to use
the Wrapper as a simple tool to launch Java applications. When enabled, the
Wrapper terminates immediately and the JVM is left to run on its own. Also
add new wrapper.java.outfile and wrapper.java.errfile properties which make
it possible to redirect the stdout and stderr of the JVM to files when
detached.
* When running the Wrapper as a specified User Account, through the
wrapper.ntservice.account property, the Wrapper will add permission for the
account to log on as service automatically upon install. Feature Request
#3286491.
* Fixed a problem binding the backend socket on Windows. If another process
bound a port inside the wrapper.port.min and wrapper.port.max range using the
SO_EXCLUSIVEADDRUSE option, the Wrapper would stop at this port report
an Access Permission problem and omits binding any further port in the range.
This problem existed ever since the Wrapper was released.
3.5.7
* Changed the way the script is installing the daemon gets installed on an AIX
system. The script now uses inittab & SRC.
* Fix a problem in the shell script that was preventing the script from
starting the Wrapper correctly if a file or directory existed in the current
working directory which was one character in length. This was only a problem
when the delta-pack naming of the Wrapper was used. This was easy to
reproduce on AIX systems on system restart because a "u" directory exists in
the root directory by default. This had been a problem since 3.4.0 when
it was introduced as a fix to a Solaris problem. The root cause was a
missing set of quotes in the tr command.
* Fix a problem in the shell script that was preventing the script from finding
the running wrapper process when it was started when the working directory
was in the same directory as the wrapper binary, but queried later from
another location. It would also fail if it was started from another
location, but then queried from the location of the Wrapper. This was
introduced in version 3.5.6 when the script stopped changing the working
directory in the script.
* Add a new GC action that will cause the JVM to immediately perform a full
garbage collection sweep. See the wrapper.commandfile,
wrapper.filter.action., wrapper.check.deadlock.action, and
wrapper.timer..action properties for details.
* (Professional) Modify the wrapper.event..command.block.action
property slightly so it will now correctly warn if an unknown action is
encountered. It had been defaulting to CONTINUE silently.
* Modify the timing of the message shown when an #encoding directive is missing
from the top of a configuration file. It was only being logged if debug
output was enabled. It will now also be logged if the #include.debug
directive is specified.
* Fix the indentation of warning messages about encoding or include problems in
configuration files.
* (Standard, Professional) Fix a problem where include file problems could
cause the shell script to have errors due to invalid translated output from
the Wrapper.
* Add a warning when the maximum include depth is reached and include debugging
is enabled. The Wrapper had always just silently skipped the include.
* Fix a problem where #include.required directive was not correctly preventing
startup if the include file was missing but the required include was in a
nested include.
* Fix a problem where the cause of some fatal include problems were not being
logged correctly, resulting in a simple, non-informative message only that
the configuration file failed to be loaded. This was a problem since 3.5.5.
* Fix a Windows problem where the Wrapper could fail to start as a service if a
defined environment variable would expand to a length larger than the 32k
limit specified in the ExpandEnvironmentStrings system function. This was a
problem on all Windows platforms prior to version 3.5.5, but only on Windows
2000 since then, when the code used to reload the environment from the
registry was disabled for newer versions of Windows. We now simply skip the
expansion of the problem variable and continue with a warning. Bug #3103776.
* Add a set of optional system properties that the WrapperSimpleApp,
WrapperStartStopApp, and WrapperJarApp helper classes are aware of to tell
them to ignore uncaught exceptions thrown within the main methods of the user
application. The exceptions will still be logged, but they can now be
configured so that the main method is just allowed to end without causing the
Wrapper to shutdown in an error state. Java on its own will stay running in
such a case as long as it has launched at least one non-daemon thread prior
to the uncaught exception being thrown. This does not affect most users, but
an application was found that was having problems because of this difference
in behavior. See the javadocs of the helper classes for details.
* (Professional) Fix a problem when looking for the correct exit code to use
for the wrapper.event..command.on_exit. property. The Wrapper
now searches for a value as follows:
wrapper.event..command.on_exit.,
wrapper.event..command.on_exit.default,
wrapper.event.default.command.on_exit., then
wrapper.event.default.command.on_exit.default. The third pattern had been
getting skipped in previous versions since it was added in version 3.3.0.
* (Professional) Add logic to report a warning if an unexpected value is
specified for the wrapper.event..command.on_exit. or
wrapper.event..command.block.action properties.
* (Professional) Clean up the message log levels so the output is as expected
when using the wrapper.event..command.loglevel property.
* (Professional) Improve the wrapper.event..command.on_exit.
property so the configured action will now work even if the command exits
after the block time out has expired. In previous versions, there was no
way to make the Wrapper do anything other than continue.
* (Professional) Fix a problem where the Wrapper was failing to detect a JVM
exit correctly if an event command had been fired first. The only problem
was that the Wrapper was always reporting a JVM exit code of 0 rather than
the actual exit code.
* Fix a buffer overflow on Windows when either installing as a service, or
updating an existing service. The problem only occurred when properties
containing spaces, or Java passthrough arguments containing spaces were
specified on the command line. The running service did not have any
problems. This was introduced in 3.5.0.
* (Standard, Professional) Improve the error message logged when an unlicensed
version of the Wrapper's native library is used.
* (Standard, Professional) Fix a buffer overflow problem on Windows when
creating a customized Wrapper binary if the target binary name did not
include the ".exe" extension. This problem existed since its intruduction in
version 3.3.7.
* The wrapper.exe, wrapperw.exe and wrapper.dll binaries are now being signed
on Windows making it possible to verify that valid Tanuki Software binaries
are being used.
* Implemented a way to install, remove, start, stop, etc., the Wrapper as a
Windows service from a non-elevated (UAC) console. The Wrapper is elevated
transparently using a child process. This is needed starting with Windows
Vista and 2008 for smooth interaction with the Windows Service Manager.
* (Standard, Professional) Fix a problem where the wrapperjni_*.mo localized
files were not being loaded correctly. These messages are only shown when
debug output is enabled. Application and Wrapper localization was working
fine. Introduced in 3.5.5.
* (Standard, Professional) Enhanced the ability to run with localizations
other than the system language on Windows. The Wrapper process locale was
not being set correctly. So Japanese text was not always showing correctly
if the wrapper.lang property was set when the OS was English or German.
The Java process still has an issue where it will always start with the
system default value for the file.encoding system property. This can still
cause problems writing Japanese text when the file.encoding is German for
example.
* Added support in the shell script for starting/installing the wrapper on
system boot with upstart.
* Fix a problem in the shell script where it would fail to recognize a running
Wrapper if the Wrapper command line or path contained a square bracket.
* Modify the way we test for the existance of the temp directory so we now
generate our own file name rather than using File.createTempFile. On some
systems createTempFile was taking a long time because it requires that Java
initialize its internal entropy. We discovered that large numbers of files
in the java.tmpdir directory makes Java's entropy initialization code very
slow. This has been a potential issue since 3.5.0.
* Fixed a problem on Windows where passthrough arguments after a "--" which
contained spaces were not being passed through to the JVM intact, they were
being split at the spaces into multiple arguments.
* Fix a problem on Windows where the Wrapper could sometimes crash on shutdown
if more than one thread got into the cleanup code at the same time. This
did not affect running applications and was only an issue on shutdown. It
was more likely if a language pack was loaded. Introduced in 3.5.3.
3.5.6
* Fix a problem on UNIX platforms where the log file path was being calculated
incorrectly if an absolute path was specified for wrapper.logfile, and the
file did not already exist. A warning message was being displayed but the
Wrapper would continue using the default log file. There was a problem in
the message displayed which caused a crash on some platforms include Mac OSX.
Introduced in version 3.5.5.
* Fix a problem on Windows platforms where the Wrapper would crash if it could
not access the directory of the configured wrapper.logfile.
Introduced in version 3.5.5. Bug #3087424.
* Improve the way warnings are logged when there are problems writing to the
configured wrapper.logfile so that the message will now be logged into the
log file that the Wrapper ends up using in case it is successful in falling
back to a default log file.
* Fix a problem on Windows platforms where wrapper.java.additional.
properties that were specified on the command line, and contained spaces,
were not being requoted correctly when building up the Java command line.
Introduced in version 3.3.6.
* Fix a problem where the warning message logged for invalid values of the
wrapper.java.additional. property, contained corrupted text. Introduced
in version 3.3.6.
* Fix a problem on UNIX platforms where an invalid value for the
wrapper.java.additional. property was correctly being reported and then
skipped, but the resulting command line to launch the JVM had a blank value
that was causing the JVM to fail to launch. An invalid value is any value
that does not begin with a "-" character.
* Add a new WRAPPER_INIT_DIR environment variable which can be used to
reference the working directory from which the Wrapper was launched. This is
needed for certain applications because the Wrapper always changes its
working directory to the location of the Wrapper binary.
* Modify the UNIX shell script so it no longer changes the current working dir
to the location of the script. This is no longer needed because the Wrapper
has been changing the working directory to its own location since version
3.2.0.
* Add a new wrapper.request_thread_dump_on_failed_jvm_exit.delay property to
control how long the Wrapper will wait after doing a thread dump before
killing the Java process. This delay has always been hardcoded to 5 seconds.
* Clean up the text of several warning messages about invalid configuration
values to make them more consistent.
* (Professional) Add a new wrapper.jvm_kill.delay property which makes it
possible to control the amount of time to allow between the jvm_kill event
being fired and the JVM actually being killed. Useful if an external event
command is fired that needs to do something with the JVM process first.
* (Professional) Fix a problem where the output of the
wrapper.event..message and wrapper.event..loglevel
properties were not displaying correctly on UNIX platforms.
* (Professional) Fix a problem on UNIX platforms where the Java side of the
Wrapper was not being correctly notified if a large number of child
processes that had been launched with WrapperManager.exec, exited at the
same instant. Some of them were going into a defunct state until the next
child exited, at which point they would be cleaned up. This was mainly an
issue on JVM shutdown if the user code was calling WrapperProcess.waitFor()
as part of its shutdown process. WaitFor calls at any point were getting
stuck and would remain so until another child exited. As part of this fix,
there were also several changes to the Windows implementation to bring the
two code bases into sync.
* Fix a problem on Windows when multiple threads were creating Childobjects,
Handles could have been unintendedly get inherited by another Child Process,
causing problems on reading/writing to the Input/Output/Errorstream.
* Fix a problem on solaris and AIX when errno calls were not thread safe due
to a compiler switch.
* Fix a problem where debug level warning output while loading the Wrapper
configuration was being displayed on startup. This could be fixed because
the Wrapper actually loads the configuration twice, and such output is now
only logged on the second call.
* (Standard, Professional) Remove the undocumented ability to define a single
file share mapping without the index. This would cause confusion if used,
and complicated the code.
* (Standard, Professional) Fix a byte alignment problem caused by a bad
compiler directive on Windows platforms. It was known to cause a crash when
defining mapped drives on 64-bit Windows versions. The problem was in the
source since version 3.3.7, but is not known to cause any other issues.
* (Standard, Professional) Modify the messages displayed when network shares
are mapped or fail for some reason. Also add messages about them being
unmapped on shutdown.
* On some Windows platforms, a failure to delete a rolled log file was not
being reported correctly. The system function to delete a file was
returning success even if it had failed. We now double check.
* Fix a deadlock in the code that is used to send data to the Java process.
It was only possible if debug level output was enabled and log file rolling
was enabled. Introduced in 3.3.7.
* Fix a problem where the Wrapper was not notifying the JVM whenever the log
file was rolled and the new name was the same as the previous one, as it is
when wrapper.logfile.rollmode is anything other than NONE or DATE.
* Fix a problem where the WrapperManager.getWrapperLogFile() was not returning
the accurate log file name until the first time the log file was rolled after
each JVM invocation. This was only noticeable if the wrapper.logfile
contained either the "ROLLNUM" or "YYYYMMDD" tokens.
* Correct an error message that was displayed on UNIX platforms when the
configured java binary could not be accessed. The message referenced a
buffer whose contents were undefined on some platforms.
* Fix a problem on z/OS where due a difference in the API used to lock a
mutex compared to all other UNIX platforms, the mutex's locking and
unlocking code were effectively being ignored. This means that multiple
threads were able to access code which was not thread safe and could lead to
a crash of the Wrapper. This is a problem that has been in the code since
the first z/OS release and is not known to have actually caused any problems.
Starting with 3.5.1, this was only an issue if debug output was enabled.
Versions 3.3.9 through 3.5.0 could have also had problems whenever the
Wrapper received a system signal.
3.5.5
* Add new wrapper.filter.trigger. action, "SUCCESS". If this gets triggered
then the Wrapper will treat the current JVM invocation as a success, and
reset its internal failed invocation counter. This is useful for
applications that need to be restarted frequently.
* (Standard, Professional) Ignore Juniper Network Connect hostIds as they
change on each reboot and are thus unreliable as hostIds.
* Added a PASS_THROUGH setting to the UNIX shell script and Windows
AppCommand.bat.in files which tells them to pass any extra arguments directly
on to the JVM when it is launched.
* Added a FIXED_COMMAND setting to the UNIX shell script and Windows
AppCommand.bat.in files to make it possible to run either without specifying
a command. Mainly useful in conjunction with PASS_THROUGH.
* (Standard, Professional) Added a --passthrough option to the exe
customization, in order to tell the wrapper to precede the whole command line
through to the application in the JVM.
* (Standard, Professional) Added a --conf option to change the default conf
file, the wrapper tries opening when no conf file was explicitly specified.
* Added wrapper.ntservice.account.prompt. If set to TRUE the wrapper will
prompt for all account details (domain, account name, password).
* Fix a minor issue in #include file declarations where a leading space was not
required.
* Add a new #include.required directive which works the same as the #include
directive except that it will output an error and prevent the loading of the
configuration if the included file does not exist. Normally include files
are optional by design.
* Modify the error messages displayed when configuration files fail to load so
they now provide more information about where specifically the problem was.
* Disabled the forced reloading of the SYSTEM (and if set to a specific
account, the user) registry before launching the Wrapper as a service on
Windows. This was done originally in Windows NT because changes to the
configured environment were not being reflected when running a service unless
the system was first rebooted. Microsoft appears to have solved this problem
in Windows XP and 2003. In Windows 7 and 2008, this was actually causing a
problem because the SYSTEM registry contains a setting "USERNAME=SYSTEM" by
default that was overwriting the USERNAME when run as specific user. It was
decided to disable this registry loading for Windows versions starting with
XP and 2003. Of the supported versions, only 2000 is now reloading its
environment. The only difference from version 3.5.4 and earlier that could
be found is that when running as the SYSTEM user on Windows 7 or 2008, the
USERNAME environment variable will now be set to the host name followed by a
dollar sign rather than SYSTEM. This is actually how all other services
work. But just in case this is a problem, it can we resolved by adding a
"set.USERNAME=SYSTEM" property into the Wrapper configuration file.
Bug #3061490.
* (Standard, Professional) Fix a problem for Solaris and HP-UX where the socket
timeout properties for the email notifications were ignored.
* (Standard, Professional) Added wrapper.ntservice.recovery. properties to
define system level actions in the event that the Wrapper process itself
has a failure.
* (Standard, Professional) Fixed a problem in the WrapperProcess.waitFor() and
WrapperProcess.exitValue() call, where it would fail to return when called
after the Wrapper had initiated the shutdown of the JVM.
* (Standard, Professional) Add WrapperProcessConfig.setSoftShutdownTimeout(int)
method to tell the Wrapper how long to wait after nicely asking the child
process to shutdown cleanly when calling WrapperProcess.destroy(). Once the
timeout has ellapsed, the child process will be forcibly terminated. This
timeout had been hard coded to 5 seconds in earlier versions.
* Add more detailed usage output to the UNIX shell script.
* Make it possible to 'pause' and 'resume' the JVM from the UNIX shell and
Windows batch scripts.
* (Professional) Fix a minor memory memory leak while initializing timers.
* Fix a memory leak which could happen if there were any invalid strings in
localization resources.
* (Professional) Fix a bug where the wrapper.event..command.argv.
properties were not correctly parsed on Windows. This issue was introduced
in version 3.5.0.
* (Professional) Add the ability to define wrapper.event.default.command.argv.
properties that will be used if the event specific specific commands are not
defined. Mainly useful for testing.
* Fix a problem occuring when the wrapper failed to roll the log file causing
to write to the wrapper's default log (wrapper.log) file rather than
continuing to write to the current logfile.
* (Standard, Professional) Fix a put problem in the internal hash map
implemenation used for localization where values could be lost. This was
not a visible issue because of the data used.
* Add new wrapper.filter.allow_wildcards. property and make it possible to
specify wrapper.filter.trigger. patterns which contain '*' and '?'
wildcards.
* Add a commented alternative in the default OutOfMemoryError filter
configuration to make it more specific to only trigger on uncaught exception
stack traces. This is to avoid output like that from the
-XX:+PrintClassHistogram JVM argument from causing the JVM to restart with a
false out of memory warning. See the wrapper.filter.trigger.
OutOfMemoryError example for more details.
* Localize the default filter message.
* Added ISO-8859-* encoding support and a few other encodings.
* (Standard, Professional) Fix a problem on UNIX versions, parsing dates in
license keys that was introduced in version 3.5.0. Windows verisons did not
have this problem. All license upgrade terms and lease terms which contained
"08" or "09" as either a month or day were being parsed incorrectly. This
was leading the Wrapper to interpret those date components as "00". If the
number was the date, then this would cause the date to be set to the last day
of the previous month. If it was the month however, it would cause the date
to be set to December of the previous year. For example "2010-08-20" was
being interpreted as "2009-12-20", and "2010-10-08" was being interpreted as
"2009-09-30". This would have prevented some licenses from being able to
start because the upgrade terms were in effect prior to the Wrapper's release
date. Some trial licenses could also have stopped early because their lease
term end was earlier that it should may have been. For normal licenses, his
will have no effect on installations once they are up and running because
they do not use the lease term.
* Fix a problem on Windows when a service received several service control
codes in rapid succession. Since version 3.5.1, the Wrapper was only to
process a single control code in each cycle of its main loop. This was
resulting in messages like "Previous control code (4) was still in queue,
overwriting with (4)." in the logs. The Wrapper can now handle up to 25
control codes per 10ms cycle.
* Fix a problem where it was not possible to send passthrough arguments to the
JVM when installing or updating a Windows Service. Passthrough using the
"--" argument was added in 3.5.2.
* Add a new wrapper.pause_on_startup property which makes it possible to tell
the Wrapper to go directly into a paused state without ever launching a JVM.
* Fix a problem where the STOP command set in a command file was being ignored
if the Wrapper was currently in a paused state.
* Make it possible to specify DEFAULT for the configuration file encoding.
This will cause the file to be loaded using the default system encoding. We
added this by request, but recommend using a portable encoding like UTF-8 to
ensure that the configuration file will load correctly on all systems.
* Added a WRAPPER_LANG environment variable which makes it possible to reference
the current locale language code in the configuration file. One common use
is to do localization using inclues.
(e.g. #include ../conf/wrapper-%WRAPPER_LANG%.conf)
3.5.4
* Add optional support for custom public static methods in the
WrapperSimpleApp and WrapperStartStopApp helper classes. Feature Request
#2812276.
* Add a new special configuration file directive "#properties.debug" which
enables debug output about the properties as they are loaded by the
configuration file. This can be useful to tell if and why certain properties
are being overwritten. Feature Request #3042959.
* Fix a minor problem where the "#include.debug" configuration file directive
was sticky so it would be enabled when the configuration file was reloaded
even if the reloaded configuration file no longer had the directive set.
This was only an issue if the wrapper.restart.reload_configuration property
was set.
* Messages about missing included configuration files that were output when the
#include.debug" configuration file directive was active were being logged at
the ERROR level even though they were not problems.
* Fix a minor problem where the WRAPPER_JAVA_HOME environment variable was not
correctly being set to final when it was set internally by Wrapper. This
could lead to unexected results if the user overwrote it later in their
configuration file.
* Fix a problem on AIX and z/OS, when running the Wrapper without any
arguments. The Wrapper was attempting to use the default wrapper.conf file
but the check for the file was failing causing the Wrapper to continue even
though the file did not exist. This caused a confusing error message to be
displayed, but was otherwise harmless.
* Clean up some debug code associated with sleeping where log output was being
queued when it did not need to be.
* (Standard, Professional) Consolidate some redundant code associated with
waiting for interfaces on startup.
* (Professional) Fix a problem in the email feature of the Wrapper where a
subject of more than 27 bytes in length when encoded as UTF-8. This was
caused by a miscalculation in the Base64 conversion of the subject.
* (Professional) Fix a problem when the WrapperManager.exec method which takes
an array of command elements was called on Windows. The command elements
need to be combined into a single command line, but if any of the elements
contained spaces, the resulting command line was not being correctly quoted.
* Add a new wrapper.java.command.resolve property to control whether or not the
Wrapper tries to resolve any symbolic links in the Java command, specified
with the wrapper.java.command property. Historically, it has always done so,
but some jvm started applications like run-java-tool on Gentoo will fail if
it is run directly as they have a check to make sure it is launched via a
symbolic link.
* Fix a problem on Windows versions where a path to the Wrapper binary,
including the Wrapper binary itself, which was more than 100 characters would
cause a buffer overflow when installing the service. A second similar
problem would happen if the same path was more than 128 characters, whenever
the Wrapper was launched. These were both very old issues and only happened
on 32-bit versions of Windows XP and 2000. Microsoft documentation says that
the issue should also exist on the 64-bit versions, but we were unable to
reproduce it there. Newer versions of Windows are all fine.
3.5.3
* Fix a typo in the UNIX shell scripts that was causing "command not found"
errors to be shown when running the Community Edition.
* Add new wrapper.console.fatal_to_stderr, wrapper.console.error_to_stderr,
and wrapper.console.warn_to_stderr properties to control whether the output
at the FATAL, ERROR, and WARN log levels go to stdout or stderr. In the past
they all went to stdout. With this change, FATAL and ERROR log levels now
default to stderr output.
* Fix a problem where the shell script would produce unexpected results if the
Standard or Professional Edition shell scripts were used with the Community
Edition Wrapper. Fix was in Wrapper binary by changing the default ERROR and
FATAL log level console output to stderr rather than stdout.
* (Standard, Professional) Fix a problem where script error message output was
not being shown if the wrapper.conf file specified in the script did not
exist.
* Fix a problem where errors from failed forks on Windows were always being
flushed immediately rather than honoring the value of the
wrapper.console.flush property.
* Fix a problem on Windows 2000 systems where a new feature added in 3.5.2 was
preventing the Wrapper from running because the API used was too new.
* Change the font of the wrapperw dialog in order to have prettier output of
multibyte characters.
* Add a line feed after the first message when starting the Wrapper from the
UNIX script.
* Add a note in the debug output so the configured java temporary directory is
always logged to help with debugging.
* Add a workaround for a bug in both Sun and IBM JVMs which cause an invalid
exception to be thrown when a socket is already bound. It had been causing
the Wrapper to report: "Unexpected exception opening backend socket:
java.net.SocketException: Unrecognized Windows Sockets error: 0: JVM_Bind":
http://bugs.sun.com/view_bug.do?bug_id=6965962
* Add the encoding of the subjects in the event mails to be always UTF-8
Base-64 encoded.
* Add new wrapper.event..email.smtp.auth.type,
wrapper.event..email.smtp.auth.userid, and
wrapper.event..email.smtp.auth.password properties which make it possible
to do LOGIN and PLAIN connection authorizations. Currently SSL (STARTTLS)
connections to the mail are server are not yet supported.
* Fix a buffer overflow while loading the configuration file on Mac OSX
versions. Introduced in 3.5.0.
* Fix a several memory leaks on UNIX versions that were added in 3.5.0, as well
as a few others on all platforms, some from quite early versions.
* Fix some places where a resolved path of exactly MAX_PATH characters in
length could have resulted in a buffer overflow.
* (Standard, Professional) Fix a memory leak disposing language packs.
* Go through and increase the consistency of text strings.
* Fix a problem on HP-UX where the Wrapper was logging a warning that the
configured JVM was invalid if it was a PA-RISC 2.0 binary. Bug #3037317.
* Fix a problem where the WrapperManager was failing to trap and hide errors
initializing the MBean server on some JVMs that did not support it.
3.5.2
* Added new command line argument "--" . All arguments following will be
preceded and passed to the java application. The arguments are attached after
the arguments used in wrapper.app.parameter.
* Fixed a problem in the shell script which could lead to report failed starts
of a daemon incorrectly on the command line.
* Implemented some small logic in the wrapper script which tries to change the
permissions of the wrapper binary to executable if it wasn't set.
* The Demo Application had problems locating the right conf file on Unix
platforms and failed to launch the internal demonstration wrapper process.
* Improved the error message logged if the Windows version of the Wrapper exits
with an internal error. It now logs more information about the internal
state of the Wrapper as well as saving a mini dump file which can be sent to
support to make it easier to diagnose the cause of the problem.
* Fix a problem where the names and displayNames in WrapperWin32Service
instances were corrupted. List affected the WrapperManager.listServices()
and WrapperManager.sendServiceControlCode() methods. There was a similar
problem with the WrapperManger.getUser(), WrapperManager.getInteractiveUser()
and WrapperManager.setConsoleTitle() methods. Introduced in 3.5.0.
* Fix a problem on Windows where wildcards would sometimes fail to be resolved
or cause the Wrapper to crash. This affected the generation of classpaths
and logfile rolling. Introduced in 3.5.0.
* Fix a problem on UNIX platforms where some error messages related to a failed
fork to launch the JVM were not being logged correctly. Introduced in 3.5.0.
* Fix a problem where invalid characters in configuration files that did not
declare an encoding could cause the Wrapper to crash on startup. This could
be issue for users upgrading from versions prior to 3.5.0 as older versions
did not do any character set translations and would not have had a problem.
* Fix a problem in code to check whether a drive was a mapped network drive or
not was failing. This would sometimes lead to a false warning that the drive
could not be identified. Introduced in 3.5.0.
* Add a new ACCESS_VIOLATION command to the wrapper.commandfile property to
test how the Wrapper and external systems behave if the Wrapper were to
crash. Only enabled when the wrapper.commandfile.enable_tests property is
enabled.
3.5.1
* Start using a system function to determine whether or not a character in the
configuration file is a control character or not. This way it works on
non-ASCII platforms.
* (Standard, Professional) Fix a crash on Windows platforms caused by freeing
up unallocated memory while loading the Wrapper's configuration.
* Add debug output describing the system and current code pages on Windows
versions to help understand encoding and mojibake issues.
* Add a Japanese localized src/conf/wrapper.conf.in_ja template configuration
file to assist Japanese users.
* Fix an potential deadlock on UNIX platforms if the JVM exits while logging
is taking place and the wrapper.debug or undocumented wrapper.state_output
properties were set to TRUE.
* Fix a problem where a failed JVM invocation that happened immediately after
being launched would cause the Wrapper to immediately give up and shutdown.
This should not have been possible with normal JVM configurations, but was
turned up in testing.
* Fix a problem where some startup output of the tick timer debug output was
corrupted. This was only an issue if the wrapper.tick_output property was
set.
* (Standard, Professional) Rework the way text is localized so that mallocs
are all handled on initialization. 3.5.0 had problems with occassional
freezes and crashes caused by mallocs being made within signal handlers.
The problems were rare unless debug output was enabled.
* Greatly simplify signal handlers on all platforms so they now do as little
as possible, actions are now queued and then processed by the main thread.
* (Standard, Professional) Fix a problem where the hostname in the
wrapper.syslog.remote.host couldn't resolve a hostname (IP Address was
working).
* (Standard, Professional) Add debug output on Windows versions to help debug
localization and code page issues.
* (Standard, Professional) Fix a localization problem on Windows where the
Wrapper was using the system-wide language rather than that of the current
process. This was resulting in mojibake if the Wrapper was launched in a
new console if that new console did not support the required code page.
This was only an issue if the user had changed the active code page from the
default for their Windows desktop.
* Fix a problem on Windows platforms where the JVM child output was being
logged with an extra line feed in some cases.
* Fix a problem running the DemoApp from some Network shares on Windows.
* Add a new WrapperManager.isWindows() and WrapperManager.isMacOSX() methods to
make it easy to write such conditional code as both platforms can require non
standard code.
* (Standard, Professional) Make the GetHostId.bat file more robust so it can be
executed using a relative reference from the command line. It also now
supports Delta-pack style Wrapper binary naming and falling back to use which
binaries are available.
* Change the timing of when the wrapper.working.dir is set so that any error
messages generated while loading the configuration will be logged to the
correct log file. It is also needed for Standard and Professional Editions
to ensure that the language pack is loaded from the correct location so that
all such messages will be in the correct locale.
* Fix a problem on UNIX platforms where the status command was failing with an
error due to the localization feature added in 3.5.0.
3.5.0
* (Standard) Added the ability to detect and react to thread dead locks in
the JVM. Requires at Java 1.5. Added wrapper.check.deadlock,
wrapper.check.deadlock.interval, wrapper.check.deadlock.action, and
wrapper.check.deadlock.output properties to configure the detection.
* (Professional) Add a new jvm_deadlock event which is fired in response to
a thread deadlock being detected within the JVM.
* Fix a problem where the intervals like wrapper.ping.interval were all
rounding down causing them to function at a rate one second shorter than
configured.
* Fix a minor memory leak calling WrapperManager.exec.
* Add a new wrapper.filter.message. property which can be used to control
the message which is logged when a wrapper.filter.trigger. is matched.
* Rework the way actions are fired for the wrapper.filter..action and
wrapper.timer..action properties so there is no longer any duplicate
code.
* Modify the way the wrapper.filter..action and wrapper.timer..action
properties work so it is now possible to specify a list of actions which will
happen in the order specified. This makes it possible to do a thread dump
and then restart in response to an error.
* Add the DEBUG action to the wrapper.filter..action property for
consistency.
* (Professional) Implement the ability to fire user defined events as actions
of the wrapper.filter..action, wrapper.timer..action, and
wrapper.check.deadlock.action properties.
* Fix a problem in the WrapperProcess.destroy() function, when a child process
couldn't have been forcibly killed.
* Add GetHosdID.bat file for Windows platforms. This file will open a dialog
displaying the HostId of the machine.
* Fix a problem in the shell script which, on a rc based OS, could lead to
problems starting the Wrapper when the APP_NAME in the script contained
capital letters.
* (Standard, Professional) Added a set of wrapper.share..* properties which
makes it possible to configure the Wrapper to map specific network resources
before launching the JVM on Windows.
* Corrected the way the Wrapper is installing itself as a Windows service when
the binary and/or conf file are located on a Mapped Drive.
* Add new wrapper.pausable and wrapper.pausable.stop_jvm properties to control
whether the JVM can be paused or not, and deprecate the use of the Windows
specific wrapper.ntservice.pausable and wrapper.ntservice.pausable.stop_jvm
properties.
* Modified the wrapper.commandfile property so PAUSE and RESUME commands are
now supported on all platforms at any time.
* Modified the wrapper.filter.action. property so PAUSE, RESUME, and DEBUG
actions are now supported.
* (Professional) Modified the wrapper.timer..action property so PAUSE and
RESUME actions are now supported.
* (Professional) Modified the wrapper.event..command.block.action
property so PAUSE and RESUME actions are now supported.
* Added new WrapperServicePauseEvent and WrapperServiceResumeEvent classes to
make it possible to notify an application that it has been paused or resumed.
To date, this was only possible when the Windows service was paused or
resumed
* (Professional) Add new "wrapper_pause" and "wrapper_resume" event types that
are fired whenever the Wrapper is paused or resumed.
* Enhance the command line parsing for the WrapperManager.exec() command. The
single commandLine version of the exec call will handle quotes more
sophisticated.
* Modified the wrapper.syslog.ident property so its value is now silently
trimmed to 32 characters in length. This is needed to avoid problems with
syslog servers. (See RFC 3164 section 4.1.3)
* (Standard, Professional) Add new wrapper.syslog.remote.host,
wrapper.syslog.remote.port, and wrapper.syslog.local.host properties which
can be used to redirect all syslog (UNIX) or Event Log (Windows) output to
a remote syslog server.
* Add support for the wrapper.syslog.facility property on Windows so remote
syslog entries can be sent from Windows versions of the Wrapper.
* Add debug output from the WrapperManager class which shows information about
the current wrapper.jar, including its size, location, and MD5 hash.
* Add a check for wrapper.java.classpath. entries containing quotes. The
quotes are now stripped and a debug warning logged.
* (Standard, Professional) Increase the size of the wrapperw.exe error dialog
so it is a little easier to read. Also changed the font for the same reason.
* (Standard, Professional) Modify the title of the wrapperw.exe error dialog
so it now includes the value of the wrapper.displayname property.
* Add a new check for the writability of the configured Java temporary
directory. When running on Vista, it will not be writable and can lead to
errors.
* Added new wrapper.java.tmpdir.required and wrapper.java.tmpdir.warn_silently
properties to control whether the temporary directory is required.
* Add a note in Wrapper conf template showing users how to configure a specific
Java version to use.
* Add a new CLOSE_SOCKET command to the wrapper.commandfile property and added
a new wrapper.commandfile.enable_tests property to control whether it can be
used.
* Fix a debug warning while shutting down caused by one thread closing the
backend socket when another expected it to be open.
* If the backend socket between the JVM and Wrapper is somehow closed, make the
JVM respond promptly by restarting the JVM immediately to resync with the
Wrapper. Added log information to make it clear when this happens.
* Add a new wrapper.use_tick_mutex property to control whether or not the
internal tick timer is protected by a mutex. (Experimental)
* (Standard, Professional) Add support for zLinux 32 and 64-bit on s390 and
s390x systems.
* Change the internal encoding of the wrapper from native characters to
UNICODE. This will allow the wrapper to handle correctly any characters in
its configuration file and internally.
* (Standard, Professional) Implement a new WrapperResources class which makes
it possible for user applications to localize their applications using the
same methods common to native applications. The Wrapper uses this internally
to provide localized versions of the Wrapper.
* Remove the old org.tanukisoftware.wrapper.resources package as it is no
longer being used.
* (Standard, Professional) Add Japanese language pack to localize the Wrapper
to Japanese.
* Fix a problem in the WrapperManager class where unexpected exceptions thrown
in the main socket loop were being thrown away without being logged.
* Make the Wrapper more robust against failures removing the Wrapper's shutdown
hook on shutdown. It had been causing the clean shutdown of the JVM to fail
as an unexpected exit.
* Fixed a problem in the wrapper customize code where customized multi layer
icons may get scaled incorrectly by Windows. Bug #3015848
* Modify the wrapper.on_exit. property so it is now possible to PAUSE the
Wrapper when a JVM exits. This delays the restart of the JVM until the
Wrapper is resumed.
* Add a new log format, 'U', which logs the approximate time in seconds since
the Wrapper was launched. It is based on the internal tick timer and will
be a few percent lower than the actual number of seconds that have elapsed.
Added to the wrapper.console.format, wrapper.logfile.format, and
wrapper.logdialog.format properties.
* Fix a problem where deleting the configured anchor file was not recognized
if the JVM was not running at the time. The Wrapper was not noticing that
it was missing until the next JVM was launched.
* (Standard, Professional) Add a new NOTICE log level which is used to log
license related message. These will only show up trial license log output.
* (Standard, Professional) Add a new default 15 minute trial license which
can be used out of the box on any machine without the need to register and
obtain a trial license or purchase a license.
* Add a new wrapper.environment.dump property which will dump all of the
environment variables to the log, along with where the variables originated.
* Force the Wrapper to flush all logfile output for each line until the
configuration file has been loaded. There is normally no output up to this
point anyway, but this ensures that any errors are logged in a consistent
location.
* Move the registration of the main thread with the logging system up a bit
to make it possible to perform low level debug logging earlier.
* Add a set of checks to display an error and prevent the Wrapper from starting
if the batch or shell scripts being used are based on the TestWrapper demo
application. It is important that the user start with the default template
files in the distribution src/bin and src/conf directories to make sure the
integration goes smoothly.
3.4.1
* Fix a problem where the wrapper.app.parameter.1 property was always being
set to an empty string when launched from launchd on Mac OSX. It worked
correctly with the testwrapper application, but would fail for most user
applications.
* (Professional) Fix a potential synchronization problem in the log output
of the tick timer, event command and event email code. This had been in
the code since 3.3.0 without any reports of problems.
* Improve the error message displayed when the configured wrapper.java.command
can not be found on the path.
* Log the name of the signal in the logs when a SIGSEGV is detected from the
JVM. It had been logged as Unknown.
* Add some comments to the wrapper.conf.in template to help users get started
with a new license key file.
* Add some default properties to the wrapper.conf.in template file to make
it easier to get up and running with out of memory checks, as well as
sending out alert emails.
* Add a small debug message when running wrapperw.exe so it is clear which
wrapper binary is being used.
* Fix a problem where the wrapper.logfile.maxfiles was not being applied on
startup when the current log file did not yet exist. This was true for any
wrapper.logfile value which contained a unique value like a PID.
* (Professional) Fix a problem in the WrapperProcess.destroy() function, where
the function was failing to forcibly kill the child process.
* (Standard, Professional) Add a new GetHostID.bat file for Windows platforms.
This file will open a dialog displaying the HostId of the machine to help
new users get up and running.
* Add a new WrapperManager.appearOrphan() method which can be used to test
how the WrapperManager shuts down the JVM in the event that the Wrapper
process ever crashes or freezes. This was not due to any particular problem
and was added to fill out our test coverage.
* (Professional) Fix a problem where event commands were being left in a
defunct state after execution on UNIX platforms.
* Fix a potential problem on 64-bit versions where the internal tick timer was
not rolling over in the same way as the 32-bit versions. This has been in all
previous versions but is not known to have caused any problems. It was fixed
for consistency.
* Modify the WrapperManager class so it will now request a JVM hard exit only
after 4-times the ping timeout, in seconds, since the last contact with the
JVM. This had been 90 seconds more than the ping timeout, which was not
always long enough when the wrapper.ping.timeout was very large.
* Shift the initial start point of the tick counter so it will roll over 50
seconds after startup. This shouldn't be noticeable to the user, but makes
sure that this roll over is much better tested as it always happens the first
time on startup.
* Add a new wrapper.java.classpath.use_environment property which makes it
possible to set the classpath using the CLASSPATH environment variable rather
than including it on the Java command line.
* Fix a problem where requests to shutdown the Wrapper when in the state where
it was just about to launch a JVM would being ignored. This was fixed in all
editions, but was only an issue in the Professional Edition when the
wrapper.event.jvm_prelaunch.command.on_exit.=SHUTDOWN property was being
used with the wrapper.event.jvm_prelaunch.command.block=TRUE property and the
command exited with a code that triggered the SHUTDOWN.
* (Professional) Add a new wrapper.event..command.block.action
property to control how the Wrapper behaves when a command does not complete
execution within the configured timeout. Accepted values are CONTINUE, KILL,
KILL_SHUTDOWN and KILL_RESTART. Default value is CONTINUE.
* (Professional) Made it possible to use the "default" event type with the
wrapper.event..command.loglevel,
wrapper.event..command.block,
wrapper.event..command.block.timeout,
wrapper.event..command.on_exit., and
wrapper.event..command.on_exit.default properties.
* Fixed a single byte buffer overflow which takes place just before the JVM is
launched on Windows platforms. This was introduced in 3.4.0.
* Add a message pointing the user to the Wrapper's log file when the service
fails to start after it has been launched.
* Update the debug message displayed when attempting to open the backend socket
if the port is unavailable so it doesn't seem like a problem. It will retry
with another port.
* Work around an issue on some Solaris problems where the shell script would fail
if /usr/ucb/ps wasn't installed.
* Fix a problem on UNIX versions where the Wrapper would fail to resolve the
correct location of java if it was located using the system PATH, and that PATH
element pointed to a binary via a relative symbolic link. This was introduced
in 3.4.0.
3.4.0
* Increased the minimum supported Java version from 1.2 to 1.4.
* Removed the reflection code used to manage the Wrapper's shutdown hook.
The Runtime methods are now called normally.
* Add a note in the TestWrapper shell script to make it clear that the user
should always use the scripts in the WRAPPER_HOME/src/bin/ directory when
generating scripts for their own applications. This became more of an
issue because of changes to the TestWrapper script starting with 3.3.8.
Bug #2902843.
* (Professional) Added new WrapperManager.exec methods and a new
WrapperProcess class to allow the launching and management of child
processes through the Wrapper rather than using the standard Runtime
class. This makes it possible to clean up child processes when the
JVM crashes or is restarted, as well as solves severe memory issues with
the way processes are forked on some UNIX platforms.
* (Professional) Added a new wrapper.child.status.loglevel property to make
it easier to debug the status of child processes.
* (Professional) Added a new wrapper.child.count.interval property to control
the interval at which the number of waiting child processes is logged after
a JVM is shutdown.
* (Professional) Added a new wrapper.jvm_cleanup.timeout property to control
the amount of time that managed child processes still running after the JVM
has exited are given to shutdown before being forcibly killed.
* Fix a problem with WrapperManager.getUser() and getInteractiveUser() methods
which was preventing us from using the latest compiler on 32-bit Windows.
(The compiler used to build 32-bit Windows versions was rolled back to the
version used through the 3.3.5 release in 3.3.9 to work around the problem
that was causing these methods to always return null.) The change in this
version should not affect how the Wrapper functions.
* The old compiler used in 3.3.9 for Windows 32-bit builds was causing a false
hit on Symantec security software. The new compiler causes the Wrapper to
once again pass without any warnings.
* Added a warning while starting up the JVM which will be displayed if the
Java command in wrapper.java.command does not point to a valid java binary
file.
* [Changed the scripts and batch files to try to load the wrapper executable
according to the system, i.e. on 64-bit systems the 64bit binary of the
wrapper is attempted to be executed first and after this fails the 32 bit
gets attempted to be loaded. This behaviour is primaly useful with the
delta-pack of the wrapper.]
* Add some debug output logging the current timezone to assist supporting
time related problems.
* (Standard, Professional) Added a new wrapper.license.debug property which
will log information about the license key(s) being tested on startup.
* (Standard, Professional) Fix a problem where license validation was
failing at certain times of the day for servers with timezones east of
Japan. Development license keys which have their update times obfuscated
were not affected. This was a problem introduced in 3.3.7.
* Fixed a bug in the wrapper shell script which occured when running the script
on a Solaris within a non singlebyte locale. Bug #2910327
* Fixed a potential bug in the wrapper script where requesting a Thread Dump,
the shell is sending the wrapper console to the background and returning
with a prompt.
* Fix a problem where Java log output would sometimes get extra line feeds
when under heavy load.
* Fix a problem which was leading to a resource not found error when trying
to start a service, if it was installed on a Mapped Network Drive under
Windows.
* Added some advice messages recommending the use of UNC paths if a resource
located on a Mapped Network Drive is used in the configuration file on
Windows versions.
* (Standard, Professional) Fix a bug in the wrapper binary customization,
which occured when the source binary file was set to read only.
* Fixed a null string problem in the error message if a classpath value
wasn't found.
* (Professional) Added the option to include a logfile into the wrapper's
EmailNotification mails via wrapper.event.default.attach_log=TRUE
* Improve the message displayed when a user calls
WrapperManager.requestThreadDump() in JVM which does not have console
window on Windows. This should never be an issue when run with the Wrapper,
but can happen if running standalone without the wrapper binary.
* Update the Windows batch scripts so they now take AMD64 and IA64
architectures into account when deciding which version of the Wrapper to
run when using the delta pack.
* Update the UNIX shell script so it now does a much better job of resolving
the ideal platform bits to run the correct version of the Wrapper when using
the delta pack. Thanks to Leo Leung for the patch.
* Add install and remove commands to the UNIX shell script so it is now much
easier to install and remove the Wrapper on many UNIX plattforms to start
and stop on system startup and shutdown. Thanks to Leo Leung for the patch.
* Update the Windows batch scripts so it is now easier to change the location
of the Wrapper configuration file or rename the Wrapper binary when using
the scripts.
* Added a new QueryApp-NT.bat.in template script which can be used to query
the current running status of the service on Windows.
* (Standard, Professional) Add a new "-u" or "--update" command to the Wrapper
which allows you to effectively reinstall the Wrapper as a service without
having to provide the account credentials if the service is running as a
specific user. This is very useful for installers upgrading an application
to a new version.
* Add a new "update" command to the Windows AppCommand.bat.in batch script.
* Go through and clean up the messages displayed when controlling the Wrapper
as a service so the messages are consistent and more meaningful to the user.
* Add wrapper.wait_for_hostid and wrapper.max_hostid_timeout property.
This properties set if and how long the wrapper shall wait when starting up
until the hostid is available. This is important to make sure that server
licenses are validated correctly on UNIX platforms as the OS is booting up.
* (Professional) Fix a problem where environment variables referenced in
property values were not being expanded correctly the first time they were
referenced if the property's value was a default value. The underlying fix
was in all editions, but this was only causing a problem in the Professional
Edition where the WRAPPER_HOSTNAME variable was not being expanded in the
subject and body of emails sent out for the "wrapper_start" event if the
defaults were used.
* (Professional) Fix a problem where backslashes in the body of emails,
configured with the wrapper.event..email.body property, were
not being handled correctly when displaying things like paths from
environment variable references.
* Fix a problem on UNIX platforms where the Wrapper was displaying an error
about not being able to locate the configuration file when the Wrapper was
run without any arguments.
* (Standard, Professional) Improve the message shown when a License Key is not
found.
* Add a new message to the Community Edition when the user requests a HostId.
* Add WAIT_FOR_STARTED_STATUS and WAIT_FOR_STARTED_TIMEOUT to the script. This
lets the script wait (up to timeout sec.) when starting a daemonized process
until the process has been started.
Thanks to Dobes V. Feature Requests #2917391.
* Improve the error message displayed when the user tries to run the Wrapper
with the internal -s or --service commands.
* Fix a problem where the WrapperSystemPropertyUtil.getBooleanValue() method
was not correctly returning the specified default value when the looked up
property was missing. Also added a new getStringValue() method.
* Improve the error message displayed when the user tries to install and remove
the wrapper as Service on Windows Versions after Windows Vista.
* Add an advice message when MacOSX applications launched with launchd
encounter a "Returning nil _server" error when displaying a GUI.
3.3.9
* Modify the way JNI functions are called from within the native library so
they work correctly on platforms which are not ASCII based.
* (Professional) Add support for IBM z/OS 390 servers. This is still an alpha
release and will be made available on request.
* Improve the message displayed when a server license key is used on a
different server.
* Add a minimum max file size of 1024 bytes to the wrapper.logfile.maxsize
property to avoid the log file rotating too often if the user enters a
very small value.
* Add a message that shows up in the console when the Wrapper fails to write
to the configured log file. As with previous versions, it will then fall
back to writing to wrapper.log in the current working directory.
* On UNIX platforms, automatically set the wrapper.disable_console_input
property when wrapper.daemonize is set.
* Fix a problem introduced in 3.3.8 where relative configuration file includes
were failing to resolve correctly when the wrapper.working.dir and
wrapper.daemonize properties were used together. The wrapper.daemonize
property causes the configuration to be loaded twice on startup and the
working directly was not being reset correctly before it was loaded the
second time.
* Fix a problem introduced in 3.3.8 where wildcard selection of files on
Windows failed in some cases.
* Fix a problem introduced in 3.3.8 where setting the wrapper.logfile.maxfiles
property to 0 was causing all log files to be deleted rather than none when
the ROLLNUM file pattern was used.
* Revert the way rolled log files are deleted when using the ROLLNUM file
pattern to the functionality used in versions 3.3.7 and earlier. Files such
as wrapper.log.bak or other files manually created with the same log file
base name were also being deleted with 3.3.8.
* (Standard, Professional) Fix a problem where the close window button in the
title of the WrapperW log dialog was not correctly cancelling the dialog.
* (Standard, Professional) Fix a problem where the WrapperW log dialog would
sometimes fail to show itself on top of other windows if the splashscreen
had been displayed on startup.
* Fix a problem on 32-bit Windows versions where starting with he Wrapper,
the WrapperManager.getUser() and getInteractiveUser() methods were always
returning null. This problem was introduced in version 3.3.6.
* (Professional) Fix a buffer overflow when sending alert emails to multiple
addresses. This would sometimes cause crashes in versions 3.3.7 and 3.3.8
when sending alert emails to even a single recipient. Because of the nature
of the overflow, in most cases did not cause any problems.
3.3.8
* Add the new start type DELAY_START for NT Services, which startes the service
after other auto-start services are started plus a short delay.
* Fix a problem where the Wrapper's PID file was not being set to the correct
PID when the wrapper was launched daemonized. With the shell scripts that
ship with the Wrapper, this means that it would not be possible to stop the
Wrapper using the script because the expected PID did not exist. This was
a problem introduced in 3.3.7.
* Changed the timing for the wrapper's splashscreen when the splash screen
mode was set to JVM_STARTING. Now the splashscreen will disappear when the
JVM has been initialized.
* Fix a problem where the splashscreen was being shown when starting a service
or performing other command line operations.
* Remove some extra debug output on startup for Mac versions.
* Fix a crash in the Community Edition on PPC platforms of the Mac OSX version.
This crash has been reproduced in all versions starting with 3.3.1. The OSX
distribution is a universal binary but does not appear to result in a crash
on x86 servers. Standard and Professional Editions were not affected.
* Fix a problem on Windows versions where problems accessing the registry were
not reporting the correct error message. This did not cause any problems in
and of itself, but it made it difficult to track the down the cause.
* When wildcards are used in the classpath elements, the list of matching jar
files included in the classpath are now sorted to ensure that their order
is consistent across installations. Normally it would not matter, but if
certain classes or resources are redefined in multiple jars this will ensure
that the application now always works the same.
* Fix a problem where wrapper.logfile.maxfiles was being ignored when
wrapper.logfile.rollmode=JVM was set.
* Changed the way the wrapper.logfile.maxfiles property works with the ROLLNUM
token. Now when the log files are rolled, all files greater than maxfiles
count will be deleted. Previously, the Wrapper would roll within the maxfiles
count and ignore extra files if they existed. This would cause extra files to
be left around if the maxfiles property value was decreased.
* Add new wrapper.logfile.purge.pattern and wrapper.logfile.purge.sort
properties which make it possible to limit the number of log files in some
advanced cases. Be sure to read the documentation before playing with them.
* Fix a potential crash when referencing non-existent environment variables
in the value of wrapper.logfile.
* Modify the way all properties used to define file names behave so that
undefined environment variable references will now have their '%' characters
replaced by '_'. This is to avoid problems caused by file names containing
'%' characters on some platforms.
* Fix a problem introduced in 3.3.6 where the windows shown by the JVM or its
child processes could not be displayed when running in iteractive mode.
* Rework the TestWrapper application a bit so it can now be run in headless
mode for testing.
* Fix a problem on some UNIX platforms where the shell script was showing an
extra '-n' when run with the "start" command.
* Fix a problem for FreeBSD which could cause the wrapper being unable to stop
the wrapper daemon if the ps command buffer size (kern.ps_arg_cache_limit)
was too small to contain the wrapper command line.
3.3.7
* (Professional and Standard) Added the ability to customize the wrapper.exe
and wrapperw.exe binaries on Windows with a user specified icon and splash
screen.
* (Professional and Standard) Added a new wrapper.splashscreen.mode property
to control how long the splashscreen is visible.
* Fix a problem on SELinux where a strict security policy could lead the
Wrapper fail to load the libwrapper library. Thanks to Jean for the hint.
* Fixed a problem in the obfuscated license date, which caused a license to
be reported as invalid if run in a timezone west of Japan. This feature
was implemented in 3.3.6, but disabled on the site until the release of
version 3.3.7. Thanks to Leo for the hint.
* Added a new WRAPPER_PID environment variable. Feature Request #2870136.
* Added a new WrapperManager.getWrapperLogFile() method and
WrapperLogFileChangedEvent class that can be used to receive notifications
of changes to the Wrapper log file currently in use.
Feature Request #2870133.
* (Profesional) Improved the wrapper.event..email.to property
so it now supports the ability to specify multiple recipients.
3.3.6
* Introduce the wrapper.timezone property. This property allows to set the
timezone in which the wrapper will be executed. This property is available
in the standard and the professional Edition of the Java Service Wrapper.
* Fix a potential problem on Windows platforms where a failure to register the
control handler was not being logged. If this happened, user logoffs would
not be trapped correctly but no other problems would have occurred.
* Fixed a problem in the shell script on Solaris platforms where a deep
directory structure would cause the script to incorrectly report that the
Wrapper was not running. That could lead to multiple zombie copies of the
Wrapper and its application running in memory.
Bug #1664303.
* Fixed a problem in the shell script on HP-UX platforms where a deep
directory structure would cause the script to incorrectly report that the
Wrapper was not running. That could lead to multiple zombie copies of the
Wrapper and its application running in memory.
Bug #2812207.
* Improve the error message displayed when there are problems initializing the
main class specified for the WrapperSimpleApp, WrapperStartStopApp, or
WrapperJarApp helper classes.
* (Professional) Add new wrapper.event..loglevel and
wrapper.event..message properties which can be used to output
a customizable message like "Event: " to the logs at an arbitrary
log level.
* Add debug output in the Windows version to log the full path of the native
library.
* Add a new wrapper.java.detect_debug_jvm property which will control whether
or not the Wrapper disabled timeouts when java's debugger is in use. The
Wrapper has automatically disabled timeouts in this case since version 3.2.1.
Thanks to Ruslan Gainutdinov for the patch.
* Fix a buffer overflow problem for values of wrapper.ntservice.name.
* Fix a problem with where the wrapper.syslog.ident property was not working
as documented. It had been necessary to use wrapper.ntservice.name in its
place.
* Add a new wrapper.ignore_sequence_gaps property which makes it possible to
have non sequential numbered property values. This affects the
wrapper.app.parameter., wrapper.event..command.argv.,
wrapper.filter.trigger., wrapper.java.additional.,
wrapper.java.classpath., wrapper.java.library.path.,
wrapper.ntservice.dependency., and wrapper.timer..interval,
properties. The default value maintains past functionality.
Feature Request #1930298.
* (Professional) Fix a problem where the Event Handler Variables
were not being set correctly in the values of the
wrapper.event..command.argv. properties.
* (Professional) Fix a potential access violation if memory allocations fail
while sending event mails or executing event commands.
* Add a new WRAPPER_HOSTNAME default environment variable as an alias of the
existing WRAPPER_HOST_NAME variable.
* (Professional) Deprecate the use of the wrapper.event..set_environment
property. It will remain in the product for compatibility but its use is
discouraged as it does not always work correctly when the configuration
file is reloaded. See the property's documentation for more details.
* Add a new DUMP action to the wrapper.filter.action. property to make it
possible to invoke a thread dump in response to a specific string in the
JVM's console output.
* Fix a problem where the WrapperManager.stopAndReturn method was dead locking
if called when the JVM was being run in standalone mode without the Wrapper.
Bug #2711872.
* (Standard, Professional) Modify the way the licensing times work so the
Wrapper compares the License Upgrade Term to an official release date
rather than the build date. This makes it possible to release additional
platforms at a later date while keeping the use of a license consistent.
* (Standard, Professional) Make it possible to obfuscate the upgrade term in
License Key files for development licenses so it is not visible to an end
user what the development license holder's upgrade term is. This feature
is accessed from the License Management Page when downloading a new or
existing License Key file.
3.3.5
* Fix a problem on some UNIX platforms introduced in 3.3.4 where the Wrapper
would crash on startup if the configured JVM could not be found.
* Fix a problem introduced in 3.3.2 where the Wrapper could crash if the
system host name was longer than 27 characters in length.
* Fix a potential problem with the way thread ids were being compared on UNIX
systems.
* Add a new wrapper.java.additional.auto_bits property which will automatically
add the -d32 or -d64 arguments to the JVM for platforms whose JVMs typically
expect the argument.
* (Professional) Fix a problem with the Date field of outgoing event emails.
3.3.4
* (Standard, Professional) Update the development license to version 1.1
so that a new copyright notice file can be shipped with user applications
rather than the full license text.
* The Community Edition may be licensed under either the GPL2 based Community
License, or the Development License. The source for the Standard and
Professional Editions of the Wrapper are proprietary.
http://wrapper.tanukisoftware.org/doc/english/licenseOverview.html
* Fix a problem introduced in 3.3.2 where querying a the status of a Windows
service with the -q or -qs commands resulted in an access violation. The
running status of the service was reported correctly but additional
configuration information was failing. Bug #2644515.
* Add a new wrapper.disable_restarts.automatic property to disable only
restarts caused by JVM timeouts, crashes, etc. Manual or configured
restarts will still be allowed.
* Switch to using make for HPUX IA 32/64 builds.
* Add Advice comments when the Wrapper fails to launch the JVM process.
* Fix a problem on UNIX platforms where log entries made by the forked Wrapper
process would result in two blocks of log entries in the log file because
the parent Wrapper process would think they were console output from the JVM
process.
* Add a set of new wrapper environment variables that can be referenced in the
wrapper.conf file to generate random numbers, or timestamps for use in
generating unique file names, etc. See the Default Environment Variable
definitions section for more details.
* (Standard, Professional) Fix a problem with Development licenses being
able to authorize applications using Integration Method #4 which was
added in version 3.3.3.
* Add the number of bits of the current Wrapper to the startup banner to aid
in support requests.
* (Standard, Professional) Fix a crash problem on HPUX versions which would
reliably happen on some machines at startup.
3.3.3
* Modify the wrapper.ignore_signals property so it now takes the values
WRAPPER, JAVA, and BOTH, in addition to TRUE and FALSE.
* Modify the WrapperManager so it is now careful never to poll the native
library once the JVM is flagged as being ready to shutdown. This is to
make sure that the JVM never exits in the middle of a call as that could
lead to the JVM crashing.
* Add a pair of methods to allow threads to request and release locks which
will prevent the Wrapper from letting the JVM exit while certain operations
are in progress. See WrapperManager.requestShutdownLock() and
WrapperManager.releaseShutdownLock().
* Fix a problem where interactive services would sometimes leave a console
window visible when after starting up. The Wrapper is now more resilient
about closing the window even if it fails to do so initially.
* Add a new integration method (#4), which makes it easy to configure the
Wrapper to execute an executable jar file.
* Fix a problem where the random generator was not being seeded correctly
before naming the Wrapper's console window when running as a Windows
service. This was leading to problems identifying the wrapper's console
when more than one service was running on the same machine.
3.3.2
* Add a file information record to the wrapper.exe and wrapperw.exe binaries
so the Version tab will be displayed correctly in the Properties dialog of
the file.
* (Standard, Professional) Fix a problem with the wrapperw.exe binary where
the log dialog was not being displayed correctly when the Wrapper was
launched with the "-?", "-v", or "-h" arguments.
* (Standard, Professional) Fix a problem with the wrapperw.exe binary where
a message was being displayed in the dialog with the location of the full
log file even if there had not been any entries written to the log.
* (Professional) Improve the debug output produced when sending event emails
when the wrapper.event..email.debug property enabled.
* (Professional) Add wrapper.event..email.send.timeout and
wrapper.event..email.receive.timeout properties to avoid the
wrapper hanging waiting for a response from a remote mail server.
Bug #2064885.
* (Professional) Fix a problem where the Wrapper would get stuck and fail to
send emails with some mail servers. Problems was being caused by incorrect
linefeeds in the body of the email.
* Add a warning if the leading '#' is missing from an '#include' in the
configuration file to assist users with include file problems.
* Added a new wrapper.ntservice.generate_console property which will cause
the Wrapper to always generate a console when running as a service and
then hide it immediately. This will cause a slight flicker but is needed
to support thread dumps. Bug #2060181.
* Fix a problem in the Windows version where the console window would
sometimes be left visible when running as an interactive service even when
it was configured to be hidden.
* Add support for PowerEvents so Windows services can respond to suspend
and resume events.
* Fix a problem where the wrapper.key system property passed to the JVM was
being generated incorrectly randomly, 1 in 2048 times the JVM was launched.
This would result in the JVM failing to start and the Wrapper shutting down.
* Add a new wrapper.disable_console_input to disable to feature which allows
the Wrapper to pass console input on to the Java process.
* Fix a buffer overflow problem in the logging code which would happen once on
startup. This was benign on most platforms but was causing intermittent
crashes in the 32-bit AIX version.
* Modify the way configuration properties are parsed so that their names are
no longer case sensitive.
* Modify the WrapperServiceException so that a new getErrorCode method can be
used to obtain the integer error code which caused the exception.
Feature Request #2188280.
* (Standard, Professional) Fix a problem where on some Windows machines the
Wrapper would return a random hostId that changed each time the system was
rebooted.
* (Standard, Professional) Make it possible to define License Keys so that
their property names are encoded using either the host name or hostId. This
makes it possible to define multiple keys within the same configuration file,
visible on the same host. This was necessary to support some load balanced
network adapters where the visible hostId changes depending on the active
physical network adapter.
* Rework the Java side state engine so it is now possible for the Java side of
the Wrapper to respond to stop events while the WrapperListener.start method
is still in progress.
* Add a new wrapper.listener.force_stop property which allows control over
whether the WrapperListener.stop method is called on shutdown even if the
WrapperListener.start method has not yet completed.
* Fix a problem on Windows where the ability to start and stop the Wrapper as
a service using the Wrapper itself was requiring the Administrator permission
when a lower permission should have been possible. The Wrapper should now
allow service control to do whatever is possible from the Services control
panel.
* Fix a memory corruption error if the value of wrapper.java.maxmemory was more
than 4 digits in length. wrapper.java.initmemory did not have any problems.
* (Professional) Add a new wrapper.event..email.client.host
property which makes it possible to configure the host name sent in EHLO and
HELO commands to the SMTP server.
* Add a new default environment variable, WRAPPER_HOST_NAME, which stores the
name of the machine where the Wrapper is running.
3.3.1
* Add debug output showing the current os name and architecture to aid in
debugging problems.
* (Standard, Professional) Improve the message displayed when a license key
is found but is deemed to be invalid.
* Modify the template wrapper.conf file to help users debug include file
problems.
* Disable the console title feature on all UNIX platforms other than LINUX
because the console title does not get reset correctly when the Wrapper
process terminates.
* Add support for HP-UX IA64 CPUs.
* Update the license banner in source files so it is clearer that the user
is restricted by the license they agreed to.
* Modify the Community edition so it will now display a Licensed to banner
on startup if shipped with a Development License. This is required to
enable the distribution of the Community Edition under the Development
License.
* (Professional) Fix a problem where the UNIX versions of the Professional
Edition would sometimes deadlock on startup when run as a daemon process.
Bug #1989355.
* (Professional) Added two new events; jvm_failed_invocation and
jvm_max_failed_invocations. Feature Request #1994718.
* Fix a problem where the Windows service exit code was not being set
correctly when the JVM exited with a non-zero exit code. The problem
could be seen by running "sc query {service}" from the command line.
Bug #1859061.
* Added support for the Windows Itanium 64-bit platform.
* Added support for the HP-UX Itanium 32 and 64-bit platforms.
* Added support for the MAC OSX 64-bit platform.
* (Standard, Professional) Fix a problem on Windows versions where servers
which reported a large number of possible host ids could cause a buffer
overflow on startup. This crash was possible when using either
Development or Server licenses. Removed duplicate host ids from the list
of possible ids.
* Add a new "condrestart" command to the shell script which will restart
the Wrapper only if it is already running. Feature Request #1928045.
* Fix a problem where the 64-bit Solaris x86 version was unable to load its
JNI library. Bug #1992039.
* Fix a problem on Windows versions where a frozen JVM process was not always
being killed. This could result in the zombie JVM processes being left
around that consumed memory and other resources.
* Add a new wrapper.ignore_console_logouts property which allows the Wrapper
and JVM to survive logouts when launched as a console application from
another service.
* (Standard, Professional) Add a wrapperw.exe binary in Windows implementations
which makes it possible to run the Wrapper without a console. A console still
flickers for an instant when the Wrapper starts. This is the same issue that
has existed when running as an interactive service and is required to make
thread dumping possible.
* (Standard, Professional) Add new wrapper.logdialog.enable,
wrapper.logdialog.format, wrapper.logdialog.lines, and
wrapper.logdialog.loglevel properties used to configure the display of a Log
dialog when the wrapperw.exe binary exits in an error state.
* Fix a problem where the Wrapper was attempting to reopen its backend port
even when the JVM was down. This was only a problem when the defined port
range was limited to a single port with the wrapper.port.min and
wrapper.port.max properties. In such a case one or more warning messages
were being displayed because the port is locked for a few moments after
being closed.
* (Standard, Professional) The wrapper.initmemory.percent and
wrapper.maxmemory.percent properties were not correctly being calculated
relative to a maximum of 2048MB for 32-bit versions of the Wrapper.
Bug #2053167.
3.3.0
* Add a new wrapper.ping.interval.logged property which makes it possible to
reduce the debug output caused by ping transactions between the Wrapper and
JVM.
* Fix a problem on Windows where the Windows Service Manager was not waiting
the full configured time of the wrapper.jvm_exit.timeout and
wrapper.shutdown.timeout properties. This was leading to the net stop
command timing out and the system shutting down without the java application
having fully stopped. Bug #1582568.
* If internal firewalls were preventing the backend socket from being created,
it was not being made clear what the cause was. It was also possible that
the JVM would deadlock on shutdown. This second problem was recovered from
when the Wrapper killed the JVM.
* Rework the console output from all Wrapper classes to make it much more
obvious that that is their source.
* Submit a patch to the UNIX sh script by Chris Dance which makes it possible
to tell the shell to wait a few seconds for the wrapper to start up. Also
includes some modifications to work correctly on older Debian and RedHat
systems.
* Fix a problem where the local copy of ant was not always being used
correctly on UNIX systems which have a default copy of any installed.
Thanks to Robey Pointer for the patch.
* Add the -lm to the command line when building Linux 32 and 64 bit versions
of the wrapper on Linux. This is to support building on recent Debian
and Ubuntu versions. Thanks to Robey Pointer for the patch.
* Add support for the SIGUSR1 and SIGUSR2 signals so they can now trigger a
shutdown, restart or be forwarded to the JVM for custom functionality.
See the wrapper.signal.mode.usr1 and wrapper.signal.mode.usr2 properties.
Based on a patch by Robey Pointer. Note that the JVM process does not
trap SIGUSR1 or SIGUSR2 signals as they are used internally by the JVM
as part of the garbage collection process.
* Fix a problem where the WRAPPER_OS, WRAPPER_ARCH, and WRAPPER_BITS
environment variables were not being initialized correctly for the various
unix platforms.
* Removed the 4096Mb upper limit set on the wrapper.java.initmemory and
wrapper.java.maxmemory properties. 64bit users need to go way beyond that.
* Fix a problem where relative include file references in the configuration
file were not working correctly if the wrapper.working.dir was used to
change the working directory. The working directory is now always reset
to its original value as the configuration file is being loaded.
* Added a new wrapper.registry.java_home property which makes it
possible to specify the location of java within the registry.
* Set a new WRAPPER_JAVA_HOME environment variable if the JAVA_HOME is
located in the Windows registry.
* Modify the way properties are looked up so that any unreplaced environment
variable references will be reevaluated in case they were set after the
property was originally set. This is possible with some WRAPPER_*
environment variables or depending on the placement of set.* properties
in the configuration file.
* Set any unset properties to their default values internally. This is
necessary so the WrapperManager.getProperties() method returns the
correct set of active properties.
* Fix an occasional crash with 64-bit UNIX caused by a native synchronization
problem when system signals are trapped. Bug #1614010.
* Fix a problem on Solaris versions, where the Wrapper was not correctly
recovering and attempting another back end port when the first was already
in use. Bug #1594073.
* Fix a problem on Solaris and AIX where the RUN_AS_USER feature of the
shell script was not working due to lack of support for the "-m" option of
su. The shell script now uses "su -". Bug #1590168.
* Add HP-UX Makefiles for building with make. Fix some problems in the
shell script to make the script work better on HP-UX. Thanks to David
Brown and Nicolas Varney for the patches.
* Fix a problem where any signals received by the JVM and triggering a
SIGCHLD signal in the Wrapper were being interpretted as the JVM having
stopped. This was not always true. Bug #1643666.
* The Wrapper is now able to detect when the JVM process is stopped and
continued. It will still timeout if stopped, but a descriptive warning
is now logged.
* Increase the maximum number of log entries which can be queued to avoid
losing them. These are only used for log entries outside of the primary
thread.
* Fix a problem in the shell script which was making it impossible to stop
the Wrapper or query its status on OSX.
* Add support for 64 bit AIX. Thanks to Nicolas Varney for supplying a
Makefile.
* Correct the AIX library extension to be ".a".
* Rename the UNIX Makefiles so it is more obvious which tool must be used
to build with them.
* Fix a problem where the HP-UX native library would not be located
correctly for some processor types if the file had a platform specific
name.
* Internally rename the WRAPPER_JSTATE_LAUNCH state to
WRAPPER_JSTATE_LAUNCH_DELAY for clarity.
* Fix a problem where the UNIX versions of the Wrapper would shutdown
rather than restarting a frozen JVM if the arrival of the SIGCHLD signal
from the old JVM process was delayed by more than a second or two.
* Rework the Windows build so it now uses nmake and a Makefile rather than
vcbuild. This is probably not as clean, but it was needed to get the
64-bit build working.
* Fix a problem on Windows versions where quoted values specified from the
command line were not always being requoted correctly when generating the
java command line.
* Add validation checks for Windows versions to make sure that all additional
parameters, application arguments, the classpath, and library path all
contain values which are quoted correctly. Incorrectly quoted values will
now result in a warning message that will help resolve the problem.
* Fix a memory leak when calling WrapperManager.listServices() on Windows.
Bug #1665947.
* Fix a buffer overflow problem if the Wrapper was launched without explicitly
specifying a configuration file.
* Add tests of the return values of all malloc calls to catch out of memory
errors and recover as gracefully as possible. Bug #1649880.
* Modify the WrapperManager.signalStarting and signalStopping methods so that
they will never have the effect of shortening the existing timeout.
Updated the javadocs of both methods so they more accurately reflect what
the methods do.
* Move the Wrapper Copyright banner into the Wrapper process so it will be
output more consistently.
* Branch the code to support Community, Standard, and Professional Editions
of the Java Service Wrapper.
* (Standard, Professional) Add support for Server (Fixed) as well as
Development (OEM based) licenses.
* (Standard, Professional) Add 64-bit versions of the Windows version. The
64-bit Community Edition will not be distributed initially to support
ongoing development costs.
* (Professional) Add event handling callbacks for Wrapper start/stop, JVM
start/stop, JVM started/stopped, JVM restart, JVM killed, and JVM unexpected
exit events.
* (Professional) Add the ability to send emails in response to any event
callback.
* (Professional) Add the ability to execute a a user configured command in
response to any event callback.
* Add WRAPPER_BIN_DIR and WRAPPER_WORKING_DIR environment variables which are
now available for use within the wrapper.conf file as well as by any child
processes.
* Add documentation to the integration pages about existing system properties
that be used to control the way the WrapperSimpleApp and WrapperStartStopApp
handle application startup.
* Remove support for native PPC and x86 distributions of the Wrapper for
MAC OSX in favor of the universal X-Code distribution. This appears to be
the standard for the market and saves lots of time on testing.
* Add a new '-it' command to the Windows version which makes it possible to
install and start a service as a single command.
* Fix a problem where the PATH environment variable was not being set correctly
on Windows versions when run as a service if the wrapper.ntservice.account
was set and a PATH was set for both the SYSTEM and user accounts.
Bug #1702274.
* Modify the shell script to set JAVA_HOME to the default JVM location on
OSX systems if it is not already set. OSX always places the JVM in a known
location so this is possible. Thanks to Andrew Williams for the patch.
* Fix a problem where the UNIX shell script would fail if the APP_NAME was set
to a value containing spaces. Thanks to Andrew Williams for the patch.
Bug #1695678.
* Fix a problem where the DIST_ARCH was not being resolved correctly on HP-UX
systems. Thanks to Matej Kraus for the patch. Patch #1697421.
* Log output from the timer thread was not being queued correctly, this could
have lead to timing problems if there were any delays writing to disk.
* Add partial support for OS/400 into the build file. Still needs a Makefile.
* Fix a problem where the WrapperActionServer would deadlock in its stop method
if the JVM shutdown was initiated by a call to the shutdown or restart
actions.
* Add support for wrapper.console.title on UNIX platforms. Add a set of
wrapper.console.title. properties which make it possible to set the
title based on the platform.
* Fix a problem where the wrapper.ntservice.account and
wrapper.ntservice.password properties were being stored in the system
registry if the they were specified on the command line when the Wrapper
was installed as a service. This was broken in version 3.2.2.
Bug #1538725.
* Fix a problem where the DUMP command was not working with the
wrapper.commandfile property when run as a service on Windows.
Bug #1644421.
* Fix a problem where wildcards like "*.*" or "*" in a classpath property were
including the "." and ".." files on Windows versions. Bug #1517928.
* Modify the debug log output when the Wrapper is attempting to load its native
library in an attempt to make the expected failures less threatening.
* Commit a patch by Rob Oxspring which adds the start_msg and stop_msg commands
to the shell script. These are expected by init scripts on HP-UX.
Patch #1750027.
* Add a DETAIL_STATUS flag to the UNIX shell script which will cause the
status, start_msg, and stop_msg commands to display the current internal
status of both the Wrapper and Java processes.
* Commit a patch by Rob Oxspring which adds an init block to the UNIX shell
script to make it work with install_initd and remove_initd scripts used by
SUSE linux. Patch #1750028.
* Commit a patch by Travis Carlson, ia64 systems were being grouped as "x86"
systems. They now are assigned the name "ia" which makes it possible to
create a distribution for them. Patch #1663887.
* (Standard, Professional) Add new wrapper.java.initmemory.percent and
wrapper.java.maxmemory.percent properties which make it possible to set
the initial and maximum memory values relative to the amount of physical
memory on the system. Feature Request #1741051.
* Add a new #include.debug declaration in the wrapper configuration file which
makes it much easier to debug problems with cascading include files.
* Add -l and --controlcode commands to the Windows version which make it easy
to send user defined control codes to the Wrapper running as a service.
* Fix a synchronization problem in the logging code which could result in
data corruption or access violations.
* Add version numbers to the bat and sh scripts to make them easier to
support.
* Make the wrapper.ntservice.name, wrapper.ntservice.displayname, and
wrapper.ntservice.description properties aliases of new wrapper.name,
wrapper.displayname, and wrapper.description properties as they are now
used on UNIX platforms as well as Windows.
* Fix a problem where the wrapper would sometimes fail to send a packet to
the JVM because the sending of the packet would block. Thanks to Peter
Gorgon for the patch.
* Fix a problem where CPUs identifying themselves as 'ia64n' or 'ia64w' were
not correctly being categorized as 'ia'. Thanks to Stirling Chow for the
patch. Patch #1859412.
* Add -d and --dump commands to the Windows version which make it possible to
send thread dump requests to the Wrapper when running as a service. Works
in association with the new wrapper.thread_dump_control_code property.
Feature Request #1118110.
* (Professional) Add wrapper.timer..interval and wrapper.timer..action
properties which make it possible to schedule Wrapper shutdowns, JVM
restarts and thread dumps at arbitrary times.
* Fix a problem where the default configuration file name was being corrupted
by a buffer overrun. Thanks to Rob Joyce for the patch. Patch #1879049.
* Fix a problem where the WrapperManager would sometimes attempt to unregister
its shutdown hook after the shutdown hook had been initiated. Bug #1799489.
* Fix a problem where log files were limited to 2GB on Linux systems.
Bug #1881038.
3.2.3
* Add support for x86 Mac OS X distributions.
* The 3.2.2 Windows version was accidentally released with its MFC libraries
dynamically linked. This meant that anyone who did not have VS8 installed
were not able to run the Wrapper due to missing DLLs. This version fixes
that snafu by correctly using statically linked libraries as was done in
previous versions built with VS6. Bug #1578554.
3.2.2
* Correct a typo in the usage output of the WrapperStartStopApp. Thanks to
Michael Giroux for pointing it out.
* Fix a problem on OSF1 systems where the backend socket was not listening
correctly due to a backlog of 0. This was broken in 3.2.0. Thanks to
Phillip Gussow for supplying a patch.
* Remove the com.silveregg.wrapper package classes that were deprecated in
version 3.0.0.
* Fix a potential problem in the UNIX script where the lock file permissions
were not being set correctly if the LOCKFILE and RUN_AS_USER variables are
specified but the group of the specified user could not be resolved.
* Fix a problem where the exit code returned by WrapperListener.stop was being
ignored in some cases.
* Fix a problem where the shell script would not work correctly when the
wrapper or its configuration files were located in a directory path
containing spaces.
* Apply a series of patches by Michael Saya to get the Windows 64 bit build
working.
* Fix a problem in UNIX versions where the SIGTERM handler was being disabled
when a SIGCHLD was received.
* Added support in UNIX versions for the SIGHUP signal.
* Migrated the source to Subversion from CVS. Did a bunch of cleanup in the
source, removing CVS specific tags.
* Fix a problem in UNIX versions were the pid file specified by the
wrapper.java.pidfile property contained the wrapper pid rather than the
jvm pid. Bug #1565011.
* Fix a problem in UNIX versions where the file specified by the
wrapper.java.pidfile property was not always being deleted when the JVM
process went away.
* A user encountered a JVM bug where calls to System.exit were resulting in
an IllegalThreadStateException being thrown. Added some code to trap this
and shut down the JVM using other means to avoid a hang during shutdown.
* Fix a NullPointerException caused by users incorrectly implementing
an Integration Method #3 class and then calling WrapperManager.start with
a null value for the args parameter.
* Update the banner displayed by the Wrapper on startup to include a
copyright notice. Please see the license page of the documentation for
details.
* Add a new 'Z' log format which will log the time to millisecond accuracy.
* Fix a problem where the JVM exit code was not being set correctly when
the JVM was shutdown using WrapperManager.stopImmediate(). The exit code
of the Wrapper was being set correctly through other means however.
* Fix a potential synchronization problem in the logging code if a JVM exits
with debug output enabled.
* Updated the WrapperListener.stop method javadocs to better explain the
exitCode value under certain exit modes.
* On UNIX versions, add a log message which records the signal that caused
the JVM process to exit when it terminates unexpectedly.
* Fix a problem where the wrapper.on_exit. property was not working
correctly in some cases on UNIX. With help from Andreas Schafer.
* Add support for building the Wrapper with Visual Studio 8 for Windows.
Releases will now be done using this compiler.
* Fix a CRITICAL bug in the 3.2.0 and 3.2.1 Windows versions of the Wrapper
where the Wrapper would crash under rare circumstances when running as a
service. If the service manager interrogated the service at the same
instant as the wrapper was pinging the JVM, the wrapper was sometimes
crashing due to a synchronization problem. The problem did not exist
prior to 3.2.0. Bug #1574537.
* Fix a minor logging problem where the 'D' format was not displaying the
correct thread name for queued log messages.
3.2.1
* Fix a problem with the solaris-sparc-64 makefile.
* Add a solaris-x86-64 makefile.
* Merge in a patch by Hugo Weber to make it possible to configure the Wrapper
to pull the JRE from the system registry on windows.
* Fix a batch file bug added in 3.2.0 where the scripts would not function
correctly if the full path to the batch file contained spaces.
Bug #1450601.
* Modify the message shown when a native library fails to load so the
exception message text is now shown in the log without having to enable
debug log output.
* Modify the UNIX shell script to be more informative if the script is unable
to locate a wrapper binary due to a executable bit permission problem.
* Fix a minor permission problem with the build for the delta-pack.
* Commit a patch by Juergen Hermann to make the error shown when realpath
fails clearer.
* Add the ability to use a default wrapper.conf file that is in the same
directory as the wrapper binary. The file will be named based on the
name of the wrapper binary.
* Synchronize the command line so that both the Windows and UNIX versions
are now the same. The old command line syntaxes are now supported
everywhere so there will be no compatibility problems.
* It is no longer possible to specify arguments using the '/c' syntax.
This was undocumented so hopefully it is not being used. The documented
'-c' syntax must now be used. The change was necessary to synchronize
the command line between UNIX and windows platforms.
* The 32-bit HP-UX 3.2.0 build was generating a libwrapper.so file rather
than libwrapper.sl.
* Make the WrapperManager.setConsoleTitle, getWrapperPID, and getJavaPID
methods available through JMX.
* Fix a state engine problem introduced in 3.2.0 which was causing the
wrapper.on_exit. properties to be ignored in most cases.
* Fix a potential problem that could have caused crashes when debug logging
was enabled.
* Fix a problem where signals were not being handled correctly on some UNIX
platforms, including AIX. This was making it impossible to shutdown the
wrapper cleanly with the TERM signal. Bug #1477619.
* Add new default environment variables which can be referenced in a
configuration file to configure platform specific directories and file
names. WRAPPER_OS, WRAPPER_ARCH, and WRAPPER_BITS.
* Add a -v argument to make it possible to request the version from a wrapper
binary.
* Add support for registering the WrapperManager MBean with the
PlatformMBeanServer when run on a 1.5+ JVM. See the JMX section in the
documentation for details.
* Rework the way timeout properties are handled. Values of 0 now actually
disable the timeouts rather than setting them to a large value. To avoid
overflow problems when converting to internal timer ticks, timeouts are now
restricted to a maximum of 20 days, or 1728000 seconds. Change affects the
wrapper.cpu.timeout, wrapper.startup.timeout, wrapper.ping.timeout,
wrapper.shutdown.timeout, and wrapper.jvm_exit.timeout properties. For
values less than 20 days, there should be no change in functionality.
* Add support for debuggers. The Wrapper will now show a warning on startup
and then again the first time a timeout occurs. But all timeouts will be
ignored. This is to avoid problems with the Wrapper restarting a suspended
JVM in the middle of a debugging session. The wrapper enters this mode if
the wrapper.java.command ends with the string "jdb" or "jdb.exe", or the
"-Xdebug" parameter is passed to the JVM.
* Add 'athlon' to the list of supported architectures.
* Fix a problem where the environment variables loaded when a service was
started were always the system environment even if the service was running
as a specific account. The environment of a specific account will now be
loaded on top of the system environment if the USERNAME environment
variable is set by the system. Bug #1491138.
* Added new wrapper.ntservice.pausable and wrapper.ntservice.pausable.stop_jvm
properties to make it possible to pause and resume the Wrapper when installed
as a Windows service.
* Added new Pause and Resume batch files as well as modified the command batch
file to support pause and resume.
* Added PAUSE and RESUME commands for use by the wrapper.commandfile property.
* Fix a problem with the wrapper.pidfile, wrapper.java.pidfile,
wrapper.anchorfile, wrapper.commandfile, wrapper.statusfile,
wrapper.java.statusfile, wrapper.java.idfile, and wrapper.lockfile
properties where forward slashes in paths were not being changed to back
slashes on Windows versions.
* Simplify the code used to load a native library by using the
System.mapLibraryName method rather than doing the same thing manually.
* Add a new wrapper.syslog.facility property which makes it possible to
specify the syslog facility on UNIX systems. Thanks for the patch from
Bruce Pennypacker.
* Removed the custom thread counting used to keep track of when the wrapped
Java application has completed. It is now done in a different way that
will work on all Java implementations without requiring any special
consideration of the current JVM. Deprecated the
wrapper.monitor_thread_count and wrapper.thread_count_delay properties.
Bug #1470265.
* The WrapperStartStopApp helper class still requires thread counting if the
stopWait parameter is set to true. Previous versions all hardcoded the
system thread count to 1 which worked for most JVMs. A new system property,
org.tanukisoftware.wrapper.WrapperStartStopApp.systemThreadCount, was added
to make it possible to customize. It currently defaults to 1.
* Make it possible to extend the WrapperSimpleApp and WrapperStartStopApp
helper classes. Feature Request #1510274.
* Add warning messages if the old org.silveregg.wrapper package classes are
still being used. They will be removed in the next release.
3.2.0
* Rework the release cycle so that the wrapper.jar file released for all
platforms is now built on the same machine. This resolves a few
incompatibility problems caused by jars built on very new JVMs but run
on old JVMs.
* Add additional output when the JVM can not be launched due to security
restrictions on Windows.
* Greatly improved the performance of file logging. On a windows test machine
3.1.2 could log 67210 lines of output in 20 seconds with a 80-15% split
between the Wrapper and JVM process CPU usage. It now outputs 215214 lines
with a 64-34% split, also showing less load on the system process. This is
a 220% increase in performance. In both cases, the JVM was completely idle
other than the console output which makes the Wrapper appear to be a bit of
a CPU hog. In fact it is the only process doing any work in this case.
This improvement was accomplished by keeping the log file open unless idle.
The idle time can be controlled using the new
wrapper.logfile.inactivity.timeout property. The speed increase on UNIX
platforms was much smaller at around 10%.
* Add a new property, wrapper.disable_restarts, which will completely disable
the Wrapper's ability to restart JVMs.
* Add a pair of new properties, wrapper.port.min and wrapper.port.max, which
make it possible to define the port range used when a specific wrapper.port
is not specified.
* Fix a problem where certain characters like umlauts were being stripped from
property values. Bug #1049528.
* Make the PIDs of the Wrapper and Java process easier to access by providing
a new pair os system properties; wrapper.pid and wrapper.java.pid, as well
as a new pair of methods; WrapperManager.getWrapperPID() and
WrapperManager.getJavaPID().
* Add a new WrapperEventListener class which can be implemented to receive
a wide variety of events from the Wrapper.
* Add a WrapperServiceControlEvent class which will report any service control
codes received by the Wrapper as it is running as an NT service. This was
added to make it possible for other applications to sent custom codes to the
Wrapper using the Window Service Manager.
* Add a WrapperManager.listServices() method which can be used to obtain the
status of all services on a Windows system.
* Add a WrapperManager.sendServiceControlCode() method which makes it possible
to start, stop, pause, continue, any service on Windows systems. It is also
possible to send custom user codes via the service manager.
* Add comments in the sh script to support the chkconfig command.
* Implement the ability to read from standard input via System.in. Feature
Request #1024693.
* Made the tick based timer the default by changing the default value of the
wrapper.use_system_time property to false. Most users should see an
improvement in reliability under heavy loads with this new setting. If you
have extended any timeouts in the past, you may wish to try going back to
defaults as they may no longer need to be extended.
* Add a new wrapper.restart.reload_configuration property which causes the
Wrapper to reload its configuration file immediately before a JVM restart.
Properties which can not be reloaded have comments stating that fact in
their documentation. Feature Request #981060.
* Fix a problem in the UNIX shell script which was preventing the script from
locating the PID and anchor files when the wrapper.working.dir property was
used.
* Modify UNIX versions so that the wrapper binary will now force its working
directory to the location of the wrapper binary. This change was made to
make the UNIX version work the same way as the Windows version and thus make
configuration files that modify their working directory work correctly on
a cross platform basis. Users which have been using the scripts supplied
with the Wrapper should not encounter any problems. Other users may require
slight changes to their configuration file to deal with the new way that the
Wrapper deals with its initial working directory.
* Add a new method WrapperManager.getProperties() which makes it possible to
access any property in the Wrapper configuration file.
* Fix a problem where TERM signals were not being correctly ignored by the
JVM process on UNIX platforms even if the wrapper.ignore_signals property
was set to true. Earlier versions of the Wrapper would generate a
WRAPPER_CTRL_SHUTDOWN_EVENT when a TERM signal was received. On Windows
that signal should never be ignored. To resolve this a new
WRAPPER_CTRL_TERM_EVENT was added making it possible to selectively ignore
the TERM signals. This change may affect user implementations of the
WrapperListener.controlEvent() method. Bug #1086344.
* The Windows version has a feature which allows the user to immediately kill
the Wrapper and its Java application without waiting for a clean shutdown
by pressing CTRL-C twice. Windows sends the CTRL-C signal to both the
Wrapper and Java processes. Due to a rare timing problem, it was possible
for the Java process to get the signal first and initialize a shutdown
before the Wrapper could respond to the signal. In this case the Wrapper
was interpreting this as a second CTRL-C signal even though the user only
pressed it once.
* If the wrapper.anchorfile or wrapper.pidfile properties are used on Windows
they were being unintentionally deleted if the -t, -p, -i, or -r commands
were used while another Wrapper instance was running. In the case of the
anchor file, this would result in the Wrapper being shutdown unintentionally.
This was not an issue on non-Windows versions. Bug #1108517.
* Fix a security problem where the value of the wrapper.ntservice.account
and wrapper.ntservice.password properties were being stored in plain text
within the registry if they were specified on the command line when
installing the Wrapper as a Windows service. Bug #1110183.
* Add a pair of properties wrapper.ntservice.password.prompt and
wrapper.ntservice.password.prompt.mask which which will cause the Wrapper
to prompt the user for an account password when it is being installed as
an NT service.
* Added system properties to make it possible to configure whether or not
the WrapperSimpleApp and WrapperStartStopApp helper classes will wait
for the configured main methods to complete before reporting that the
application has started. See the javadocs for these classes for more
details.
* Modify the HP-UX build so that it now dynamically links with the pthread
library. This was to make the binaries work with HP-UX 11.00. Thanks to
Sun Kun Choi for the patch.
* Add new wrapper.statusfile and wrapper.java.statusfile properties which can
be used by external applications to monitor the internal state of the Wrapper
or JVM at any given time. These will not be useful to most users.
* Add a new wrapper.commandfile property which can be used by external
applications to control the Wrapper and its JVM.
* Add a new wrapper.java.idfile property which can be used by external
applications to monitor the internal state of the JVM at any given time.
* Add a warning on startup if the JVM has a SecurityManager set but the
wrapper.jar has not been granted the AllPermissions permission. Failure
to do so will almost certainly lead to the Wrapper throwing a number of
errors and this helps to point out the cause.
* Add a security model which protects most Wrapper method calls when a
SecurityManager has been registered. See the Security Model section
for more details.
* Add a new pair of batch files which can be used to start and stop the
Wrapper when installed as a service.
* Add new -q and -qs commands to the Windows version of the Wrapper which
make it possible to query the currently installed status of the service.
* Fix a problem where the wrapper.java.library.path.append_system_path
property was not working correctly on Windows when the system PATH
contained quotes. Bug #1238726.
* Modify the usage output of the Wrapper on all platforms so the Wrapper's
version is now included. It was not previously possible to get the version
of the Wrapper being used without launching a JVM.
* Add a pair of new methods WrapperManager.stopAndReturn() and
WrapperManager.restartAndReturn() which make it possible for code to
stop or restart the JVM and then continue until the JVM is shutdown.
This can be useful for shutdowns initiated within places like servlets,
whose operation is expected to complete.
* Fix a problem on UNIX where the child JVM was sometimes leaving around
zombie processes after a restart. The SIGCHLD signal was not being handled
correctly. Thanks to Traun Leyden for the patch. Bug #1291201.
* Implement the ability to catch control events using the WrapperEventLisener.
Feature Request #836975.
* Add new wrapper.jvm.port, wrapper.jvm.port.min, and wrapper.jvm.port.max
properties which make it possible to control the port the JVM uses to open
a connection back to the JVM. The Wrapper uses to leave this up to the
OS, but some users were having problems with the default conflicting with
other ports.
* Switch from using ftime() to gettimeofday() on UNIX platforms to work around
a problem where the Wrapper would not run on new versions of OSX because
they deprecated the ftime() function call. Thanks for the patch by
Michael Macaluso. Bug #1313162.
* Remove the shutdown timeout from the UNIX shell script. It is not needed
and can cause a zombie JVM if the wrapper's internal shutdown timeout was
longer than that of the shell script.
* Add the ability to specify integer property values in base 8 or 16 in
addition to base 10. Base 8 values start with a '0' and base 16 values
start with a '0x'.
* Make it possible to set the umask on all files created by the Wrapper
as well as the default umask of files created by the JVM. Added new
wrapper.umask, wrapper.java.umask, wrapper.pidfile.umask,
wrapper.lockfile.umask, wrapper.java.pidfile.umask,
wrapper.java.idfile.umask, wrapper.statusfile.umask,
wrapper.java.statusfile.umask, wrapper.anchorfile.umask, and
wrapper.logfile.umask properties.
* Improve the message when the native library can not be loaded to make mention
of the possibility of a 32/64 bit mismatch.
* Add a new wrapper.monitor_thread_count property which makes it possible to
disable the Wrapper's counting of non-daemon threads and thus the shutting
down of the JVM when they have all completed.
* Add support for BELOW_NORMAL and ABOVE_NORMAL options to the
wrapper.ntservice.process_priority property. Feature Request #1373922.
* Ignore '#' characters which are included within double quotes in the value
of a property in the configuration file. Unquoted values must be escaped
with a second '#' characters or it will be interpreted as a comment.
* Display the Wrapper banner in the JVM earlier so that it is displayed
even where there are startup errors.
* Modify the WrapperSimpleApp and WrapperStartStopApp classes so that the
WrapperManager is always initialized immediately. This makes the output
clearer in the event of startup errors.
* Fix a problem where the Windows ServiceManager was not correctly reporting
a startup error if a service failed on startup. The service was being
reported as having started even though it failed to start.
* Fix a problem on UNIX versions where the Wrapper would go into a recursive
state of attempting to launch the JVM from failed child processes if there
was any problems executing the configured java process.
* Rework the way the RUN_AS_USER setting in the UNIX shell script works so
the specified user is now set regardless of the command being executed.
To make sure the user never has to enter the password twice when running
the script, it now recurses after changing the user. The script then
runs entirely as the configured user.
* Improve the message that is displayed when attempting to start, stop, or
remove a windows service which is not installed.
* Add new wrapper.lockfile property which makes it possible to specify a
lock file containing a pid.
* Modified the sh script so it now creates a lock file on startup in the
/var/lock/subsys directory if it exists. This is needed by fedora systems
on shutdown.
* Store javadocs in tar distibutions in a nested tar file to avoid problems
with long filenames in some tar distributions.
* Fix a problem with the WrapperSimpleApp and WrapperStartStopApp helper
classes where on heavily loaded systems it was possible for the Wrapper
to get a running thread count of 0 and shutdown before the main thread
had a chance to be started.
* Add a new wrapper.thread_count_delay property which will force the
WrapperManager to wait the specified number of seconds before it begins
to check the number of running threads.
* Fix a problem where the wrapper.java.library.path.append_system_path
property was appending the PATH rather than the LD_LIBRARY_PATH environment
variable on Unix systems. PATH is correct for Windows systems.
* Add a new wrapper.logfile.rollmode property which makes it possible to
control how and when the logfile is rolled. Feature Requests #864463,
#1085097, and #1085850.
* Fix a problem on Linux where the test for the status of the Java child
process would sometimes fail causing the Wrapper to shutdown with the
error "Critical error: wait for JVM process failed (No child processes)"
rather than restart the child JVM. Users who encountered this problem
found it easy to reproduce, but it only happened on some systems.
* Modify the way the UNIX shell script tests for the existence of a process
matching the pid in an existing pid file. It now verifies the process
command as well as the pid to fix a system reboot problem where a stale
pid has been reused by another application, making the script think the
wrapper was already running.
* Add support for the GNU libjcj JVM. Like JRocket, it requires slightly
different thread counting.
* Add support for Linux 64-bit PPC and Solaris 32-bit x86 versions.
* Add a new set.default.ENV syntax to the configuration file making it
possible to environment variable values which do not overwrite existing
values, ie. to specify a default value.
* Added a new wrapper.console.flush property which forces the wrapper to
explicitly flush stdout after each line of log output.
* Change the error shown when the JVM shuts down prematurely during a
shutdown to a warning message.
* Fix a problem where the Wrapper would show the following error message
if user code called System.exit from within the WrapperListener.stop
callback method. This would happen if the stop class's main method
registered with the WrapperStartStopApp called System.exit.
"JVM exited unexpectedly while stopping the application."
Bug #945976.
* Add a new wrapper.syslog.ident property which makes it possible to
specify the identity used in syslog entries on UNIX. This was possible
in older versions but was set using the wrapper.ntservice.name property.
Bug #1432855.
* Add support for MacOSX Universal Binary distributions.
* Add support for Delta Pack distributions. This is a distribution that
contains the binaries of multiple platforms.
3.1.2
* Modify the way boolean system properties are resolved by the WrapperManager
so it is now possible to set them to true or false rather than assuming they
are true if set.
* Fix a problem where some localized error messages were not having their
tokens replaced correctly.
* Fix a problem when using the WrapperStartStopApp helper class. The usage
text was incorrectly being displayed in the console if an exception was
thrown while executing the main method of the configured stop class. This
did not change the functionality of the application, but it did cause some
confusion.
* Fix a problem on Windows where a library path or class path which ended in
a backslash was preventing the Wrapper from launching the JVM. The Windows
OS was using the backslash to escape the quote used to close the path. The
fix was to add a second backslash where needed.
* Added a new wrapper.java.command.loglevel property which makes it possible
to control the log level of the generated java command.
* Add support for escaped quotes when stripping quotes on UNIX for the
wrapper.java.additional. and wrapper.app.parameter. properties.
* Change the default value of wrapper.jvm_exit.timeout from 5 to 15 seconds.
The old default was too fast for some applications which take a while to
exit. Applications which were exiting promptly will not see any difference.
* Fix a problem where the JVM would restart at certain times when using the
system time based timer due to an overflow error. This problem was
introduced in 3.1.0. Due to a separate bug in 3.1.0, the Wrapper would
shutdown rather than simply restarting the JVM as was happening in 3.1.1.
The last restart happened on Aug 21, 2004. It will next occur Oct 10, 2004
and repeat at regular intervals. There are no problems when using the new
Tick based timer. Bug #1014405.
* Correct the wrapper.logfile.maxsize property so that a a kilobyte is now 1024
rather than 1000, and a megabyte is a megabyte. We aren't a hard drive
manufacturer after all.
* Add try-catch blocks around all thread entry points in the Windows version.
This has always been done in the main function, but these blocks will help
to narrow down the cause of problems should they ever be encountered in
control or service handlers.
* Centralize shutdown code on UNIX version in an appExit method as was already
being done for Windows versions.
* Fix a problem where the build.sh was not correctly using the included ant
if an ANT_HOME environment variable was defined.
* Add a new wrapper.single_invocation property which will prevent multiple
invocations of an application from being started on Windows platforms.
The shell script handles this on UNIX platforms. Feature Request #889123.
* Fix a crash problem introduced in 3.1.1, caused by a pair of uninitialized
pointers. The crash was possible on all platforms but would only happen
if the Wrapper was started without any arguments. It would not affect
users running the Wrapper normally. Bug #1018481.
* Fix a problem with the run as user feature of the shell script on Solaris.
Needed to be using /usr/xpg4/bin/id rather than /usr/bin/in if available.
Bug #1024008.
* Replace calls to usleep with nanosleep on platforms where it is available.
This was to fix an occasional hang on a specific Solaris machine. It would
occasionally hang on calls to usleep. From research, it appears that usleep
has problems when signals are encountered while sleeping. Still testing
whether or not this change solved the problem.
* Upgrade the version of Ant included with source releases to 1.6.2 to fix
some problems generating jni headers when building with Java 1.4.2.
* Upgrade the version of Cocoon included with source releases to 2.0.4 to
fix some problems generating documentation using Java 1.4.2.
* Display a warning if the exit status of a JVM process ever returns the
STILL_ACTIVE status on Windows. There was no known problem here, just
noticed it while looking over the code.
* Display a descriptive error message on Windows if the the JVM process crashes
due to an uncaught exception in native JVM code.
* Add a test for invalid jvm arguments set using the wrapper.java.additional.
properties. Invalid arguments could cause the Wrapper startup to fail in
non obvious ways if they are mistaken by the JVM as the main class.
3.1.1
* Modified the way libwrapper.so is built on Solaris and Linux so that it
no longer statically links its required libraries.
* Fix a file handle leak when calling WrapperManager.getUser or
WrapperManager.getInteractiveUser on Windows platforms.
* Fix a problem introduced in 3.1.0 where the JVM would not be restarted
correctly if it quit after a ping timeout to let the Wrapper resynch and
restart it.
* Fix a problem where CTRL-C was not being handled correctly if the console
was configured to be shown when running as an NT service.
* Fix a problem where signals fired at UNIX versions of the wrapper were
not being handled correctly when the tick timer was being used.
* Fix a synchronization problem in the logging code which would
occassionally cause the Wrapper to crash with an Access Violation.
The problem was only encountered when the tick timer was enabled,
and was only seen on multi-CPU systems. Bug #949877.
* Fix a problem when using the tick timer where the Wrapper would sometimes
exit on startup due to an uncaught SIGALRM. Only reported on multi-CPU
Solaris systems.
* Fix a problem where the Wrapper would sometimes hang on shutdown if
another thread called System.exit while the Wrapper was shutting down.
Bug #955248.
* Fix a problem introduced in 3.1.0 where a very very large CPU timeout
warning message was being displayed if the system time was set back
while using the default system timer.
* Added a new property, wrapper.anchorfile, which makes it possible to
cause the Wrapper to shutdown by deleting an anchor file. The UNIX sh
script has been modified to optionally make use of this feature.
* Add a debug message at startup which makes it clear which timer is being
used.
* A Windows user reported that using forward slashes in the path the log
file was failing. Avoid this problem by always converting '/' to '\'
in the wrapper.logfile property on Windows.
* Fix a problem where it was not possible disable the wrapper log file as
documented in the wrapper.logfile property. Most likely broken way back
in version 2.2.5.
* Add some additional error checks after calls to control the pipe between
the JVM and Wrapper as well as improving the messages around other socket
related error messages.
* Fix a problem on some HP-UX systems were not working correctly because
the EAGAIN and EWOULDBLOCK constants are not equal with some compilers.
* Change some of the defaults in the src/conf/wrapper.conf.in file which
ships with the Wrapper to avoid confusion with new users.
* Rewrote the routine which reads and logs console output from the JVM
for Windows versions. Internal buffers are now scaled dynamically,
fixing a problem where long lines were being wrapped at 1024 characters.
This rewrite also resulted in a 4 fold increase in speed when the JVM is
sending large quantities of output to the console.
* Increase debug output on UNIX platforms when a signal is caught. When
possible, information about where the signal came from is now logged.
* Modified the way log output from within signal handlers is handled so it
is now queued and then logged by the main event loop.
* Back out a 3.1.0 change where a JVM that had failed to exit cleanly was
sent a SIGTERM prior to a SIGKILL. The SIGTERM made no difference and
slowed down the forced shutdown. A modification to the event loop made
the functionality more difficult to implement.
* Add the ability to set the user that the Wrapper and its JVM will run as
from within the sh script on UNIX platforms.
* Add an icon resource to the Wrapper binary on Windows versions.
* Fix a typo in the UNIX sh script which caused an extra slash to be included
in the path of the pid file. Was not causing any known problems.
* Added support for 64-bit HP-UX. Big thanks to Venkatesh Sellappa for
supplying the patch.
* Fix a deadlock problem introduced in 3.1.0 with some FreeBSD systems. Not
all users were experiencing it, but those who did were able to reliably
reproduce the problem. The problem appears to have been caused by
FreeBSD bug #kern/64313.
* Make the signal handling variables in the wrapper native library volatile.
Directly this was to fix a compiler warning on HP-UX64 systems but it
should also make the calls more efficient.
3.1.0
* The license was revised for this version to include a copyright omission.
This change is to be retroactively applied to all versions of the Java
Service Wrapper starting with version 3.0.0. The changes should have
no effect on users.
* The Online documentation and web site were both reworked. The logo has
been updated so that Duke is no longer used. The new online site now
has the ability for users to logon and append comments to any page.
* Added a new batch file which accepts commands like the UNIX shell script.
The new file is offered as an alternative to the default batch files, and
can be found at src/bin/AppCommand.bat.in. Thanks to Mike Castle for
donating the new script.
* The Windows version of the Wrapper was not correctly registering that it
would accept SHUTDOWN messages when running as a service. The Wrapper
was getting the message anyway so this should not change functionality.
Thanks to Jason Tishler for noticing this and sending in a patch.
* Add a new property, wrapper.native_library, which can be used to specify
the base name of the native library which is loaded by the WrapperManager
class.
* Modify the WrapperManager class so it now stores references to System.out
and System.err on initialization and always writes to those stored streams.
This makes sure that all Wrapper console output always goes to the
wrapper.log file even if user code overrides those streams with calls to
System.setOut and System.setErr. This was necessary to prevent deadlocks
in such user code from affecting the functionality of the Wrapper.
* Fixed a problem where some environment variables where not being correctly
loaded from the system registry when running as an NT service. Big thanks
to Eric Smith for tracking this down and submitting a patch. It turns out
that the putenv function was not being used correctly.
* Modified the way the wrapper.conf file is loaded so it will now read the
contents correctly even if the line feeds in the file are incorrect for
the current platform. Windows line feeds had been causing problems when
used on UNIX platforms. Feature Request #829896.
* Added a new property, wrapper.ntservice.console, which allows a console to
be displayed when running as an NT service.
* Fixed a problem where the request thread dump on failed JVM exit feature
had never worked when running as an NT service. Bug #831775.
* Add a new property, wrapper.console.title, which makes it possible to set
the title of the console in which the Wrapper is currently running. This
currently only works on Windows platforms.
* Added a new method, setConsoleTitle, to the WrapperManager class which
enables the application to dynamically set the console title. Like the
wrapper.console.title property, this only works on Windows platforms.
* Improved the algorithm of the request thread dump on failed JVM exit feature
so that extremely large thread dumps will not be truncated when the JVM
is killed.
* Fix a problem where CTRL-C was being ignored by the WrapperManager if a
WrapperListener is never registered. This is not possible if the Wrapper
is being used correctly but never the less a user did come across it.
* Add some additional debug output to help identify the cause of problems
loading the native library.
* The WrapperManager class now checks to make sure that its current version
matches the version of the native library and Wrapper. If there are any
discrepancies found then appropriate warnings will be displayed, but the
Application will still be allowed to start. This was added to make obvious
the cause of problems resulting from mismatched versions.
* Added a new property wrapper.use_system_time system time. By setting this
property to false, the Wrapper will start using a new experimental timer
which uses a background thread to manage time rather than the system time.
This has a number of advantages over using the system time and should give
most users even more reliable behavior when the system is under high load
or there are changes being made to the system time. The timer is very
critical to the operation of the Wrapper so the old behavior is left as
the default for the time being until this feature has had the chance to be
"time" tested. If all goes well then this will be enabled as the default
in a future version of the Wrapper.
A pair of related properties, wrapper.timer_fast_threshold and
wrapper.timer_slow_threshold were also added to aid in debugging.
* Rework the logging code so it is now thread safe. The addition of the
timer thread means that there is now more than a single thread accessing
that code. This was causing problems as the two threads tried to use the
same buffers. As part of this change, a new format variable 'D' was added
to display the thread which is doing the logging.
* Fix a problem where a thread dump would be invoked if the request thread
dump on failed JVM exit was enabled and the user forced an immediate
shutdown by pressing CTRL-C more than once.
* Add getUser and getInteractiveUser methods to the WrapperManager class to
make it possible for user code to query information about the user running
Wrapper or the user who is interacting with the Wrapper and its JVM.
Feature Request #812175.
* The Wrapper will now always exit with the exit code used to terminate the JVM
whether System.exit is used or WrapperManager.stop. When running as an NT
service the Wrapper now correctly returns the correct exit code to the
service manager so failure recovery tools should now work correctly.
Feature Request #852491.
* Add a status command to the UNIX shell script which can be used to find out
whether or not the wrapper is currently running. Patch submitted by
Joseph Benavidez.
* Modify the WrapperSimpleApp and WrapperStartStopApp so that the main method
of a class is located even if it exists in a parent class rather than the
class specified.
* To make debugging classpath problems easier, the Wrapper now verifies all
classpath entries before launching a JVM and logs debug level warnings for
any entries that do not exist.
* Fix a problem where it was possible to define a zero length filter that would
trigger on any output.
* Add some additional debug output to make it easier to debug startup,
shutdown and restart problems.
* Modify the way the Wrapper forcibly kills a frozen JVM on UNIX platforms so
that it now sends a SIGTERM, waits up to 5 seconds, then sends a SIGKILL.
* Add a new wrapper.java.library.path.append_system_path property which will
cause the Wrapper to append the system path to the generated library path.
Feature Request #917902.
* Fix a problem where spaces around the '=' character of a property definition
were rendering the property invisible to the Wrapper. Bug #916001.
* Fix a problem where the first ping timeout after the JVM was started was
still hard coded at 30 seconds. This was causing a combination of large
values of wrapper.ping.interval and wrapper.ping.timeout to fail.
* Fix a problem where the JVM would fail to shutdown cleanly if the Wrapper
was asked to stop too soon after launching a JVM. This was leading to the
JVM being killed after the shutdown timeout expired. Bug #917281.
* Added an adviser which will print out explanatory messages to the console
and wrapper log file when the Wrapper encounters a commonly made
configuration mistake. This is designed to cut down on support requests
by new users. Can be disabled using the wrapper.adviser property.
* The bash script and the realpath utility have been deprecated since version
3.0.3. They have been removed in this release. The sh script is recommended
on all UNIX platforms, and the realpath utility which was used by pre-3.0.3
bash and sh scripts has not been used since.
* Add the wrapper.startup.delay property along with console and service
specific variants which make it possible to configure a delay between the
Wrapper being launched and the first JVM being launched.
* Promote the wrapper.debug property back from being "deprecated". It has
continued to be useful and deserved documentation and official status.
* Add wrapper.on_exit. properties to control what happens when a exits
based on the exit code.
* Modify the way calls to System.in.read() are handled so that they now block
rather than throwing an exception. Currently, System.in can not be used with
the Wrapper because of the way I/O is passed between the Wrapper and JVM.
* Modified the Windows batch files to fix a problem where the path to the
Wrapper.exe contained more than one "/bin". The new batch files are much
simpler and should be easier to customize if needed. Bug #925308.
* Modified the wrapper.java.initmemory and wrapper.java.maxmemory properties
so that they now default to a value of 0 which causes the -Xms and -Xmx
parameters to be omitted from the command used to launch Java. This
will cause the JVM to use its own default values and also makes it possible
to specify the memory parameters using the wrapper.java.additional.
properties.
* Added a pair of environment variables, WRAPPER_FILE_SEPARATOR and
WRAPPER_PATH_SEPARATOR, whose values are set to either '/' and ':' or
'\' and ';' on startup. They can be used in the wrapper.conf file
to construct platform independent property values.
* Add a new wrapper.working.dir property which makes if possible to change
the Wrapper and JVM's working directory to a location other than the
location of the Wrapper binary. Feature Request #738160.
3.0.5
* Added support for SGI Irix. Big thanks to Andreas Wendt for supplying the
patch.
* Due to a bug in the build, the native library was not included in the 3.0.3
or 3.0.4 binary releases for OSX, building from source was working correctly.
This has been fixed and the build greatly simplified to avoid such problems
in the future. Bug #791755.
* Changed the default location of the pid file generated by the sh script to
exist in the same directory as the sh script rather than in the /var/run.
This can be changed by setting the PIDDIR variable in the sh script used to
launch the Wrapper.
* Added support for the wrapper.pidfile property on the Windows platform.
* Added the wrapper.java.pidfile property which will cause the pid of the
java process to be written to a specified file.
(WINDOWS USERS) If you are using a wrapper.conf file that was created prior
to version 3.0.0 of the Wrapper, then you may have this property defined in
your configuration file. You will get an error on startup if the specified
path does not exist.
* Stop clearing the file creation mask when the Unix version of the Wrapper is
run as a daemon process. The file creation mask will not be inherited from
the process which launches the Wrapper. Bug #788849.
* Modify the sh script so it works on Linux, then deprecate the bash script.
This means that all Unix platforms can now use the same script to control
the Wrapper. Thanks to Mike Castle for the patch. The bash script can still
be found in the release, but it is deprecated and will be removed in a
future version.
* Modified the sh script so it is now possible to set the nice priority in the
script configuration block.
* Remove output to System.out in the WrapperManager.requestThreadDump() method.
If some JVM threads were hung while accessing the System.out object,
attempting to do a thread a dump would cause the calling thread to hang as
well. Thanks to Thomas Hart for the patch.
* Make it obvious in the log whether or not the Wrapper was started as a
daemon process on UNIX systems.
* Modify the way restarts requested from the JVM, or caused by a filter are
handled. The Wrapper will no longer reset the restart count in either of
these cases. If an application runs for longer than the
wrapper.successful_invocation_time timeout then the count will still be
reset back to 0.
* Added a new wrapper.ignore_signals property which makes it possible to
configure the Wrapper so it will ignore CTRL-C, HALT and INT signals.
* Modify the WrapperManager.isLaunchedAsService() method on UNIX systems so it
now returns true if the Wrapper was launched with the wrapper.daemonize flag
set.
* Added a pair of MBean interfaces which allow the Wrapper to be controlled
using JMX. See the new JMX section in the documentation for details.
Thanks to Sal Ingrilli for help with testing.
* Modify the Windows build so the Wrapper.exe and Wrapper.dll files can now
be built from Ant if MSVC is installed.
* Added a new wrapper.ping.interval property which lets users control the
frequency that the Wrapper pings the JVM. Feature Request #607768.
* When a JVM refuses to shutdown, the Wrapper can be configured to request a
thread dump using the wrapper.request_thread_dump_on_failed_jvm_exit
property. The Wrapper was then waiting 1 second before the process was
killed. This was not always long enough, resulting in a truncated thread
dump. Increased the pause to 3 seconds. Feature Request #633761.
* Fix a bug where wrapper.app.parameter. and wrapper.java.additional.
properties declared from the Windows command line were not correctly
handling spaces in their values. Support Request #802139.
3.0.4
* Fix a problem on UNIX systems where requesting a second thread dump any time
during the life of a single Wrapper process would cause the Wrapper and JVM
to shutdown rather than perform the thread dump.
* Fix a problem where a, user without permission, attempting to stop an
application was able to delete the pid file even though they were unable
to stop the application itself. This would make the scripts think that
the application was stopped when was actually still running.
* Fix a problem where an application was being killed prematurely if it took
longer than 6 seconds to exit on its own. The scripts now make sure that
an application always has enough time to shutdown cleanly.
* Improve the debug output so that packet codes are now shown using a name
rather than a raw number.
* Reduce the frequency of "Waiting to stop..." messages displayed when removing
an NT service that is currently running. Decreased frequency from once per
second to once every five seconds.
* Fix a minor problem where the hour in the date returned by
WrapperInfo.getBuildTime() was not base 24.
* Added -t and -p command line options to the Windows version of the Wrapper
to sTart and stoP the Wrapper as an NT service. This can be used in place
of "net start" and "net stop", which do not always work correctly when a
service takes a long time to start up or shutdown. See the Launching Your
Application (Win32) section for more details.
* Add a new method WrapperManager.stopImmediate which will cause the JVM to
exit immediately without calling any stop methods or shutdown hooks.
* Add a new class, WrapperActionServer, which makes it easy to remotely control
the Wrapper remotely by opening a socket and sending commands. See the
javadocs of the class for more details.
* Fix bug #744801. A Java GUI was not being displayed when the application was
run in either console mode or as a service with wrapper.ntservice.interactive
enabled. This problem was introduced in Version 3.0.0 when using 1.2.x or
1.3.x versions of Java. To use interactive services with 1.2.x or 1.3.x
versions of java, please review the documentation for the
wrapper.ntservice.interactive property.
* Fix a problem where the JVM was not receiving CTRL-C and CTRL-CLOSE events
when running under the Wrapper on Windows. This was not a problem in most
cases as the Wrapper was taking care of the processing of the events. But
the WrapperListener.controlEvent() method was not being called as documented.
* Changed the way the WrapperSimpleApp and WrapperStartStopApp respond to
control events so that the JVM will respond and call WrapperManager.stop()
even when being controlled by the Wrapper.
* Modified the suggested behavior of the WrapperListener.controlEvent() method.
Users who have implemented the WrapperListener interface themselves should
review the Javadocs. The changes are not required and applications will
continue to function as they did before.
* Added support for DEC OSF1 (Alpha). Big thanks to Andreas Wendt for
supplying the patch.
* Fix a problem where the sh and bash scripts were failing if the path to the
script contained spaces.
* Fix a problem where the JVM would sometimes hang when trying to shutdown if
the wrapper.key parameter was passed to the JVM while not being controlled
by the Wrapper. This would happen if a user copied the command from the
Wrapper's debug output and attempted to run it as is without first removing
the wrapper.key parameter.
* Implement the ability to specify an NT service's load order group in response
to feature request #764143. See the javadocs for the new
wrapper.ntservice.load_order_group property for details.
* Improve the error message displayed when the NT EventLog is full in response
to feature request #643617. The EventLog output will now be disabled if any
errors are encountered while logging events. This prevents the error from
repeating.
* Improve the error message displayed on Windows when the configured Java
command can not be executed or does not exist.
* Fix a problem where the Wrapper was leaving a pipe unclosed each time the JVM
was restarted on all UNIX platforms. This was causing the Wrapper to run out
of file handles. Bug #767267, discovered and patched by David Wong.
* Fix a problem where the '#' character, which signifies a comment, could not
be included in property values. A double hash, '##' will now resolve into a
'#' within the property value. Bug #777303.
* Added support for FreeBSD. Big thanks to Alphonse Bendt for supplying the
patch.
* Make the wrapper.port property optional.
* Changed the way environment variables are loaded from the registry on Windows
platforms so users will no longer get warning messages about not being able
to handle very large environment variables. Prior versions could only handle
environment variables whose expanded value was less than 2048 characters in
length.
* Fix a problem on UNIX platforms where a shell used to start the Wrapper
running as a detached process would hang when the user attempted to exit
the shell. Thanks to Mike Castle for this patch.
3.0.3
* Added support for Mac OS X. Big thanks to Andy Barnett for supplying the
patch.
* Fix a segmentation fault on UNIX systems when the first console output
from the JVM was an empty line. Thanks to Mike Castle for finding this.
* Fix a problem where a 0 length malloc was being called if there were no
configured filters. This was fine on most platforms but caused a crash
on MAC OS X.
* Rework the initialization of the bash and sh scripts so that they will
work correctly when referenced as symbolic links. Thanks go out to Richard
Emberson for the code to resolve symbolic links.
* Deprecated the realpath binary in the *NIX distributions as it is no longer
used by the bash or sh scripts. It is being left in for now so as not to
break the build scripts of other projects, but it will be removed after a
couple more releases.
* Added a test to make sure that wrapper.ntservice.interactive is not set to
TRUE when an account is specified using wrapper.ntservice.account.
3.0.2
* Modified the sh and bash scripts so that console log output is disabled by
default when the scripts are launched with the 'start' action. Running with
the 'console' action will still send output to the console. Logging to the
file is still enabled.
* Modified the wrapper.ping.timeout property so it also controls the ping
timeout within the JVM. Before the timeout on responses to the Wrapper
could be controlled, but the ping timeout within the JVM was hardcoded to
30 seconds.
* In the last release, some work was done to avoid false timeouts caused by
large quantities of output. On some heavily loaded systems, timeouts were
still being encountered. Rather than reading up to 50 lines of input, the
code will now read for a maximum of 250ms before returning to give the main
event loop more cycles.
* Fix a problem where the values of environment variables set in the
configuration file were not correct when those values included references
to other environment variables.
* Fix a potential buffer overflow problem if configuration properties
referenced extremely large environment variables.
* Fix a potential problem where the inability to expand very large environment
variables would have led to an access violation when run as an NT service.
* Add some extra checks in the event where the native library can not be loaded
so that the WrapperManager can differentiate between the library missing and
not being readable due to permission problems.
* Remove the wrapper.ntservice.process_priority from the default wrapper.conf
because its use can produce unexpected results if used improperly. Please
see the property documentation for details.
* Fix a problem where environment variables in the registry which had no value
were causing the Wrapper to crash with an access violation. This was
introduced in version 3.0.0 with the feature to load environment variables
from the registry. The offending registry entry was WV_GATEWAY_CFG which
appears to be related to Oracle.
3.0.1
* Fix a problem with the wrapper.disable_shutdown_hook. Due to a typo in the
source, the property was being ignored. This was broken in the 3.0.0
release.
* Fix a problem with the HP-UX release build reported by Ashish Gawarikar.
* Add the ability to set environment variables from within the configuration
file or from the command line.
* Fix a problem on HP-UX and AIX machines where the stop() function in the
shell scripts was causing a syntax error due to a conflict with a like named
shell command on those platforms. This appears to be an issue with the
Korn shell on all platforms.
* Fix a problem where very heavy output from the JVM can cause the Wrapper to
give a false timeout. The Wrapper now only reads 50 lines of input at a time
to guarantee that the Wrapper's event loop always gets cycles.
* Fix a problem on UNIX versions where extra line breaks would sometimes be
added to the logged output when there was large amounts of output being
sent from the JVM.
* Fix a problem where a large number of calls to WrapperManager.log()
immediately before the JVM exits could lead to the Wrapper incorrectly
reporting that the JVM exited unexpectedly.
3.0.0
* Deprecated the com.silveregg.wrapper package in favor of
org.tanukisoftware.wrapper. The classes and interfaces in the silveregg
package will continue to function, but migration to the new package should
be done when possible. See the project history for details.
* On Windows systems change any forward slashes in the wrapper.java.command
property to back slashes. Some users had reported having problems on
Windows XP.
* Implemented feature request #633178. Added WrapperManager.requestThreadDump()
to force the current JVM to immediately perform a thread dump.
* Fixed bug where wrapper.logfile.maxsize was being set to 0 if the 'k' or 'm'
unit was omitted.
* Add the ability to specify an account name and password when installing an
NT service.
* Add a property, wrapper.ntservice.interactive, which makes it possible to
control whether or not the Java process can gain access to the desktop while
it is running as an NT service.
* Add limited support for 1.2.x versions of Java. Shutdown hooks are
supported until Java 1.3 so those functions will be disabled. If the
application displays a GUI then Java 1.3 should be used as the GUI can not
currently be displayed when using Java 1.2.x.
* Made it possible to use the wrapper.pidfile property on all *nix platforms.
Please notice that the property has been removed from the default
wrapper.conf file. The property is not needed when the wrapper is launched
with the bash shell script. The sh shell script will set the wrapper.pidfile
when the wrapper is launched. If either of the scripts provided with the
Wrapper distribution are used then the wrapper.pidfile should always be
removed from your wrapper.conf file.
* Added a new wrapper.daemonize property which, when set, will form the wrapper
process to be a detached non-session group leader. This makes it possible to
launch the wrapper in such a way that it will not be terminated when the user
launching the process logs out. This had been a problem on Solaris systems
when using the sh shell. The default sh and bash scripts both make use of
this in the default. Please update your scripts for use with this version.
Thanks to Rajiv Subrahmanyam for the patch.
* Fix a problem where the Wrapper was incorrectly counting the number of
non-daemon threads in BEA's JRockit Virtual Machine. This was causing the
application to shutdown when the non-daemon thread count dropped to 1.
* Added support for building the wrapper on AIX and HP-UX systems. Thanks for
the patches involved go out to Ashish Gawarikar and William Lee.
* Implement feature request #653131 to force the JVM to immediately exit when
the user presses CTRL-C multiple times.
* Added a 'console' action to the bash and sh scripts to make it possible to
launch the Wrapper in the current shell process. The 'start' task will launch
the Wrapper as a spawned daemon process.
* Fixed a problem where missing environment variables specified in classpath
or library path properties were not being handled correctly.
* Implemented feature request #676599 to enable the filtering of JVM output to
trigger JVM restarts or Wrapper shutdowns. See the new
wrapper.filter.trigger.n and wrapper.filter.action.n properties.
* Modify the Win32 version of the Wrapper so that Environment Variables are
always read from the system registry when the Wrapper is run as a service.
By doing this, it makes it possible to change or add the system environment
variables and have them take effect without having to first reboot the
machine.
* Implemented cascading configuration files.
* Changed the default value for the wrapper.java.initmemory property to be 3Mb.
The default on Windows and Linux JVMs is 2Mb, but the Solaris JVM requires
a minimum of 3Mb. The minimum value accepted by the Wrapper was changed
from 8Mb to 1Mb to make it possible to reduce the footprint of applications
to what is possible without using the wrapper.
* Improve the parsing of configuration files so that leading and trailing white
space is now correctly trimmed. It is also now possible to have comments at
the end of a line containing a property.
* Modify the way exceptions thrown by an application's main method are
presented to the user by the WrapperSimpleApp and WrapperStartStopApp so
they no longer look like a problem with Wrapper configuration.
2.2.9
* Added a new property, wrapperper.restart.delay, which allows the user to control
the amount of time to pause between a JVM exiting and a new JVM being
launched.
* Fixed bug #611024. The Wrapper would sometimes fail to start if
wrapper.max_failed_invocations is set to 1.
* Fix a problem where the number of non-daemon threads was not being calculated
in some cases.
* Implemented feature request #491443. Environment variables referenced in the
wrapper.conf file will now be evaluated as the file is loaded. The windows
syntax for environment variables is used on all platforms to make them
platform independent.
* Fixed a problem where the wrapper.conf was being open with both read and
write locks when a read lock is all that is needed. Made the wrapper fail
on startup if another application held a read lock on the conf file.
* Modified the message displayed when the native library could not be found,
so that it is much more descriptive. Hopefully it will cut down on questions
caused by configuration problems.
* Implemented feature request #613539. Modified the wrapper.java.library.path
to function like the wrapper.java.classpath.n properties so that multiple
directories can be specified in the library path in a platform independent
way. The old property is still supported, but deprecated.
* Fix Bug #632215. The WrapperManager.isLaunchedAsService() method was always
returning false, even when run as a service under Windows. On linux, the
Wrapper is always run as a console app, so this method will always return
false.
* Improve the message thrown when user code attempts to access System.in from
within a JVM being controlled by the Wrapper. System.in will not work
because the JVM is a spawned process.
2.2.8
* Fixed a compiler problem on Solaris some systems.
* Added a new property, wrapper.cpu.timeout, which allows the user to control
how much time without receiving any CPU the Wrapper will tolerate before
displaying a warning message. The CPU timeout feature was added in 2.2.7
but the default timeout of 10 seconds was not configurable.
* The Wrapper was only allowing 5 seconds between the JVM informing the
Wrapper that it was going to exit and the JVM process actually exiting.
This would cause the Wrapper to terminate the process prematurely in
cases where an application shutdown thread took longer than 5 seconds to
complete. The Wrapper now allows wrapper.jvm_exit.timeout seconds for
the JVM process to exit on its own before being forcibly terminated.
* When there is a configuration problem or a resource is unavailable, a JVM
will sometimes exit abnormally very shortly after being launched. This
can lead the the JVM being infinitely restarted due to a simple class
path misconfiguration. To work around this, the Wrapper has always had
a hard limit of 5 restarts within a short period of time. If the JVM
has been running for more than a few minutes, then the count was reset.
In this version, a new property. wrapper.max_failed_invocations was added
to allow the max value to be set. The time period which the JVM must
now be running for the JVM launch to have been considered a success for
restart purposes is set using the new wrapper.successful_invocation_time
property.
* The number of advanced properties which most users do not need has been
increasing as the Wrapper has been made more and more flexible. This
has been causing confusion in their usage by people who play with them
without first reading the documentation. To solve this, the advanced
properties were removed from the default configuration file. They still
function. But users must now read to the advanced configuration
documentation to learn about their existence. Added quite about to the
descriptions of these properties to hopefully clear up any confusion
about their usage.
* When the JVM exits abnormally, the Wrapper will pause for a few seconds
before starting another JVM. If the user pressed CTRL-C during this
pause, a new JVM would still be launched. The new JVM was exiting
immediately but it was a waste of time. The Wrapper now recognizes the
event and aborts launching the new JVM.
* Added a page to the documentation which shows inline javadocs. This
will hopefully make it easier to navigate them as part of the full
documentation set.
* Added a new method to the WrapperManager which enables user code to
log at any log level.
* Added a new Helper class WrapperStartStopApp which allows users to easily
integrate applications like Tomcat which use a separate class to stop
the application.
* Added a samples section to the documentation. Just includes Tomcat 4
for now.
2.2.7
* Fix a problem where the JVM was trying to reconnect the Wrapper as it was
being shutdown. This was causing problems if the JVM was being restarted.
* Added support for the system being suspended to RAM or disk. Also improved
wrapper performance when a system is under 100% load. See the new example
output in the example section.
* Fix a problem where the log output was not being directed to a file called
wrapper.log in the same directory as the Wrapper binary in the event that the
configured wrapper log file could not be accessed.
* Fix a problem where the Wrapper was not shutting down the JVM correctly when
all non daemon threads completed. Normally a JVM will exit when all of its
non daemon threads have completed so this was causing some problems.
(Thanks to Jung Tamas)
* Added the ability to set the priority of the Wrapper and its JVM when run
as an NT service or console application. The same thing can be better
achieved on Unix systems by using "nice" in the shell script used to launch
the Wrapper. See the documentation for for details.
* JVM information was not being displayed correctly when the Wrapper native
library could not be loaded.
* Added a new property to cause the wrapper to attempt to request a thread dump
when the JVM does not exit on request.
* Improved the documentation of the WrapperSimpleApp and WrapperListener
classes.
* Adding a new property wrapper.shutdown.timeout to allow the user to extend
the length of time that an application is allowed to take shutting down.
* Rework the way the shutdown process works so that System.exit will never be
called before the stop method in WrapperListener has had a chance to complete.
* Add a Restart button to the TestWrapper application.
* Fix a problem on Unix versions where '%' characters in Java output would
sometimes cause the wrapper to crash. Somehow missed getting this into the
last release.
* Added a test to make sure that WrapperManager.stop is not called recursively.
* Added support for building under Windows XP. Prebuilt installations had
already been working.
2.2.6
* Fix a problem where '%' characters in Java output would sometimes cause the
wrapper to crash. (Thanks to Frode Moe)
* Added support for requesting a Java thread dump without shutting down the
Java process.
* Fixed a problem on windows where the java command was looking in the windows
system and system32 directories for the java executable before checking the
path when the full path to the java executable was not specified in the
configuration file. This could lead to different JVM being run from the
Wrapper than was run if java -version was run from the command line. The
Wrapper will now attempt to resolve the full java path using the PATH
environment variable.
* Added debug output showing Java version information when the JVM first
starts.
* Modified c source to use /* */ style comments rather than // style comments.
Some people were having problems with some compilers.
2.2.5
* Added support for service descriptions for Win2k and XP.
* Fixed bug issue when reading configuration files from Windows on Unix.
* Deprecated the wrapper.debug property in favor of loglevels.
* Added new logger functionality includes the following features:
Loglevels like Log4j, NT Eventlog support, UNIX syslog support and rolling
log files.
* Added wildcard support for classpath entries in wrapper.conf.
* Added the ability to specify configuration properties from the command line.
* Changed the way NT services are installed so that a patched version of the
Wrapper.exe file no longer needs to be created to reference the
wrapper.conf file.
2.2.4
* The value of APP_NAME in the bash or sh scripts no longer needs to be the
same as the script.
* Added the ability to format and/or disable file logging and output to the
console.
* Set mode of executables in binary release tar files so that they can be run
without modification after being extracted.
* Fixed line feeds in release so that bat files are always CRLF, unix scripts
are always LF. Other source files are always CRLF in ZIP archives and LF
in tar.gz archives.
* Make the build fail if Wrapper.exe or Wrapper.dll do not exist for Windows
builds.
* Added an empty wrapper.log to the releases so that the TestWrapper example
program runs out of the box.
2.2.3
* Added template scripts and conf files for ease of integration with other
applications.
* Cleaned up the build.
* The WrapperSimpleApp method of launchine applications was not working
correctly with applications whose main method did not return.
* Add sample scripts and wrapper.conf files in the bin and lib directories.
These scripts are used to start a sample application which runs out of the
box. See the new example.html page in the documentation for more details.
* Get rid of the platform specific directories in the bin and lib directories.
* Enable relative paths for Windows version. In previous versions of Wrapper,
it was necessary to always use absolute paths because the working directory
of the wrapper would be then NT System32 directory when run as a service.
* On the windows version, the wrapper always sets the current working
directory to the location of the wrapper executable immediately after
startup.
* Improvements to the documentation / web page.
2.2.2
* Added HTML based documentation.
2.2.1
* Added Linux and Solaris build files.
* Added Linux and Solaris documentation.
2.2.0
* Initial Public Release.
wrapper_3.5.22_src/doc/wrapper-community-license-1.1.txt 100644 0 0 47625 12224722016 20324 0 ustar 0 0 ----------------------------------------------------------------------
----------------- -----------------
Tanuki Software, Ltd.
Community Software License Agreement
Version 1.1
IMPORTANT-READ CAREFULLY: This license agreement is a legal agreement
between you ("Licensee") and Tanuki Software, Ltd. ("TSI"), which
includes computer software, associated media, printed materials, and
may include online or electronic documentation ( Software ). PLEASE
READ THIS AGREEMENT CAREFULLY BEFORE YOU INSTALL, COPY, DOWNLOAD OR
USE THE SOFTWARE ACCOMPANYING THIS PACKAGE.
Section 1 - Grant of License
Community editions of the Software are made available on the GNU
General Public License, Version 2 ("GPLv2"), included in Section 4 of
this license document. All sections of the Community Software License
Agreement must be complied with in addition to those of the GPLv2.
Section 2 - Definitions
2.1. "Community Edition" shall mean versions of the Software Program
distributed in source form under this license agreement, and all new
releases, corrections, enhancements and updates to the Software
Program, which TSI makes generally available under this agreement.
2.2. "Documentation" shall mean the contents of the website
describing the functionality and use of the Software Program, located
at http://wrapper.tanukisoftware.org
2.3. "Product" shall mean the computer programs, that are provided by
Licensee to Licensee customers or potential customers, and that
contain both the Software Program as a component of the Product, and a
component or components (other than the Software Program) that provide
the material functionality of the Product. If the Product is released
in source form, the Software Program or any of its components may only
be included in executable form.
2.4. "Software Program" shall mean the computer software and license
file provided by TSI under this Agreement, including all new releases,
corrections, enhancements and updates to such computer software, which
TSI makes generally available and which Licensee receive pursuant to
Licensee subscription to TSIMS. Some specific features or platforms
may not be enabled if they do not fall under the feature set(s)
covered by the specific license fees paid.
2.5 "End User" shall mean the customers of the Licensee or any
recipient of the Product whether or not any payment is made to use
the Product.
Section 3 - Licensee Obligations
A copy of this license must be distributed in full with the Product
in a location that is obvious to any End User.
In accordance with Section 4, the full source code of all components
of the Product must be made available to any and all End Users.
Licensee may extend and/or modify the Software Program and distribute
under the terms of this agreement provided that the copyright notice
and license information displayed in the console and log files are
not obfuscated or obstructed in any way.
Section 4 - GPLv2 License Agreement
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
Everyone is permitted to copy and distribute verbatim copies of
this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General
Public License is intended to guarantee your freedom to share and
change free software--to make sure the software is free for all
its users. This General Public License applies to most of the Free
Software Foundation's software and to any other program whose
authors commit to using it. (Some other Free Software Foundation
software is covered by the GNU Library General Public License
instead.) You can apply it to your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and
charge for this service if you wish), that you receive source code
or can get it if you want it, that you can change the software or
use pieces of it in new free programs; and that you know you can
do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the
rights. These restrictions translate to certain responsibilities
for you if you distribute copies of the software, or if you modify
it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights
that you have. You must make sure that they, too, receive or can
get the source code. And you must show them these terms so they
know their rights.
We protect your rights with two steps:
(1) copyright the software, and
(2) offer you this license which gives you legal permission to
copy, distribute and/or modify the software.
Also, for each author's protection and ours, we want to make
certain that everyone understands that there is no warranty for
this free software. If the software is modified by someone else
and passed on, we want its recipients to know that what they have
is not the original, so that any problems introduced by others
will not reflect on the original authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making
the program proprietary. To prevent this, we have made it clear
that any patent must be licensed for everyone's free use or not
licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which
contains a notice placed by the copyright holder saying it may be
distributed under the terms of this General Public License. The
"Program", below, refers to any such program or work, and a "work
based on the Program" means either the Program or any derivative
work under copyright law: that is to say, a work containing the
Program or a portion of it, either verbatim or with modifications
and/or translated into another language. (Hereinafter, translation
is included without limitation in the term "modification".) Each
licensee is addressed as "you".
Activities other than copying, distribution and modification are
not covered by this License; they are outside its scope. The act
of running the Program is not restricted, and the output from the
Program is covered only if its contents constitute a work based on
the Program (independent of having been made by running the
Program). Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep
intact all the notices that refer to this License and to the
absence of any warranty; and give any other recipients of the
Program a copy of this License along with the Program.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange
for a fee.
2. You may modify your copy or copies of the Program or any
portion of it, thus forming a work based on the Program, and copy
and distribute such modifications or work under the terms of
Section 1 above, provided that you also meet all of these
conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but does
not normally print such an announcement, your work based on the
Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the
Program, and can be reasonably considered independent and separate
works in themselves, then this License, and its terms, do not
apply to those sections when you distribute them as separate works.
But when you distribute the same sections as part of a whole which
is a work based on the Program, the distribution of the whole must
be on the terms of this License, whose permissions for other
licensees extend to the entire whole, and thus to each and every
part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or
contest your rights to work written entirely by you; rather, the
intent is to exercise the right to control the distribution of
derivative or collective works based on the Program.
In addition, mere aggregation of another work not based on the
Program with the Program (or with a work based on the Program) on
a volume of a storage or distribution medium does not bring the
other work under the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms
of Sections 1 and 2 above provided that you also do one of the
following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software
interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work
for making modifications to it. For an executable work, complete
source code means all the source code for all modules it contains,
plus any associated interface definition files, plus the scripts
used to control compilation and installation of the executable.
However, as a special exception, the source code distributed need
not include anything that is normally distributed (in either
source or binary form) with the major components (compiler,
kernel, and so on) of the operating system on which the executable
runs, unless that component itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this
License. However, parties who have received copies, or rights,
from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify
or distribute the Program or its derivative works. These actions
are prohibited by law if you do not accept this License.
Therefore, by modifying or distributing the Program (or any work
based on the Program), you indicate your acceptance of this
License to do so, and all its terms and conditions for copying,
distributing or modifying the Program or works based on it.
6. Each time you redistribute the Program (or any work based on
the Program), the recipient automatically receives a license from
the original licensor to copy, distribute or modify the Program
subject to these terms and conditions. You may not impose any
further restrictions on the recipients' exercise of the rights
granted herein. You are not responsible for enforcing compliance
by third parties to this License.
7. If, as a consequence of a court judgment or allegation of
patent infringement or for any other reason (not limited to
patent issues), conditions are imposed on you (whether by court
order, agreement or otherwise) that contradict the conditions of
this License, they do not excuse you from the conditions of this
License. If you cannot distribute so as to satisfy simultaneously
your obligations under this License and any other pertinent
obligations, then as a consequence you may not distribute the
Program at all. For example, if a patent license would not permit
royalty-free redistribution of the Program by all those who
receive copies directly or indirectly through you, then the only
way you could satisfy both it and this License would be to refrain
entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable
under any particular circumstance, the balance of the section is
intended to apply and the section as a whole is intended to apply
in other circumstances.
It is not the purpose of this section to induce you to infringe
any patents or other property right claims or to contest validity
of any such claims; this section has the sole purpose of
protecting the integrity of the free software distribution system,
which is implemented by public license practices. Many people have
made generous contributions to the wide range of software
distributed through that system in reliance on consistent
application of that system; it is up to the author/donor to decide
if he or she is willing to distribute software through any other
system and a licensee cannot impose that choice.
This section is intended to make thoroughly clear what is believed
to be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces,
the original copyright holder who places the Program under this
License may add an explicit geographical distribution limitation
excluding those countries, so that distribution is permitted only
in or among countries not thus excluded. In such case, this
License incorporates the limitation as if written in the body of
this License.
9. The Free Software Foundation may publish revised and/or new
versions of the General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies a version number of this License which applies
to it and "any later version", you have the option of following
the terms and conditions either of that version or of any later
version published by the Free Software Foundation. If the Program
does not specify a version number of this License, you may choose
any version ever published by the Free Software Foundation.
10. If you wish to incorporate parts of the Program into other
free programs whose distribution conditions are different, write
to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free
status of all derivatives of our free software and of promoting
the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE
LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS
AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND
PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE
DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR
OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY
MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE
LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL,
INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR
INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU
OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY
OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN
ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
Section 5 - 3rd Party Components
(1) The Software Program includes software and documentation components
developed in part by Silver Egg Technology, Inc.("SET") prior to 2001
and released under the following license.
Copyright (c) 2001 Silver Egg Technology
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sub-license, and/or
sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
wrapper_3.5.22_src/src/bin/App.bat.in 100644 0 0 10356 12224722010 14534 0 ustar 0 0 @echo off
setlocal
rem
rem Copyright (c) 1999, 2013 Tanuki Software, Ltd.
rem http://www.tanukisoftware.com
rem All rights reserved.
rem
rem This software is the proprietary information of Tanuki Software.
rem You shall use it only in accordance with the terms of the
rem license agreement you entered into with Tanuki Software.
rem http://wrapper.tanukisoftware.com/doc/english/licenseOverview.html
rem
rem Java Service Wrapper general passthrough startup script.
rem
rem -----------------------------------------------------------------------------
rem These settings can be modified to fit the needs of your application
rem Optimized for use with version 3.5.22 of the Wrapper.
rem The base name for the Wrapper binary.
set _WRAPPER_BASE=wrapper
rem The directory where the Wrapper binary (.exe) file is located, this can be
rem either a absolute or relative path. If the path contains any special characters,
rem please make sure to quote the variable.
set _WRAPPER_DIR=
rem The name and location of the Wrapper configuration file. This will be used
rem if the user does not specify a configuration file as the first parameter to
rem this script. It will not be possible to specify a configuration file on the
rem command line if _PASS_THROUGH is set.
rem If a relative path is specified, please note that the location is based on the
rem location.
set _WRAPPER_CONF_DEFAULT="../conf/%_WRAPPER_BASE%.conf"
rem Makes it possible to override the Wrapper configuration file by specifying it
rem as the first parameter.
rem set _WRAPPER_CONF_OVERRIDE=true
rem _PASS_THROUGH tells the script to pass all parameters through to the JVM as
rem is.
rem set _PASS_THROUGH=true
rem Do not modify anything beyond this point
rem -----------------------------------------------------------------------------
rem
rem Resolve the real path of the wrapper.exe
rem For non NT systems, the _REALPATH and _WRAPPER_CONF values
rem can be hard-coded below and the following test removed.
rem
if "%OS%"=="Windows_NT" goto nt
echo This script only works with NT-based versions of Windows.
goto :eof
:nt
rem Find the application home.
rem if no path path specified do the default action
IF not DEFINED _WRAPPER_DIR goto dir_undefined
set _WRAPPER_DIR_QUOTED="%_WRAPPER_DIR:"=%"
if not "%_WRAPPER_DIR:~-2,1%" == "\" set _WRAPPER_DIR_QUOTED="%_WRAPPER_DIR_QUOTED:"=%\"
rem check if absolute path
if "%_WRAPPER_DIR_QUOTED:~2,1%" == ":" goto absolute_path
if "%_WRAPPER_DIR_QUOTED:~1,1%" == "\" goto absolute_path
rem everythig else means relative path
set _REALPATH="%~dp0%_WRAPPER_DIR_QUOTED:"=%"
goto pathfound
:dir_undefined
rem Use a relative path to the wrapper %~dp0 is location of current script under NT
set _REALPATH="%~dp0"
goto pathfound
:absolute_path
rem Use an absolute path to the wrapper
set _REALPATH="%_WRAPPER_DIR_QUOTED:"=%"
:pathfound
rem
rem Decide on the specific Wrapper binary to use (See delta-pack)
rem
if "%PROCESSOR_ARCHITEW6432%"=="AMD64" goto amd64
if "%PROCESSOR_ARCHITECTURE%"=="AMD64" goto amd64
if "%PROCESSOR_ARCHITECTURE%"=="IA64" goto ia64
set _WRAPPER_L_EXE="%_REALPATH:"=%%_WRAPPER_BASE%-windows-x86-32.exe"
goto search
:amd64
set _WRAPPER_L_EXE="%_REALPATH:"=%%_WRAPPER_BASE%-windows-x86-64.exe"
goto search
:ia64
set _WRAPPER_L_EXE="%_REALPATH:"=%%_WRAPPER_BASE%-windows-ia-64.exe"
goto search
:search
set _WRAPPER_EXE="%_WRAPPER_L_EXE:"=%"
if exist %_WRAPPER_EXE% goto conf
set _WRAPPER_EXE="%_REALPATH:"=%%_WRAPPER_BASE%.exe"
if exist %_WRAPPER_EXE% goto conf
echo Unable to locate a Wrapper executable using any of the following names:
echo %_WRAPPER_L_EXE%
echo %_WRAPPER_EXE%
pause
goto :eof
rem
rem Find the wrapper.conf
rem
:conf
if not [%_WRAPPER_CONF_OVERRIDE%]==[] (
set _WRAPPER_CONF="%~f1"
if not [%_WRAPPER_CONF%]==[""] (
shift
goto :startup
)
)
set _WRAPPER_CONF="%_WRAPPER_CONF_DEFAULT:"=%"
rem
rem Start the Wrapper
rem
:startup
rem Collect an parameters
:parameters
set _PARAMETERS=%_PARAMETERS% %1
shift
if not [%1]==[] goto :parameters
if [%_PASS_THROUGH%]==[] (
%_WRAPPER_EXE% -c %_WRAPPER_CONF%
) else (
%_WRAPPER_EXE% -c %_WRAPPER_CONF% -- %_PARAMETERS%
)
if not errorlevel 1 goto :eof
pause
wrapper_3.5.22_src/src/bin/AppCommand.bat.in 100644 0 0 13175 12224722010 16035 0 ustar 0 0 @echo off
setlocal
rem
rem Copyright (c) 1999, 2013 Tanuki Software, Ltd.
rem http://www.tanukisoftware.com
rem All rights reserved.
rem
rem This software is the proprietary information of Tanuki Software.
rem You shall use it only in accordance with the terms of the
rem license agreement you entered into with Tanuki Software.
rem http://wrapper.tanukisoftware.com/doc/english/licenseOverview.html
rem
rem Java Service Wrapper command based script.
rem
rem -----------------------------------------------------------------------------
rem These settings can be modified to fit the needs of your application
rem Optimized for use with version 3.5.22 of the Wrapper.
rem The base name for the Wrapper binary.
set _WRAPPER_BASE=wrapper
rem The directory where the Wrapper binary (.exe) file is located, this can be
rem either a absolute or relative path. If the path contains any special characters,
rem please make sure to quote the variable.
set _WRAPPER_DIR=
rem The name and location of the Wrapper configuration file. This will be used
rem if the user does not specify a configuration file as the first parameter to
rem this script. It will not be possible to specify a configuration file on the
rem command line if _PASS_THROUGH is set.
rem If a relative path is specified, please note that the location is based on the
rem location.
set _WRAPPER_CONF="../conf/%_WRAPPER_BASE%.conf"
rem _FIXED_COMMAND tells the script to use a hard coded command rather than
rem expecting the first parameter of the command line to be the command.
rem By default the command will will be expected to be the first parameter.
rem set _FIXED_COMMAND=console
rem _PASS_THROUGH tells the script to pass all parameters through to the JVM
rem as is. If _FIXED_COMMAND is specified then all parameters will be passed.
rem If not set then all parameters starting with the second will be passed.
set _PASS_THROUGH=true
rem Do not modify anything beyond this point
rem -----------------------------------------------------------------------------
if "%OS%"=="Windows_NT" goto nt
echo This script only works with NT-based versions of Windows.
goto :eof
:nt
rem Find the application home.
rem if no path path specified do the default action
IF not DEFINED _WRAPPER_DIR goto dir_undefined
set _WRAPPER_DIR_QUOTED="%_WRAPPER_DIR:"=%"
if not "%_WRAPPER_DIR:~-2,1%" == "\" set _WRAPPER_DIR_QUOTED="%_WRAPPER_DIR_QUOTED:"=%\"
rem check if absolute path
if "%_WRAPPER_DIR_QUOTED:~2,1%" == ":" goto absolute_path
if "%_WRAPPER_DIR_QUOTED:~1,1%" == "\" goto absolute_path
rem everythig else means relative path
set _REALPATH="%~dp0%_WRAPPER_DIR_QUOTED:"=%"
goto pathfound
:dir_undefined
rem Use a relative path to the wrapper %~dp0 is location of current script under NT
set _REALPATH="%~dp0"
goto pathfound
:absolute_path
rem Use an absolute path to the wrapper
set _REALPATH="%_WRAPPER_DIR_QUOTED:"=%"
:pathfound
rem
rem Decide on the specific Wrapper binary to use (See delta-pack)
rem
if "%PROCESSOR_ARCHITEW6432%"=="AMD64" goto amd64
if "%PROCESSOR_ARCHITECTURE%"=="AMD64" goto amd64
if "%PROCESSOR_ARCHITECTURE%"=="IA64" goto ia64
set _WRAPPER_L_EXE="%_REALPATH:"=%%_WRAPPER_BASE%-windows-x86-32.exe"
goto search
:amd64
set _WRAPPER_L_EXE="%_REALPATH:"=%%_WRAPPER_BASE%-windows-x86-64.exe"
goto search
:ia64
set _WRAPPER_L_EXE="%_REALPATH:"=%%_WRAPPER_BASE%-windows-ia-64.exe"
goto search
:search
set _WRAPPER_EXE="%_WRAPPER_L_EXE:"=%"
if exist %_WRAPPER_EXE% goto conf
set _WRAPPER_EXE="%_REALPATH:"=%%_WRAPPER_BASE%.exe"
if exist %_WRAPPER_EXE% goto conf
echo Unable to locate a Wrapper executable using any of the following names:
echo %_WRAPPER_L_EXE%
echo %_WRAPPER_EXE%
pause
goto :eof
:conf
if not [%_FIXED_COMMAND%]==[] (
set _COMMAND=%_FIXED_COMMAND%
) else (
set _COMMAND=%1
shift
)
rem Collect all parameters
:parameters
set _PARAMETERS=%_PARAMETERS% %1
shift
if not [%1]==[] goto parameters
:callcommand
rem
rem Run the application.
rem At runtime, the current directory will be that of wrapper.exe
rem
set _MATCHED=true
if [%_COMMAND%]==[console] (
if [%_PASS_THROUGH%]==[] (
%_WRAPPER_EXE% -c "%_WRAPPER_CONF%" %_PARAMETERS%
) else (
%_WRAPPER_EXE% -c "%_WRAPPER_CONF%" -- %_PARAMETERS%
)
) else if [%_COMMAND%]==[start] (
call :start
) else if [%_COMMAND%]==[stop] (
call :stop
) else if [%_COMMAND%]==[install] (
if [%_PASS_THROUGH%]==[] (
%_WRAPPER_EXE% -i "%_WRAPPER_CONF%" %_PARAMETERS%
) else (
%_WRAPPER_EXE% -i "%_WRAPPER_CONF%" -- %_PARAMETERS%
)
) else if [%_COMMAND%]==[pause] (
%_WRAPPER_EXE% -a "%_WRAPPER_CONF%"
) else if [%_COMMAND%]==[resume] (
%_WRAPPER_EXE% -e "%_WRAPPER_CONF%"
) else if [%_COMMAND%]==[status] (
%_WRAPPER_EXE% -q "%_WRAPPER_CONF%"
) else if [%_COMMAND%]==[remove] (
%_WRAPPER_EXE% -r "%_WRAPPER_CONF%"
) else if [%_COMMAND%]==[restart] (
call :stop
call :start
) else (
set _MATCHED=
goto showusage
)
if errorlevel 1 (
if [%_MATCHED%]==[] goto showusage
)
goto :eof
:showusage
rem A command was not specified, or it was now known.
if not [%_COMMAND%]==[] (
echo Unknown command: %_COMMAND%
echo.
)
if [%_PASS_THROUGH%]==[] (
echo Usage: %0 [ console : start : pause : resume : stop : restart : install : remove : status ]
) else (
echo Usage: %0 [ console {JavaAppArgs} : start : pause : resume : stop : restart : install {JavaAppArgs} : remove : status ]
)
pause
goto :eof
:start
%_WRAPPER_EXE% -t "%_WRAPPER_CONF%"
goto :eof
:stop
%_WRAPPER_EXE% -p "%_WRAPPER_CONF%"
goto :eof
wrapper_3.5.22_src/src/bin/AppNoWrapper.bat.in 100644 0 0 2032 12224722010 16342 0 ustar 0 0 @echo off
setlocal
rem
rem Copyright (c) 1999, 2013 Tanuki Software, Ltd.
rem http://www.tanukisoftware.com
rem All rights reserved.
rem
rem This software is the proprietary information of Tanuki Software.
rem You shall use it only in accordance with the terms of the
rem license agreement you entered into with Tanuki Software.
rem http://wrapper.tanukisoftware.com/doc/english/licenseOverview.html
rem
rem This script is an example of how to run your application without the Wrapper, but with the
rem Wrapper helper classes. You can obtain the actual command generated by the wrapper for
rem your application by running the Wrapper with the wrapper.java.command.loglevel=INFO
rem property set.
rem
rem The wrapper.key property MUST be removed from the resulting command or it will fail to
rem run correctly.
java -Xms16m -Xmx64m -Djava.library.path="../lib" -Djava.class.path="../lib/wrapper.jar;../lib/wrappertest.jar" -Dwrapper.native_library="wrapper" -Dwrapper.debug="TRUE" org.tanukisoftware.wrapper.test.Main
wrapper_3.5.22_src/src/bin/AppTemplate.bat.in 100644 0 0 10420 12224722010 16220 0 ustar 0 0 @echo off
setlocal
rem
rem Copyright (c) 1999, 2013 Tanuki Software, Ltd.
rem http://www.tanukisoftware.com
rem All rights reserved.
rem
rem This software is the proprietary information of Tanuki Software.
rem You shall use it only in accordance with the terms of the
rem license agreement you entered into with Tanuki Software.
rem http://wrapper.tanukisoftware.com/doc/english/licenseOverview.html
rem
rem Java Service Wrapper general startup script.
rem
rem -----------------------------------------------------------------------------
rem These settings can be modified to fit the needs of your application
rem Optimized for use with version 3.5.22 of the Wrapper.
rem The base name for the Wrapper binary.
set _WRAPPER_BASE=wrapper
rem The directory where the Wrapper binary (.exe) file is located, this can be
rem either a absolute or relative path. If the path contains any special characters,
rem please make sure to quote the variable.
set _WRAPPER_DIR=
rem The name and location of the Wrapper configuration file. This will be used
rem if the user does not specify a configuration file as the first parameter to
rem this script. It will not be possible to specify a configuration file on the
rem command line if _PASS_THROUGH is set.
rem If a relative path is specified, please note that the location is based on the
rem location.
set _WRAPPER_CONF_DEFAULT="../conf/%_WRAPPER_BASE%.conf"
rem Makes it possible to override the Wrapper configuration file by specifying it
rem as the first parameter.
rem set _WRAPPER_CONF_OVERRIDE=true
rem Note that it is only possible to pass parameters through to the JVM when
rem installing the service, or when running in a console.
rem Do not modify anything beyond this point
rem -----------------------------------------------------------------------------
rem
rem Resolve the real path of the wrapper.exe
rem For non NT systems, the _REALPATH and _WRAPPER_CONF values
rem can be hard-coded below and the following test removed.
rem
if "%OS%"=="Windows_NT" goto nt
echo This script only works with NT-based versions of Windows.
goto :eof
:nt
rem Find the application home.
rem if no path path specified do the default action
IF not DEFINED _WRAPPER_DIR goto dir_undefined
set _WRAPPER_DIR_QUOTED="%_WRAPPER_DIR:"=%"
if not "%_WRAPPER_DIR:~-2,1%" == "\" set _WRAPPER_DIR_QUOTED="%_WRAPPER_DIR_QUOTED:"=%\"
rem check if absolute path
if "%_WRAPPER_DIR_QUOTED:~2,1%" == ":" goto absolute_path
if "%_WRAPPER_DIR_QUOTED:~1,1%" == "\" goto absolute_path
rem everythig else means relative path
set _REALPATH="%~dp0%_WRAPPER_DIR_QUOTED:"=%"
goto pathfound
:dir_undefined
rem Use a relative path to the wrapper %~dp0 is location of current script under NT
set _REALPATH="%~dp0"
goto pathfound
:absolute_path
rem Use an absolute path to the wrapper
set _REALPATH="%_WRAPPER_DIR_QUOTED:"=%"
:pathfound
rem
rem Decide on the specific Wrapper binary to use (See delta-pack)
rem
if "%PROCESSOR_ARCHITEW6432%"=="AMD64" goto amd64
if "%PROCESSOR_ARCHITECTURE%"=="AMD64" goto amd64
if "%PROCESSOR_ARCHITECTURE%"=="IA64" goto ia64
set _WRAPPER_L_EXE="%_REALPATH:"=%%_WRAPPER_BASE%-windows-x86-32.exe"
goto search
:amd64
set _WRAPPER_L_EXE="%_REALPATH:"=%%_WRAPPER_BASE%-windows-x86-64.exe"
goto search
:ia64
set _WRAPPER_L_EXE="%_REALPATH:"=%%_WRAPPER_BASE%-windows-ia-64.exe"
goto search
:search
set _WRAPPER_EXE="%_WRAPPER_L_EXE:"=%"
if exist %_WRAPPER_EXE% goto conf
set _WRAPPER_EXE="%_REALPATH:"=%%_WRAPPER_BASE%.exe"
if exist %_WRAPPER_EXE% goto conf
echo Unable to locate a Wrapper executable using any of the following names:
echo %_WRAPPER_L_EXE%
echo %_WRAPPER_EXE%
pause
goto :eof
rem
rem Find the wrapper.conf
rem
:conf
if not [%_WRAPPER_CONF_OVERRIDE%]==[] (
set _WRAPPER_CONF="%~f1"
if not [%_WRAPPER_CONF%]==[""] (
shift
goto :startup
)
)
set _WRAPPER_CONF="%_WRAPPER_CONF_DEFAULT:"=%"
rem
rem Start the Wrapper
rem
:startup
rem Collect an parameters
:parameters
set _PARAMETERS=%_PARAMETERS% %1
shift
if not [%1]==[] goto :parameters
if [%_PASS_THROUGH%]==[] (
%_WRAPPER_EXE% @wrapper.command@ %_WRAPPER_CONF%
) else (
%_WRAPPER_EXE% @wrapper.command@ %_WRAPPER_CONF% -- %_PARAMETERS%
)
if not errorlevel 1 goto :eof
pause
wrapper_3.5.22_src/src/bin/AppTemplatePassThrough.bat.in 100644 0 0 10414 12224722010 20413 0 ustar 0 0 @echo off
setlocal
rem
rem Copyright (c) 1999, 2013 Tanuki Software, Ltd.
rem http://www.tanukisoftware.com
rem All rights reserved.
rem
rem This software is the proprietary information of Tanuki Software.
rem You shall use it only in accordance with the terms of the
rem license agreement you entered into with Tanuki Software.
rem http://wrapper.tanukisoftware.com/doc/english/licenseOverview.html
rem
rem Java Service Wrapper general passthrough startup script.
rem
rem -----------------------------------------------------------------------------
rem These settings can be modified to fit the needs of your application
rem Optimized for use with version 3.5.22 of the Wrapper.
rem The base name for the Wrapper binary.
set _WRAPPER_BASE=wrapper
rem The directory where the Wrapper binary (.exe) file is located, this can be
rem either a absolute or relative path. If the path contains any special characters,
rem please make sure to quote the variable.
set _WRAPPER_DIR=
rem The name and location of the Wrapper configuration file. This will be used
rem if the user does not specify a configuration file as the first parameter to
rem this script. It will not be possible to specify a configuration file on the
rem command line if _PASS_THROUGH is set.
rem If a relative path is specified, please note that the location is based on the
rem location.
set _WRAPPER_CONF_DEFAULT="../conf/%_WRAPPER_BASE%.conf"
rem Makes it possible to override the Wrapper configuration file by specifying it
rem as the first parameter.
rem set _WRAPPER_CONF_OVERRIDE=true
rem _PASS_THROUGH tells the script to pass all parameters through to the JVM as
rem is.
rem set _PASS_THROUGH=true
rem Do not modify anything beyond this point
rem -----------------------------------------------------------------------------
rem
rem Resolve the real path of the wrapper.exe
rem For non NT systems, the _REALPATH and _WRAPPER_CONF values
rem can be hard-coded below and the following test removed.
rem
if "%OS%"=="Windows_NT" goto nt
echo This script only works with NT-based versions of Windows.
goto :eof
:nt
rem Find the application home.
rem if no path path specified do the default action
IF not DEFINED _WRAPPER_DIR goto dir_undefined
set _WRAPPER_DIR_QUOTED="%_WRAPPER_DIR:"=%"
if not "%_WRAPPER_DIR:~-2,1%" == "\" set _WRAPPER_DIR_QUOTED="%_WRAPPER_DIR_QUOTED:"=%\"
rem check if absolute path
if "%_WRAPPER_DIR_QUOTED:~2,1%" == ":" goto absolute_path
if "%_WRAPPER_DIR_QUOTED:~1,1%" == "\" goto absolute_path
rem everythig else means relative path
set _REALPATH="%~dp0%_WRAPPER_DIR_QUOTED:"=%"
goto pathfound
:dir_undefined
rem Use a relative path to the wrapper %~dp0 is location of current script under NT
set _REALPATH="%~dp0"
goto pathfound
:absolute_path
rem Use an absolute path to the wrapper
set _REALPATH="%_WRAPPER_DIR_QUOTED:"=%"
:pathfound
rem
rem Decide on the specific Wrapper binary to use (See delta-pack)
rem
if "%PROCESSOR_ARCHITEW6432%"=="AMD64" goto amd64
if "%PROCESSOR_ARCHITECTURE%"=="AMD64" goto amd64
if "%PROCESSOR_ARCHITECTURE%"=="IA64" goto ia64
set _WRAPPER_L_EXE="%_REALPATH:"=%%_WRAPPER_BASE%-windows-x86-32.exe"
goto search
:amd64
set _WRAPPER_L_EXE="%_REALPATH:"=%%_WRAPPER_BASE%-windows-x86-64.exe"
goto search
:ia64
set _WRAPPER_L_EXE="%_REALPATH:"=%%_WRAPPER_BASE%-windows-ia-64.exe"
goto search
:search
set _WRAPPER_EXE="%_WRAPPER_L_EXE:"=%"
if exist %_WRAPPER_EXE% goto conf
set _WRAPPER_EXE="%_REALPATH:"=%%_WRAPPER_BASE%.exe"
if exist %_WRAPPER_EXE% goto conf
echo Unable to locate a Wrapper executable using any of the following names:
echo %_WRAPPER_L_EXE%
echo %_WRAPPER_EXE%
pause
goto :eof
rem
rem Find the wrapper.conf
rem
:conf
if not [%_WRAPPER_CONF_OVERRIDE%]==[] (
set _WRAPPER_CONF="%~f1"
if not [%_WRAPPER_CONF%]==[""] (
shift
goto :startup
)
)
set _WRAPPER_CONF="%_WRAPPER_CONF_DEFAULT:"=%"
rem
rem Start the Wrapper
rem
:startup
rem Collect an parameters
:parameters
set _PARAMETERS=%_PARAMETERS% %1
shift
if not [%1]==[] goto :parameters
if [%_PASS_THROUGH%]==[] (
%_WRAPPER_EXE% @wrapper.command@ %_WRAPPER_CONF%
) else (
%_WRAPPER_EXE% @wrapper.command@ %_WRAPPER_CONF% -- %_PARAMETERS%
)
if not errorlevel 1 goto :eof
pause
wrapper_3.5.22_src/src/bin/InstallApp-NT.bat.in 100644 0 0 10356 12224722010 16402 0 ustar 0 0 @echo off
setlocal
rem
rem Copyright (c) 1999, 2013 Tanuki Software, Ltd.
rem http://www.tanukisoftware.com
rem All rights reserved.
rem
rem This software is the proprietary information of Tanuki Software.
rem You shall use it only in accordance with the terms of the
rem license agreement you entered into with Tanuki Software.
rem http://wrapper.tanukisoftware.com/doc/english/licenseOverview.html
rem
rem Java Service Wrapper general passthrough startup script.
rem
rem -----------------------------------------------------------------------------
rem These settings can be modified to fit the needs of your application
rem Optimized for use with version 3.5.22 of the Wrapper.
rem The base name for the Wrapper binary.
set _WRAPPER_BASE=wrapper
rem The directory where the Wrapper binary (.exe) file is located, this can be
rem either a absolute or relative path. If the path contains any special characters,
rem please make sure to quote the variable.
set _WRAPPER_DIR=
rem The name and location of the Wrapper configuration file. This will be used
rem if the user does not specify a configuration file as the first parameter to
rem this script. It will not be possible to specify a configuration file on the
rem command line if _PASS_THROUGH is set.
rem If a relative path is specified, please note that the location is based on the
rem location.
set _WRAPPER_CONF_DEFAULT="../conf/%_WRAPPER_BASE%.conf"
rem Makes it possible to override the Wrapper configuration file by specifying it
rem as the first parameter.
rem set _WRAPPER_CONF_OVERRIDE=true
rem _PASS_THROUGH tells the script to pass all parameters through to the JVM as
rem is.
rem set _PASS_THROUGH=true
rem Do not modify anything beyond this point
rem -----------------------------------------------------------------------------
rem
rem Resolve the real path of the wrapper.exe
rem For non NT systems, the _REALPATH and _WRAPPER_CONF values
rem can be hard-coded below and the following test removed.
rem
if "%OS%"=="Windows_NT" goto nt
echo This script only works with NT-based versions of Windows.
goto :eof
:nt
rem Find the application home.
rem if no path path specified do the default action
IF not DEFINED _WRAPPER_DIR goto dir_undefined
set _WRAPPER_DIR_QUOTED="%_WRAPPER_DIR:"=%"
if not "%_WRAPPER_DIR:~-2,1%" == "\" set _WRAPPER_DIR_QUOTED="%_WRAPPER_DIR_QUOTED:"=%\"
rem check if absolute path
if "%_WRAPPER_DIR_QUOTED:~2,1%" == ":" goto absolute_path
if "%_WRAPPER_DIR_QUOTED:~1,1%" == "\" goto absolute_path
rem everythig else means relative path
set _REALPATH="%~dp0%_WRAPPER_DIR_QUOTED:"=%"
goto pathfound
:dir_undefined
rem Use a relative path to the wrapper %~dp0 is location of current script under NT
set _REALPATH="%~dp0"
goto pathfound
:absolute_path
rem Use an absolute path to the wrapper
set _REALPATH="%_WRAPPER_DIR_QUOTED:"=%"
:pathfound
rem
rem Decide on the specific Wrapper binary to use (See delta-pack)
rem
if "%PROCESSOR_ARCHITEW6432%"=="AMD64" goto amd64
if "%PROCESSOR_ARCHITECTURE%"=="AMD64" goto amd64
if "%PROCESSOR_ARCHITECTURE%"=="IA64" goto ia64
set _WRAPPER_L_EXE="%_REALPATH:"=%%_WRAPPER_BASE%-windows-x86-32.exe"
goto search
:amd64
set _WRAPPER_L_EXE="%_REALPATH:"=%%_WRAPPER_BASE%-windows-x86-64.exe"
goto search
:ia64
set _WRAPPER_L_EXE="%_REALPATH:"=%%_WRAPPER_BASE%-windows-ia-64.exe"
goto search
:search
set _WRAPPER_EXE="%_WRAPPER_L_EXE:"=%"
if exist %_WRAPPER_EXE% goto conf
set _WRAPPER_EXE="%_REALPATH:"=%%_WRAPPER_BASE%.exe"
if exist %_WRAPPER_EXE% goto conf
echo Unable to locate a Wrapper executable using any of the following names:
echo %_WRAPPER_L_EXE%
echo %_WRAPPER_EXE%
pause
goto :eof
rem
rem Find the wrapper.conf
rem
:conf
if not [%_WRAPPER_CONF_OVERRIDE%]==[] (
set _WRAPPER_CONF="%~f1"
if not [%_WRAPPER_CONF%]==[""] (
shift
goto :startup
)
)
set _WRAPPER_CONF="%_WRAPPER_CONF_DEFAULT:"=%"
rem
rem Start the Wrapper
rem
:startup
rem Collect an parameters
:parameters
set _PARAMETERS=%_PARAMETERS% %1
shift
if not [%1]==[] goto :parameters
if [%_PASS_THROUGH%]==[] (
%_WRAPPER_EXE% -i %_WRAPPER_CONF%
) else (
%_WRAPPER_EXE% -i %_WRAPPER_CONF% -- %_PARAMETERS%
)
if not errorlevel 1 goto :eof
pause
wrapper_3.5.22_src/src/bin/PauseApp-NT.bat.in 100644 0 0 10362 12224722010 16046 0 ustar 0 0 @echo off
setlocal
rem
rem Copyright (c) 1999, 2013 Tanuki Software, Ltd.
rem http://www.tanukisoftware.com
rem All rights reserved.
rem
rem This software is the proprietary information of Tanuki Software.
rem You shall use it only in accordance with the terms of the
rem license agreement you entered into with Tanuki Software.
rem http://wrapper.tanukisoftware.com/doc/english/licenseOverview.html
rem
rem Java Service Wrapper general startup script.
rem
rem -----------------------------------------------------------------------------
rem These settings can be modified to fit the needs of your application
rem Optimized for use with version 3.5.22 of the Wrapper.
rem The base name for the Wrapper binary.
set _WRAPPER_BASE=wrapper
rem The directory where the Wrapper binary (.exe) file is located, this can be
rem either a absolute or relative path. If the path contains any special characters,
rem please make sure to quote the variable.
set _WRAPPER_DIR=
rem The name and location of the Wrapper configuration file. This will be used
rem if the user does not specify a configuration file as the first parameter to
rem this script. It will not be possible to specify a configuration file on the
rem command line if _PASS_THROUGH is set.
rem If a relative path is specified, please note that the location is based on the
rem location.
set _WRAPPER_CONF_DEFAULT="../conf/%_WRAPPER_BASE%.conf"
rem Makes it possible to override the Wrapper configuration file by specifying it
rem as the first parameter.
rem set _WRAPPER_CONF_OVERRIDE=true
rem Note that it is only possible to pass parameters through to the JVM when
rem installing the service, or when running in a console.
rem Do not modify anything beyond this point
rem -----------------------------------------------------------------------------
rem
rem Resolve the real path of the wrapper.exe
rem For non NT systems, the _REALPATH and _WRAPPER_CONF values
rem can be hard-coded below and the following test removed.
rem
if "%OS%"=="Windows_NT" goto nt
echo This script only works with NT-based versions of Windows.
goto :eof
:nt
rem Find the application home.
rem if no path path specified do the default action
IF not DEFINED _WRAPPER_DIR goto dir_undefined
set _WRAPPER_DIR_QUOTED="%_WRAPPER_DIR:"=%"
if not "%_WRAPPER_DIR:~-2,1%" == "\" set _WRAPPER_DIR_QUOTED="%_WRAPPER_DIR_QUOTED:"=%\"
rem check if absolute path
if "%_WRAPPER_DIR_QUOTED:~2,1%" == ":" goto absolute_path
if "%_WRAPPER_DIR_QUOTED:~1,1%" == "\" goto absolute_path
rem everythig else means relative path
set _REALPATH="%~dp0%_WRAPPER_DIR_QUOTED:"=%"
goto pathfound
:dir_undefined
rem Use a relative path to the wrapper %~dp0 is location of current script under NT
set _REALPATH="%~dp0"
goto pathfound
:absolute_path
rem Use an absolute path to the wrapper
set _REALPATH="%_WRAPPER_DIR_QUOTED:"=%"
:pathfound
rem
rem Decide on the specific Wrapper binary to use (See delta-pack)
rem
if "%PROCESSOR_ARCHITEW6432%"=="AMD64" goto amd64
if "%PROCESSOR_ARCHITECTURE%"=="AMD64" goto amd64
if "%PROCESSOR_ARCHITECTURE%"=="IA64" goto ia64
set _WRAPPER_L_EXE="%_REALPATH:"=%%_WRAPPER_BASE%-windows-x86-32.exe"
goto search
:amd64
set _WRAPPER_L_EXE="%_REALPATH:"=%%_WRAPPER_BASE%-windows-x86-64.exe"
goto search
:ia64
set _WRAPPER_L_EXE="%_REALPATH:"=%%_WRAPPER_BASE%-windows-ia-64.exe"
goto search
:search
set _WRAPPER_EXE="%_WRAPPER_L_EXE:"=%"
if exist %_WRAPPER_EXE% goto conf
set _WRAPPER_EXE="%_REALPATH:"=%%_WRAPPER_BASE%.exe"
if exist %_WRAPPER_EXE% goto conf
echo Unable to locate a Wrapper executable using any of the following names:
echo %_WRAPPER_L_EXE%
echo %_WRAPPER_EXE%
pause
goto :eof
rem
rem Find the wrapper.conf
rem
:conf
if not [%_WRAPPER_CONF_OVERRIDE%]==[] (
set _WRAPPER_CONF="%~f1"
if not [%_WRAPPER_CONF%]==[""] (
shift
goto :startup
)
)
set _WRAPPER_CONF="%_WRAPPER_CONF_DEFAULT:"=%"
rem
rem Start the Wrapper
rem
:startup
rem Collect an parameters
:parameters
set _PARAMETERS=%_PARAMETERS% %1
shift
if not [%1]==[] goto :parameters
if [%_PASS_THROUGH%]==[] (
%_WRAPPER_EXE% -a %_WRAPPER_CONF%
) else (
%_WRAPPER_EXE% -a %_WRAPPER_CONF% -- %_PARAMETERS%
)
if not errorlevel 1 goto :eof
pause
wrapper_3.5.22_src/src/bin/QueryApp-NT.bat.in 100644 0 0 10362 12224722010 16076 0 ustar 0 0 @echo off
setlocal
rem
rem Copyright (c) 1999, 2013 Tanuki Software, Ltd.
rem http://www.tanukisoftware.com
rem All rights reserved.
rem
rem This software is the proprietary information of Tanuki Software.
rem You shall use it only in accordance with the terms of the
rem license agreement you entered into with Tanuki Software.
rem http://wrapper.tanukisoftware.com/doc/english/licenseOverview.html
rem
rem Java Service Wrapper general startup script.
rem
rem -----------------------------------------------------------------------------
rem These settings can be modified to fit the needs of your application
rem Optimized for use with version 3.5.22 of the Wrapper.
rem The base name for the Wrapper binary.
set _WRAPPER_BASE=wrapper
rem The directory where the Wrapper binary (.exe) file is located, this can be
rem either a absolute or relative path. If the path contains any special characters,
rem please make sure to quote the variable.
set _WRAPPER_DIR=
rem The name and location of the Wrapper configuration file. This will be used
rem if the user does not specify a configuration file as the first parameter to
rem this script. It will not be possible to specify a configuration file on the
rem command line if _PASS_THROUGH is set.
rem If a relative path is specified, please note that the location is based on the
rem location.
set _WRAPPER_CONF_DEFAULT="../conf/%_WRAPPER_BASE%.conf"
rem Makes it possible to override the Wrapper configuration file by specifying it
rem as the first parameter.
rem set _WRAPPER_CONF_OVERRIDE=true
rem Note that it is only possible to pass parameters through to the JVM when
rem installing the service, or when running in a console.
rem Do not modify anything beyond this point
rem -----------------------------------------------------------------------------
rem
rem Resolve the real path of the wrapper.exe
rem For non NT systems, the _REALPATH and _WRAPPER_CONF values
rem can be hard-coded below and the following test removed.
rem
if "%OS%"=="Windows_NT" goto nt
echo This script only works with NT-based versions of Windows.
goto :eof
:nt
rem Find the application home.
rem if no path path specified do the default action
IF not DEFINED _WRAPPER_DIR goto dir_undefined
set _WRAPPER_DIR_QUOTED="%_WRAPPER_DIR:"=%"
if not "%_WRAPPER_DIR:~-2,1%" == "\" set _WRAPPER_DIR_QUOTED="%_WRAPPER_DIR_QUOTED:"=%\"
rem check if absolute path
if "%_WRAPPER_DIR_QUOTED:~2,1%" == ":" goto absolute_path
if "%_WRAPPER_DIR_QUOTED:~1,1%" == "\" goto absolute_path
rem everythig else means relative path
set _REALPATH="%~dp0%_WRAPPER_DIR_QUOTED:"=%"
goto pathfound
:dir_undefined
rem Use a relative path to the wrapper %~dp0 is location of current script under NT
set _REALPATH="%~dp0"
goto pathfound
:absolute_path
rem Use an absolute path to the wrapper
set _REALPATH="%_WRAPPER_DIR_QUOTED:"=%"
:pathfound
rem
rem Decide on the specific Wrapper binary to use (See delta-pack)
rem
if "%PROCESSOR_ARCHITEW6432%"=="AMD64" goto amd64
if "%PROCESSOR_ARCHITECTURE%"=="AMD64" goto amd64
if "%PROCESSOR_ARCHITECTURE%"=="IA64" goto ia64
set _WRAPPER_L_EXE="%_REALPATH:"=%%_WRAPPER_BASE%-windows-x86-32.exe"
goto search
:amd64
set _WRAPPER_L_EXE="%_REALPATH:"=%%_WRAPPER_BASE%-windows-x86-64.exe"
goto search
:ia64
set _WRAPPER_L_EXE="%_REALPATH:"=%%_WRAPPER_BASE%-windows-ia-64.exe"
goto search
:search
set _WRAPPER_EXE="%_WRAPPER_L_EXE:"=%"
if exist %_WRAPPER_EXE% goto conf
set _WRAPPER_EXE="%_REALPATH:"=%%_WRAPPER_BASE%.exe"
if exist %_WRAPPER_EXE% goto conf
echo Unable to locate a Wrapper executable using any of the following names:
echo %_WRAPPER_L_EXE%
echo %_WRAPPER_EXE%
pause
goto :eof
rem
rem Find the wrapper.conf
rem
:conf
if not [%_WRAPPER_CONF_OVERRIDE%]==[] (
set _WRAPPER_CONF="%~f1"
if not [%_WRAPPER_CONF%]==[""] (
shift
goto :startup
)
)
set _WRAPPER_CONF="%_WRAPPER_CONF_DEFAULT:"=%"
rem
rem Start the Wrapper
rem
:startup
rem Collect an parameters
:parameters
set _PARAMETERS=%_PARAMETERS% %1
shift
if not [%1]==[] goto :parameters
if [%_PASS_THROUGH%]==[] (
%_WRAPPER_EXE% -q %_WRAPPER_CONF%
) else (
%_WRAPPER_EXE% -q %_WRAPPER_CONF% -- %_PARAMETERS%
)
if not errorlevel 1 goto :eof
pause
wrapper_3.5.22_src/src/bin/ResumeApp-NT.bat.in 100644 0 0 10362 12224722010 16231 0 ustar 0 0 @echo off
setlocal
rem
rem Copyright (c) 1999, 2013 Tanuki Software, Ltd.
rem http://www.tanukisoftware.com
rem All rights reserved.
rem
rem This software is the proprietary information of Tanuki Software.
rem You shall use it only in accordance with the terms of the
rem license agreement you entered into with Tanuki Software.
rem http://wrapper.tanukisoftware.com/doc/english/licenseOverview.html
rem
rem Java Service Wrapper general startup script.
rem
rem -----------------------------------------------------------------------------
rem These settings can be modified to fit the needs of your application
rem Optimized for use with version 3.5.22 of the Wrapper.
rem The base name for the Wrapper binary.
set _WRAPPER_BASE=wrapper
rem The directory where the Wrapper binary (.exe) file is located, this can be
rem either a absolute or relative path. If the path contains any special characters,
rem please make sure to quote the variable.
set _WRAPPER_DIR=
rem The name and location of the Wrapper configuration file. This will be used
rem if the user does not specify a configuration file as the first parameter to
rem this script. It will not be possible to specify a configuration file on the
rem command line if _PASS_THROUGH is set.
rem If a relative path is specified, please note that the location is based on the
rem location.
set _WRAPPER_CONF_DEFAULT="../conf/%_WRAPPER_BASE%.conf"
rem Makes it possible to override the Wrapper configuration file by specifying it
rem as the first parameter.
rem set _WRAPPER_CONF_OVERRIDE=true
rem Note that it is only possible to pass parameters through to the JVM when
rem installing the service, or when running in a console.
rem Do not modify anything beyond this point
rem -----------------------------------------------------------------------------
rem
rem Resolve the real path of the wrapper.exe
rem For non NT systems, the _REALPATH and _WRAPPER_CONF values
rem can be hard-coded below and the following test removed.
rem
if "%OS%"=="Windows_NT" goto nt
echo This script only works with NT-based versions of Windows.
goto :eof
:nt
rem Find the application home.
rem if no path path specified do the default action
IF not DEFINED _WRAPPER_DIR goto dir_undefined
set _WRAPPER_DIR_QUOTED="%_WRAPPER_DIR:"=%"
if not "%_WRAPPER_DIR:~-2,1%" == "\" set _WRAPPER_DIR_QUOTED="%_WRAPPER_DIR_QUOTED:"=%\"
rem check if absolute path
if "%_WRAPPER_DIR_QUOTED:~2,1%" == ":" goto absolute_path
if "%_WRAPPER_DIR_QUOTED:~1,1%" == "\" goto absolute_path
rem everythig else means relative path
set _REALPATH="%~dp0%_WRAPPER_DIR_QUOTED:"=%"
goto pathfound
:dir_undefined
rem Use a relative path to the wrapper %~dp0 is location of current script under NT
set _REALPATH="%~dp0"
goto pathfound
:absolute_path
rem Use an absolute path to the wrapper
set _REALPATH="%_WRAPPER_DIR_QUOTED:"=%"
:pathfound
rem
rem Decide on the specific Wrapper binary to use (See delta-pack)
rem
if "%PROCESSOR_ARCHITEW6432%"=="AMD64" goto amd64
if "%PROCESSOR_ARCHITECTURE%"=="AMD64" goto amd64
if "%PROCESSOR_ARCHITECTURE%"=="IA64" goto ia64
set _WRAPPER_L_EXE="%_REALPATH:"=%%_WRAPPER_BASE%-windows-x86-32.exe"
goto search
:amd64
set _WRAPPER_L_EXE="%_REALPATH:"=%%_WRAPPER_BASE%-windows-x86-64.exe"
goto search
:ia64
set _WRAPPER_L_EXE="%_REALPATH:"=%%_WRAPPER_BASE%-windows-ia-64.exe"
goto search
:search
set _WRAPPER_EXE="%_WRAPPER_L_EXE:"=%"
if exist %_WRAPPER_EXE% goto conf
set _WRAPPER_EXE="%_REALPATH:"=%%_WRAPPER_BASE%.exe"
if exist %_WRAPPER_EXE% goto conf
echo Unable to locate a Wrapper executable using any of the following names:
echo %_WRAPPER_L_EXE%
echo %_WRAPPER_EXE%
pause
goto :eof
rem
rem Find the wrapper.conf
rem
:conf
if not [%_WRAPPER_CONF_OVERRIDE%]==[] (
set _WRAPPER_CONF="%~f1"
if not [%_WRAPPER_CONF%]==[""] (
shift
goto :startup
)
)
set _WRAPPER_CONF="%_WRAPPER_CONF_DEFAULT:"=%"
rem
rem Start the Wrapper
rem
:startup
rem Collect an parameters
:parameters
set _PARAMETERS=%_PARAMETERS% %1
shift
if not [%1]==[] goto :parameters
if [%_PASS_THROUGH%]==[] (
%_WRAPPER_EXE% -e %_WRAPPER_CONF%
) else (
%_WRAPPER_EXE% -e %_WRAPPER_CONF% -- %_PARAMETERS%
)
if not errorlevel 1 goto :eof
pause
wrapper_3.5.22_src/src/bin/StartApp-NT.bat.in 100644 0 0 10362 12224722010 16066 0 ustar 0 0 @echo off
setlocal
rem
rem Copyright (c) 1999, 2013 Tanuki Software, Ltd.
rem http://www.tanukisoftware.com
rem All rights reserved.
rem
rem This software is the proprietary information of Tanuki Software.
rem You shall use it only in accordance with the terms of the
rem license agreement you entered into with Tanuki Software.
rem http://wrapper.tanukisoftware.com/doc/english/licenseOverview.html
rem
rem Java Service Wrapper general startup script.
rem
rem -----------------------------------------------------------------------------
rem These settings can be modified to fit the needs of your application
rem Optimized for use with version 3.5.22 of the Wrapper.
rem The base name for the Wrapper binary.
set _WRAPPER_BASE=wrapper
rem The directory where the Wrapper binary (.exe) file is located, this can be
rem either a absolute or relative path. If the path contains any special characters,
rem please make sure to quote the variable.
set _WRAPPER_DIR=
rem The name and location of the Wrapper configuration file. This will be used
rem if the user does not specify a configuration file as the first parameter to
rem this script. It will not be possible to specify a configuration file on the
rem command line if _PASS_THROUGH is set.
rem If a relative path is specified, please note that the location is based on the
rem location.
set _WRAPPER_CONF_DEFAULT="../conf/%_WRAPPER_BASE%.conf"
rem Makes it possible to override the Wrapper configuration file by specifying it
rem as the first parameter.
rem set _WRAPPER_CONF_OVERRIDE=true
rem Note that it is only possible to pass parameters through to the JVM when
rem installing the service, or when running in a console.
rem Do not modify anything beyond this point
rem -----------------------------------------------------------------------------
rem
rem Resolve the real path of the wrapper.exe
rem For non NT systems, the _REALPATH and _WRAPPER_CONF values
rem can be hard-coded below and the following test removed.
rem
if "%OS%"=="Windows_NT" goto nt
echo This script only works with NT-based versions of Windows.
goto :eof
:nt
rem Find the application home.
rem if no path path specified do the default action
IF not DEFINED _WRAPPER_DIR goto dir_undefined
set _WRAPPER_DIR_QUOTED="%_WRAPPER_DIR:"=%"
if not "%_WRAPPER_DIR:~-2,1%" == "\" set _WRAPPER_DIR_QUOTED="%_WRAPPER_DIR_QUOTED:"=%\"
rem check if absolute path
if "%_WRAPPER_DIR_QUOTED:~2,1%" == ":" goto absolute_path
if "%_WRAPPER_DIR_QUOTED:~1,1%" == "\" goto absolute_path
rem everythig else means relative path
set _REALPATH="%~dp0%_WRAPPER_DIR_QUOTED:"=%"
goto pathfound
:dir_undefined
rem Use a relative path to the wrapper %~dp0 is location of current script under NT
set _REALPATH="%~dp0"
goto pathfound
:absolute_path
rem Use an absolute path to the wrapper
set _REALPATH="%_WRAPPER_DIR_QUOTED:"=%"
:pathfound
rem
rem Decide on the specific Wrapper binary to use (See delta-pack)
rem
if "%PROCESSOR_ARCHITEW6432%"=="AMD64" goto amd64
if "%PROCESSOR_ARCHITECTURE%"=="AMD64" goto amd64
if "%PROCESSOR_ARCHITECTURE%"=="IA64" goto ia64
set _WRAPPER_L_EXE="%_REALPATH:"=%%_WRAPPER_BASE%-windows-x86-32.exe"
goto search
:amd64
set _WRAPPER_L_EXE="%_REALPATH:"=%%_WRAPPER_BASE%-windows-x86-64.exe"
goto search
:ia64
set _WRAPPER_L_EXE="%_REALPATH:"=%%_WRAPPER_BASE%-windows-ia-64.exe"
goto search
:search
set _WRAPPER_EXE="%_WRAPPER_L_EXE:"=%"
if exist %_WRAPPER_EXE% goto conf
set _WRAPPER_EXE="%_REALPATH:"=%%_WRAPPER_BASE%.exe"
if exist %_WRAPPER_EXE% goto conf
echo Unable to locate a Wrapper executable using any of the following names:
echo %_WRAPPER_L_EXE%
echo %_WRAPPER_EXE%
pause
goto :eof
rem
rem Find the wrapper.conf
rem
:conf
if not [%_WRAPPER_CONF_OVERRIDE%]==[] (
set _WRAPPER_CONF="%~f1"
if not [%_WRAPPER_CONF%]==[""] (
shift
goto :startup
)
)
set _WRAPPER_CONF="%_WRAPPER_CONF_DEFAULT:"=%"
rem
rem Start the Wrapper
rem
:startup
rem Collect an parameters
:parameters
set _PARAMETERS=%_PARAMETERS% %1
shift
if not [%1]==[] goto :parameters
if [%_PASS_THROUGH%]==[] (
%_WRAPPER_EXE% -t %_WRAPPER_CONF%
) else (
%_WRAPPER_EXE% -t %_WRAPPER_CONF% -- %_PARAMETERS%
)
if not errorlevel 1 goto :eof
pause
wrapper_3.5.22_src/src/bin/StopApp-NT.bat.in 100644 0 0 10362 12224722010 15716 0 ustar 0 0 @echo off
setlocal
rem
rem Copyright (c) 1999, 2013 Tanuki Software, Ltd.
rem http://www.tanukisoftware.com
rem All rights reserved.
rem
rem This software is the proprietary information of Tanuki Software.
rem You shall use it only in accordance with the terms of the
rem license agreement you entered into with Tanuki Software.
rem http://wrapper.tanukisoftware.com/doc/english/licenseOverview.html
rem
rem Java Service Wrapper general startup script.
rem
rem -----------------------------------------------------------------------------
rem These settings can be modified to fit the needs of your application
rem Optimized for use with version 3.5.22 of the Wrapper.
rem The base name for the Wrapper binary.
set _WRAPPER_BASE=wrapper
rem The directory where the Wrapper binary (.exe) file is located, this can be
rem either a absolute or relative path. If the path contains any special characters,
rem please make sure to quote the variable.
set _WRAPPER_DIR=
rem The name and location of the Wrapper configuration file. This will be used
rem if the user does not specify a configuration file as the first parameter to
rem this script. It will not be possible to specify a configuration file on the
rem command line if _PASS_THROUGH is set.
rem If a relative path is specified, please note that the location is based on the
rem location.
set _WRAPPER_CONF_DEFAULT="../conf/%_WRAPPER_BASE%.conf"
rem Makes it possible to override the Wrapper configuration file by specifying it
rem as the first parameter.
rem set _WRAPPER_CONF_OVERRIDE=true
rem Note that it is only possible to pass parameters through to the JVM when
rem installing the service, or when running in a console.
rem Do not modify anything beyond this point
rem -----------------------------------------------------------------------------
rem
rem Resolve the real path of the wrapper.exe
rem For non NT systems, the _REALPATH and _WRAPPER_CONF values
rem can be hard-coded below and the following test removed.
rem
if "%OS%"=="Windows_NT" goto nt
echo This script only works with NT-based versions of Windows.
goto :eof
:nt
rem Find the application home.
rem if no path path specified do the default action
IF not DEFINED _WRAPPER_DIR goto dir_undefined
set _WRAPPER_DIR_QUOTED="%_WRAPPER_DIR:"=%"
if not "%_WRAPPER_DIR:~-2,1%" == "\" set _WRAPPER_DIR_QUOTED="%_WRAPPER_DIR_QUOTED:"=%\"
rem check if absolute path
if "%_WRAPPER_DIR_QUOTED:~2,1%" == ":" goto absolute_path
if "%_WRAPPER_DIR_QUOTED:~1,1%" == "\" goto absolute_path
rem everythig else means relative path
set _REALPATH="%~dp0%_WRAPPER_DIR_QUOTED:"=%"
goto pathfound
:dir_undefined
rem Use a relative path to the wrapper %~dp0 is location of current script under NT
set _REALPATH="%~dp0"
goto pathfound
:absolute_path
rem Use an absolute path to the wrapper
set _REALPATH="%_WRAPPER_DIR_QUOTED:"=%"
:pathfound
rem
rem Decide on the specific Wrapper binary to use (See delta-pack)
rem
if "%PROCESSOR_ARCHITEW6432%"=="AMD64" goto amd64
if "%PROCESSOR_ARCHITECTURE%"=="AMD64" goto amd64
if "%PROCESSOR_ARCHITECTURE%"=="IA64" goto ia64
set _WRAPPER_L_EXE="%_REALPATH:"=%%_WRAPPER_BASE%-windows-x86-32.exe"
goto search
:amd64
set _WRAPPER_L_EXE="%_REALPATH:"=%%_WRAPPER_BASE%-windows-x86-64.exe"
goto search
:ia64
set _WRAPPER_L_EXE="%_REALPATH:"=%%_WRAPPER_BASE%-windows-ia-64.exe"
goto search
:search
set _WRAPPER_EXE="%_WRAPPER_L_EXE:"=%"
if exist %_WRAPPER_EXE% goto conf
set _WRAPPER_EXE="%_REALPATH:"=%%_WRAPPER_BASE%.exe"
if exist %_WRAPPER_EXE% goto conf
echo Unable to locate a Wrapper executable using any of the following names:
echo %_WRAPPER_L_EXE%
echo %_WRAPPER_EXE%
pause
goto :eof
rem
rem Find the wrapper.conf
rem
:conf
if not [%_WRAPPER_CONF_OVERRIDE%]==[] (
set _WRAPPER_CONF="%~f1"
if not [%_WRAPPER_CONF%]==[""] (
shift
goto :startup
)
)
set _WRAPPER_CONF="%_WRAPPER_CONF_DEFAULT:"=%"
rem
rem Start the Wrapper
rem
:startup
rem Collect an parameters
:parameters
set _PARAMETERS=%_PARAMETERS% %1
shift
if not [%1]==[] goto :parameters
if [%_PASS_THROUGH%]==[] (
%_WRAPPER_EXE% -p %_WRAPPER_CONF%
) else (
%_WRAPPER_EXE% -p %_WRAPPER_CONF% -- %_PARAMETERS%
)
if not errorlevel 1 goto :eof
pause
wrapper_3.5.22_src/src/bin/UninstallApp-NT.bat.in 100644 0 0 10362 12224722010 16742 0 ustar 0 0 @echo off
setlocal
rem
rem Copyright (c) 1999, 2013 Tanuki Software, Ltd.
rem http://www.tanukisoftware.com
rem All rights reserved.
rem
rem This software is the proprietary information of Tanuki Software.
rem You shall use it only in accordance with the terms of the
rem license agreement you entered into with Tanuki Software.
rem http://wrapper.tanukisoftware.com/doc/english/licenseOverview.html
rem
rem Java Service Wrapper general startup script.
rem
rem -----------------------------------------------------------------------------
rem These settings can be modified to fit the needs of your application
rem Optimized for use with version 3.5.22 of the Wrapper.
rem The base name for the Wrapper binary.
set _WRAPPER_BASE=wrapper
rem The directory where the Wrapper binary (.exe) file is located, this can be
rem either a absolute or relative path. If the path contains any special characters,
rem please make sure to quote the variable.
set _WRAPPER_DIR=
rem The name and location of the Wrapper configuration file. This will be used
rem if the user does not specify a configuration file as the first parameter to
rem this script. It will not be possible to specify a configuration file on the
rem command line if _PASS_THROUGH is set.
rem If a relative path is specified, please note that the location is based on the
rem location.
set _WRAPPER_CONF_DEFAULT="../conf/%_WRAPPER_BASE%.conf"
rem Makes it possible to override the Wrapper configuration file by specifying it
rem as the first parameter.
rem set _WRAPPER_CONF_OVERRIDE=true
rem Note that it is only possible to pass parameters through to the JVM when
rem installing the service, or when running in a console.
rem Do not modify anything beyond this point
rem -----------------------------------------------------------------------------
rem
rem Resolve the real path of the wrapper.exe
rem For non NT systems, the _REALPATH and _WRAPPER_CONF values
rem can be hard-coded below and the following test removed.
rem
if "%OS%"=="Windows_NT" goto nt
echo This script only works with NT-based versions of Windows.
goto :eof
:nt
rem Find the application home.
rem if no path path specified do the default action
IF not DEFINED _WRAPPER_DIR goto dir_undefined
set _WRAPPER_DIR_QUOTED="%_WRAPPER_DIR:"=%"
if not "%_WRAPPER_DIR:~-2,1%" == "\" set _WRAPPER_DIR_QUOTED="%_WRAPPER_DIR_QUOTED:"=%\"
rem check if absolute path
if "%_WRAPPER_DIR_QUOTED:~2,1%" == ":" goto absolute_path
if "%_WRAPPER_DIR_QUOTED:~1,1%" == "\" goto absolute_path
rem everythig else means relative path
set _REALPATH="%~dp0%_WRAPPER_DIR_QUOTED:"=%"
goto pathfound
:dir_undefined
rem Use a relative path to the wrapper %~dp0 is location of current script under NT
set _REALPATH="%~dp0"
goto pathfound
:absolute_path
rem Use an absolute path to the wrapper
set _REALPATH="%_WRAPPER_DIR_QUOTED:"=%"
:pathfound
rem
rem Decide on the specific Wrapper binary to use (See delta-pack)
rem
if "%PROCESSOR_ARCHITEW6432%"=="AMD64" goto amd64
if "%PROCESSOR_ARCHITECTURE%"=="AMD64" goto amd64
if "%PROCESSOR_ARCHITECTURE%"=="IA64" goto ia64
set _WRAPPER_L_EXE="%_REALPATH:"=%%_WRAPPER_BASE%-windows-x86-32.exe"
goto search
:amd64
set _WRAPPER_L_EXE="%_REALPATH:"=%%_WRAPPER_BASE%-windows-x86-64.exe"
goto search
:ia64
set _WRAPPER_L_EXE="%_REALPATH:"=%%_WRAPPER_BASE%-windows-ia-64.exe"
goto search
:search
set _WRAPPER_EXE="%_WRAPPER_L_EXE:"=%"
if exist %_WRAPPER_EXE% goto conf
set _WRAPPER_EXE="%_REALPATH:"=%%_WRAPPER_BASE%.exe"
if exist %_WRAPPER_EXE% goto conf
echo Unable to locate a Wrapper executable using any of the following names:
echo %_WRAPPER_L_EXE%
echo %_WRAPPER_EXE%
pause
goto :eof
rem
rem Find the wrapper.conf
rem
:conf
if not [%_WRAPPER_CONF_OVERRIDE%]==[] (
set _WRAPPER_CONF="%~f1"
if not [%_WRAPPER_CONF%]==[""] (
shift
goto :startup
)
)
set _WRAPPER_CONF="%_WRAPPER_CONF_DEFAULT:"=%"
rem
rem Start the Wrapper
rem
:startup
rem Collect an parameters
:parameters
set _PARAMETERS=%_PARAMETERS% %1
shift
if not [%1]==[] goto :parameters
if [%_PASS_THROUGH%]==[] (
%_WRAPPER_EXE% -r %_WRAPPER_CONF%
) else (
%_WRAPPER_EXE% -r %_WRAPPER_CONF% -- %_PARAMETERS%
)
if not errorlevel 1 goto :eof
pause
wrapper_3.5.22_src/src/bin/sh.script.in 100644 0 0 171314 12224722007 15214 0 ustar 0 0 #! /bin/sh
#
# Copyright (c) 1999, 2013 Tanuki Software, Ltd.
# http://www.tanukisoftware.com
# All rights reserved.
#
# This software is the proprietary information of Tanuki Software.
# You shall use it only in accordance with the terms of the
# license agreement you entered into with Tanuki Software.
# http://wrapper.tanukisoftware.com/doc/english/licenseOverview.html
#
# Java Service Wrapper sh script. Suitable for starting and stopping
# wrapped Java applications on UNIX platforms.
#
#-----------------------------------------------------------------------------
# These settings can be modified to fit the needs of your application
# Optimized for use with version 3.5.22 of the Wrapper.
# IMPORTANT - Please always stop and uninstall an application before making
# any changes to this file. Failure to do so could remove the
# script's ability to control the application.
# Application
APP_NAME="@app.name@"
APP_LONG_NAME="@app.long.name@"
# Wrapper
WRAPPER_CMD="./wrapper"
WRAPPER_CONF="../conf/wrapper.conf"
# Priority at which to run the wrapper. See "man nice" for valid priorities.
# nice is only used if a priority is specified.
PRIORITY=
# Location of the pid file.
PIDDIR="."
# PIDFILE_CHECK_PID tells the script to double check whether the pid in the pid
# file actually exists and belongs to this application. When not set, only
# check the pid, but not what it is. This is only needed when multiple
# applications need to share the same pid file.
PIDFILE_CHECK_PID=true
# FIXED_COMMAND tells the script to use a hard coded action rather than
# expecting the first parameter of the command line to be the command.
# By default the command will will be expected to be the first parameter.
#FIXED_COMMAND=console
# PASS_THROUGH tells the script to pass all arguments through to the JVM
# as is. If FIXED_COMMAND is specified then all arguments will be passed.
# If not set then all arguments starting with the second will be passed.
#PASS_THROUGH=true
# If uncommented, causes the Wrapper to be shutdown using an anchor file.
# When launched with the 'start' command, it will also ignore all INT and
# TERM signals.
#IGNORE_SIGNALS=true
# Wrapper will start the JVM asynchronously. Your application may have some
# initialization tasks and it may be desirable to wait a few seconds
# before returning. For example, to delay the invocation of following
# startup scripts. Setting WAIT_AFTER_STARTUP to a positive number will
# cause the start command to delay for the indicated period of time
# (in seconds).
#
WAIT_AFTER_STARTUP=0
# If set, wait for the wrapper to report that the daemon has started
WAIT_FOR_STARTED_STATUS=true
WAIT_FOR_STARTED_TIMEOUT=120
# If set, the status, start_msg and stop_msg commands will print out detailed
# state information on the Wrapper and Java processes.
#DETAIL_STATUS=true
# If set, the 'pause' and 'resume' commands will be enabled. These make it
# possible to pause the JVM or Java application without completely stopping
# the Wrapper. See the wrapper.pausable and wrapper.pausable.stop_jvm
# properties for more information.
#PAUSABLE=true
# If specified, the Wrapper will be run as the specified user.
# IMPORTANT - Make sure that the user has the required privileges to write
# the PID file and wrapper.log files. Failure to be able to write the log
# file will cause the Wrapper to exit without any way to write out an error
# message.
# NOTE - This will set the user which is used to run the Wrapper as well as
# the JVM and is not useful in situations where a privileged resource or
# port needs to be allocated prior to the user being changed.
#RUN_AS_USER=
# By default we show a detailed usage block. Uncomment to show brief usage.
#BRIEF_USAGE=true
# flag for using upstart when installing (rather than init.d rc.d)
USE_UPSTART=
# When installing on On Mac OSX platforms, the following domain will be used to
# prefix the plist file name.
PLIST_DOMAIN=org.tanukisoftware.wrapper
# The following two lines are used by the chkconfig command. Change as is
# appropriate for your application. They should remain commented.
# chkconfig: 2345 20 80
# description: @app.long.name@
# Initialization block for the install_initd and remove_initd scripts used by
# SUSE linux distributions.
### BEGIN INIT INFO
# Provides: @app.name@
# Required-Start: $local_fs $network $syslog
# Should-Start:
# Required-Stop:
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: @app.long.name@
# Description: @app.description@
### END INIT INFO
# Set run level to use when installing the application to start and stop on
# system startup and shutdown. It is important that the application always
# be uninstalled before making any changes to the run levels.
# It is also possible to specify different run levels based on the individual
# platform. When doing so this script will look for defined run levels in
# the following order:
# 1) "RUN_LEVEL_S_$DIST_OS" or "RUN_LEVEL_K_$DIST_OS", where "$DIST_OS" is
# the value of DIST_OS. "RUN_LEVEL_S_solaris=20" for example.
# 2) RUN_LEVEL_S or RUN_LEVEL_K, to specify specify start or stop run levels.
# 3) RUN_LEVEL, to specify a general run level.
RUN_LEVEL=20
# Do not modify anything beyond this point
#-----------------------------------------------------------------------------
if [ -n "$FIXED_COMMAND" ]
then
COMMAND="$FIXED_COMMAND"
else
COMMAND="$1"
fi
# Required for HP-UX Startup
if [ `uname -s` = "HP-UX" -o `uname -s` = "HP-UX64" ] ; then
PATH=$PATH:/usr/bin
fi
# Get the fully qualified path to the script
case $0 in
/*)
SCRIPT="$0"
;;
*)
PWD=`pwd`
SCRIPT="$PWD/$0"
;;
esac
# Resolve the true real path without any sym links.
CHANGED=true
while [ "X$CHANGED" != "X" ]
do
# Change spaces to ":" so the tokens can be parsed.
SAFESCRIPT=`echo $SCRIPT | sed -e 's; ;:;g'`
# Get the real path to this script, resolving any symbolic links
TOKENS=`echo $SAFESCRIPT | sed -e 's;/; ;g'`
REALPATH=
for C in $TOKENS; do
# Change any ":" in the token back to a space.
C=`echo $C | sed -e 's;:; ;g'`
REALPATH="$REALPATH/$C"
# If REALPATH is a sym link, resolve it. Loop for nested links.
while [ -h "$REALPATH" ] ; do
LS="`ls -ld "$REALPATH"`"
LINK="`expr "$LS" : '.*-> \(.*\)$'`"
if expr "$LINK" : '/.*' > /dev/null; then
# LINK is absolute.
REALPATH="$LINK"
else
# LINK is relative.
REALPATH="`dirname "$REALPATH"`""/$LINK"
fi
done
done
if [ "$REALPATH" = "$SCRIPT" ]
then
CHANGED=""
else
SCRIPT="$REALPATH"
fi
done
# Get the location of the script.
REALDIR=`dirname "$REALPATH"`
# Normalize the path
REALDIR=`cd "${REALDIR}"; pwd`
# If the PIDDIR is relative, set its value relative to the full REALPATH to avoid problems if
# the working directory is later changed.
FIRST_CHAR=`echo $PIDDIR | cut -c1,1`
if [ "$FIRST_CHAR" != "/" ]
then
PIDDIR=$REALDIR/$PIDDIR
fi
# Same test for WRAPPER_CMD
FIRST_CHAR=`echo $WRAPPER_CMD | cut -c1,1`
if [ "$FIRST_CHAR" != "/" ]
then
WRAPPER_CMD=$REALDIR/$WRAPPER_CMD
fi
# Same test for WRAPPER_CONF
FIRST_CHAR=`echo $WRAPPER_CONF | cut -c1,1`
if [ "$FIRST_CHAR" != "/" ]
then
WRAPPER_CONF=$REALDIR/$WRAPPER_CONF
fi
# Process ID
ANCHORFILE="$PIDDIR/$APP_NAME.anchor"
COMMANDFILE="$PIDDIR/$APP_NAME.command"
STATUSFILE="$PIDDIR/$APP_NAME.status"
JAVASTATUSFILE="$PIDDIR/$APP_NAME.java.status"
PIDFILE="$PIDDIR/$APP_NAME.pid"
LOCKDIR="/var/lock/subsys"
LOCKFILE="$LOCKDIR/$APP_NAME"
pid=""
# Resolve the location of the 'ps' command
PSEXE="/usr/ucb/ps"
if [ ! -x "$PSEXE" ]
then
PSEXE="/usr/bin/ps"
if [ ! -x "$PSEXE" ]
then
PSEXE="/bin/ps"
if [ ! -x "$PSEXE" ]
then
eval echo `gettext 'Unable to locate "ps".'`
eval echo `gettext 'Please report this message along with the location of the command on your system.'`
exit 1
fi
fi
fi
TREXE="/usr/bin/tr"
if [ ! -x "$TREXE" ]
then
TREXE="/bin/tr"
if [ ! -x "$TREXE" ]
then
eval echo `gettext 'Unable to locate "tr".'`
eval echo `gettext 'Please report this message along with the location of the command on your system.'`
exit 1
fi
fi
# Resolve the os
DIST_OS=`uname -s | $TREXE "[A-Z]" "[a-z]" | $TREXE -d ' '`
case "$DIST_OS" in
'sunos')
DIST_OS="solaris"
;;
'hp-ux' | 'hp-ux64')
# HP-UX needs the XPG4 version of ps (for -o args)
DIST_OS="hpux"
UNIX95=""
export UNIX95
;;
'darwin')
DIST_OS="macosx"
;;
'unix_sv')
DIST_OS="unixware"
;;
'os/390')
DIST_OS="zos"
;;
esac
# Resolve the architecture
if [ "$DIST_OS" = "macosx" ]
then
OS_VER=`sw_vers | grep 'ProductVersion:' | grep -o '[0-9]*\.[0-9]*\.[0-9]*'`
DIST_ARCH="universal"
if [[ "$OS_VER" < "10.5.0" ]]
then
DIST_BITS="32"
else
if [ "X`sysctl -n hw.cpu64bit_capable`" == "X1" ]
then
DIST_BITS="64"
else
DIST_BITS="32"
fi
fi
APP_PLIST_BASE=${PLIST_DOMAIN}.${APP_NAME}
APP_PLIST=${APP_PLIST_BASE}.plist
else
DIST_ARCH=
DIST_ARCH=`uname -p 2>/dev/null | $TREXE "[A-Z]" "[a-z]" | $TREXE -d ' '`
if [ "X$DIST_ARCH" = "X" ]
then
DIST_ARCH="unknown"
fi
if [ "$DIST_ARCH" = "unknown" ]
then
DIST_ARCH=`uname -m 2>/dev/null | $TREXE "[A-Z]" "[a-z]" | $TREXE -d ' '`
fi
case "$DIST_ARCH" in
'athlon' | 'i386' | 'i486' | 'i586' | 'i686')
DIST_ARCH="x86"
if [ "${DIST_OS}" = "solaris" ] ; then
DIST_BITS=`isainfo -b`
else
DIST_BITS="32"
fi
;;
'amd64' | 'x86_64')
DIST_ARCH="x86"
DIST_BITS="64"
;;
'ia32')
DIST_ARCH="ia"
DIST_BITS="32"
;;
'ia64' | 'ia64n' | 'ia64w')
DIST_ARCH="ia"
DIST_BITS="64"
;;
'ip27')
DIST_ARCH="mips"
DIST_BITS="32"
;;
'power' | 'powerpc' | 'power_pc' | 'ppc64')
if [ "${DIST_ARCH}" = "ppc64" ] ; then
DIST_BITS="64"
else
DIST_BITS="32"
fi
DIST_ARCH="ppc"
if [ "${DIST_OS}" = "aix" ] ; then
if [ `getconf KERNEL_BITMODE` -eq 64 ]; then
DIST_BITS="64"
else
DIST_BITS="32"
fi
fi
;;
'pa_risc' | 'pa-risc')
DIST_ARCH="parisc"
if [ `getconf KERNEL_BITS` -eq 64 ]; then
DIST_BITS="64"
else
DIST_BITS="32"
fi
;;
'sun4u' | 'sparcv9' | 'sparc')
DIST_ARCH="sparc"
DIST_BITS=`isainfo -b`
;;
'9000/800' | '9000/785')
DIST_ARCH="parisc"
if [ `getconf KERNEL_BITS` -eq 64 ]; then
DIST_BITS="64"
else
DIST_BITS="32"
fi
;;
'2064' | '2066' | '2084' | '2086' | '2094' | '2096' | '2097' | '2098' | '2817')
DIST_ARCH="390"
DIST_BITS="64"
;;
armv*)
if [ -z "`readelf -A /proc/self/exe | grep Tag_ABI_VFP_args`" ] ; then
DIST_ARCH="armel"
DIST_BITS="32"
else
DIST_ARCH="armhf"
DIST_BITS="32"
fi
;;
esac
fi
# OSX always places Java in the same location so we can reliably set JAVA_HOME
if [ "$DIST_OS" = "macosx" ]
then
if [ -z "$JAVA_HOME" ]; then
JAVA_HOME="/Library/Java/Home"; export JAVA_HOME
fi
fi
# Test Echo
ECHOTEST=`echo -n "x"`
if [ "$ECHOTEST" = "x" ]
then
ECHOOPT="-n "
else
ECHOOPT=""
fi
gettext() {
"$WRAPPER_CMD" --translate "$1" "$WRAPPER_CONF" 2>/dev/null
if [ $? != 0 ] ; then
echo "$1"
fi
}
outputFile() {
if [ -f "$1" ]
then
eval echo `gettext ' $1 Found but not executable.'`;
else
echo " $1"
fi
}
# Decide on the wrapper binary to use.
# If the bits of the OS could be detected, we will try to look for the
# binary with the correct bits value. If it doesn't exist, fall back
# and look for the 32-bit binary. If that doesn't exist either then
# look for the default.
WRAPPER_TEST_CMD=""
if [ -f "$WRAPPER_CMD-$DIST_OS-$DIST_ARCH-$DIST_BITS" ]
then
WRAPPER_TEST_CMD="$WRAPPER_CMD-$DIST_OS-$DIST_ARCH-$DIST_BITS"
if [ ! -x "$WRAPPER_TEST_CMD" ]
then
chmod +x "$WRAPPER_TEST_CMD" 2>/dev/null
fi
if [ -x "$WRAPPER_TEST_CMD" ]
then
WRAPPER_CMD="$WRAPPER_TEST_CMD"
else
outputFile "$WRAPPER_TEST_CMD"
WRAPPER_TEST_CMD=""
fi
fi
if [ -f "$WRAPPER_CMD-$DIST_OS-$DIST_ARCH-32" -a -z "$WRAPPER_TEST_CMD" ]
then
WRAPPER_TEST_CMD="$WRAPPER_CMD-$DIST_OS-$DIST_ARCH-32"
if [ ! -x "$WRAPPER_TEST_CMD" ]
then
chmod +x "$WRAPPER_TEST_CMD" 2>/dev/null
fi
if [ -x "$WRAPPER_TEST_CMD" ]
then
WRAPPER_CMD="$WRAPPER_TEST_CMD"
else
outputFile "$WRAPPER_TEST_CMD"
WRAPPER_TEST_CMD=""
fi
fi
if [ -f "$WRAPPER_CMD" -a -z "$WRAPPER_TEST_CMD" ]
then
WRAPPER_TEST_CMD="$WRAPPER_CMD"
if [ ! -x "$WRAPPER_TEST_CMD" ]
then
chmod +x "$WRAPPER_TEST_CMD" 2>/dev/null
fi
if [ -x "$WRAPPER_TEST_CMD" ]
then
WRAPPER_CMD="$WRAPPER_TEST_CMD"
else
outputFile "$WRAPPER_TEST_CMD"
WRAPPER_TEST_CMD=""
fi
fi
if [ -z "$WRAPPER_TEST_CMD" ]
then
eval echo `gettext 'Unable to locate any of the following binaries:'`
outputFile "$WRAPPER_CMD-$DIST_OS-$DIST_ARCH-$DIST_BITS"
if [ ! "$DIST_BITS" = "32" ]
then
outputFile "$WRAPPER_CMD-$DIST_OS-$DIST_ARCH-32"
fi
outputFile "$WRAPPER_CMD"
exit 1
fi
# Build the nice clause
if [ "X$PRIORITY" = "X" ]
then
CMDNICE=""
else
CMDNICE="nice -$PRIORITY"
fi
# Build the anchor file clause.
if [ "X$IGNORE_SIGNALS" = "X" ]
then
ANCHORPROP=
IGNOREPROP=
else
ANCHORPROP=wrapper.anchorfile=\"$ANCHORFILE\"
IGNOREPROP=wrapper.ignore_signals=TRUE
fi
# Build the status file clause.
if [ "X$DETAIL_STATUS$WAIT_FOR_STARTED_STATUS" = "X" ]
then
STATUSPROP=
else
STATUSPROP="wrapper.statusfile=\"$STATUSFILE\" wrapper.java.statusfile=\"$JAVASTATUSFILE\""
fi
# Build the command file clause.
if [ -n "$PAUSABLE" ]
then
COMMANDPROP="wrapper.commandfile=\"$COMMANDFILE\" wrapper.pausable=TRUE"
else
COMMANDPROP=
fi
if [ ! -n "$WAIT_FOR_STARTED_STATUS" ]
then
WAIT_FOR_STARTED_STATUS=true
fi
if [ $WAIT_FOR_STARTED_STATUS = true ] ; then
DETAIL_STATUS=true
fi
# Build the lock file clause. Only create a lock file if the lock directory exists on this platform.
LOCKPROP=
if [ -d $LOCKDIR ]
then
if [ -w $LOCKDIR ]
then
LOCKPROP=wrapper.lockfile=\"$LOCKFILE\"
fi
fi
# Decide on run levels.
RUN_LEVEL_S_DIST_OS_TMP=`eval "echo \$\{RUN_LEVEL_S_${DIST_OS}\}"`
RUN_LEVEL_S_DIST_OS=`eval "echo ${RUN_LEVEL_S_DIST_OS_TMP}"`
if [ "X${RUN_LEVEL_S_DIST_OS}" != "X" ] ; then
APP_RUN_LEVEL_S=${RUN_LEVEL_S_DIST_OS}
elif [ "X$RUN_LEVEL_S" != "X" ] ; then
APP_RUN_LEVEL_S=$RUN_LEVEL_S
else
APP_RUN_LEVEL_S=$RUN_LEVEL
fi
APP_RUN_LEVEL_S_CHECK=`echo "$APP_RUN_LEVEL_S" | sed "s/[(0-9)*]/0/g"`
if [ "X${APP_RUN_LEVEL_S_CHECK}" != "X00" ] ; then
eval echo `gettext 'Run level \"${APP_RUN_LEVEL_S}\" must be numeric and have a length of two \(00-99\).'`
exit 1;
fi
RUN_LEVEL_K_DIST_OS_TMP=`eval "echo \$\{RUN_LEVEL_K_${DIST_OS}\}"`
RUN_LEVEL_K_DIST_OS=`eval "echo ${RUN_LEVEL_K_DIST_OS_TMP}"`
if [ "X${RUN_LEVEL_K_DIST_OS}" != "X" ] ; then
APP_RUN_LEVEL_K=${RUN_LEVEL_K_DIST_OS}
elif [ "X$RUN_LEVEL_K" != "X" ] ; then
APP_RUN_LEVEL_K=$RUN_LEVEL_K
else
APP_RUN_LEVEL_K=$RUN_LEVEL
fi
APP_RUN_LEVEL_K_CHECK=`echo "$APP_RUN_LEVEL_K" | sed "s/[(0-9)*]/0/g"`
if [ "X${APP_RUN_LEVEL_K_CHECK}" != "X00" ] ; then
eval echo `gettext 'Run level \"${APP_RUN_LEVEL_K}\" must be numeric and have a length of two \(00-99\).'`
exit 1;
fi
prepAdditionalParams() {
ADDITIONAL_PARA=""
if [ -n "$PASS_THROUGH" ] ; then
ADDITIONAL_PARA="--"
fi
while [ -n "$1" ] ; do
ADDITIONAL_PARA="$ADDITIONAL_PARA \"$1\""
shift
done
}
checkUser() {
# $1 touchLock flag
# $2.. [command] args
# Check the configured user. If necessary rerun this script as the desired user.
if [ "X$RUN_AS_USER" != "X" ]
then
# Resolve the location of the 'id' command
IDEXE="/usr/xpg4/bin/id"
if [ ! -x "$IDEXE" ]
then
IDEXE="/usr/bin/id"
if [ ! -x "$IDEXE" ]
then
eval echo `gettext 'Unable to locate "id".'`
eval echo `gettext 'Please report this message along with the location of the command on your system.'`
exit 1
fi
fi
if [ "`$IDEXE -u -n`" = "$RUN_AS_USER" ]
then
# Already running as the configured user. Avoid password prompts by not calling su.
RUN_AS_USER=""
fi
fi
if [ "X$RUN_AS_USER" != "X" ]
then
if [ "`$IDEXE -u -n "$RUN_AS_USER" 2>/dev/null`" != "$RUN_AS_USER" ]
then
eval echo `gettext 'User $RUN_AS_USER does not exist.'`
exit 1
fi
# If LOCKPROP and $RUN_AS_USER are defined then the new user will most likely not be
# able to create the lock file. The Wrapper will be able to update this file once it
# is created but will not be able to delete it on shutdown. If $1 is set then
# the lock file should be created for the current command
if [ "X$LOCKPROP" != "X" ]
then
if [ "X$1" != "X" ]
then
# Resolve the primary group
RUN_AS_GROUP=`groups $RUN_AS_USER | awk '{print $3}' | tail -1`
if [ "X$RUN_AS_GROUP" = "X" ]
then
RUN_AS_GROUP=$RUN_AS_USER
fi
touch $LOCKFILE
chown $RUN_AS_USER:$RUN_AS_GROUP $LOCKFILE
fi
fi
# Still want to change users, recurse. This means that the user will only be
# prompted for a password once. Variables shifted by 1
shift
# Wrap the parameters so they can be passed.
ADDITIONAL_PARA=""
while [ -n "$1" ] ; do
ADDITIONAL_PARA="$ADDITIONAL_PARA \"$1\""
shift
done
# Use "runuser" if this exists. runuser should be used on RedHat in preference to su.
#
if test -f "/sbin/runuser"
then
/sbin/runuser - $RUN_AS_USER -c "\"$REALPATH\" $ADDITIONAL_PARA"
else
su - $RUN_AS_USER -c "\"$REALPATH\" $ADDITIONAL_PARA"
fi
RUN_AS_USER_EXITCODE=$?
# Now that we are the original user again, we may need to clean up the lock file.
if [ "X$LOCKPROP" != "X" ]
then
getpid
if [ "X$pid" = "X" ]
then
# Wrapper is not running so make sure the lock file is deleted.
if [ -f "$LOCKFILE" ]
then
rm "$LOCKFILE"
fi
fi
fi
exit $RUN_AS_USER_EXITCODE
fi
}
getpid() {
pid=""
if [ -f "$PIDFILE" ]
then
if [ -r "$PIDFILE" ]
then
pid=`cat "$PIDFILE"`
if [ "X$pid" != "X" ]
then
if [ "X$PIDFILE_CHECK_PID" != "X" ]
then
# It is possible that 'a' process with the pid exists but that it is not the
# correct process. This can happen in a number of cases, but the most
# common is during system startup after an unclean shutdown.
# The ps statement below looks for the specific wrapper command running as
# the pid. If it is not found then the pid file is considered to be stale.
case "$DIST_OS" in
'freebsd')
pidtest=`$PSEXE -p $pid -o args | tail -1`
if [ "X$pidtest" = "XCOMMAND" ]
then
pidtest=""
fi
;;
'macosx')
pidtest=`$PSEXE -ww -p $pid -o command | grep -F "$WRAPPER_CMD" | tail -1`
;;
'solaris')
if [ -f "/usr/bin/pargs" ]
then
pidtest=`pargs $pid | fgrep "$WRAPPER_CMD" | tail -1`
else
case "$PSEXE" in
'/usr/ucb/ps')
pidtest=`$PSEXE -auxww $pid | fgrep "$WRAPPER_CMD" | tail -1`
;;
'/usr/bin/ps')
TRUNCATED_CMD=`$PSEXE -o comm -p $pid | tail -1`
COUNT=`echo $TRUNCATED_CMD | wc -m`
COUNT=`echo ${COUNT}`
COUNT=`expr $COUNT - 1`
TRUNCATED_CMD=`echo $WRAPPER_CMD | cut -c1-$COUNT`
pidtest=`$PSEXE -o comm -p $pid | fgrep "$TRUNCATED_CMD" | tail -1`
;;
'/bin/ps')
TRUNCATED_CMD=`$PSEXE -o comm -p $pid | tail -1`
COUNT=`echo $TRUNCATED_CMD | wc -m`
COUNT=`echo ${COUNT}`
COUNT=`expr $COUNT - 1`
TRUNCATED_CMD=`echo $WRAPPER_CMD | cut -c1-$COUNT`
pidtest=`$PSEXE -o comm -p $pid | fgrep "$TRUNCATED_CMD" | tail -1`
;;
*)
echo "Unsupported ps command $PSEXE"
exit 1
;;
esac
fi
;;
'hpux')
pidtest=`$PSEXE -p $pid -x -o args | grep -F "$WRAPPER_CMD" | tail -1`
;;
*)
pidtest=`$PSEXE -p $pid -o args | grep -F "$WRAPPER_CMD" | tail -1`
;;
esac
else
# Check to see whether the pid exists as a running process, but in this mode, don't check what that pid is.
case "$DIST_OS" in
'solaris')
case "$PSEXE" in
'/usr/ucb/ps')
pidtest=`$PSEXE $pid | grep "$pid" | awk '{print $1}' | tail -1`
;;
'/usr/bin/ps')
pidtest=`$PSEXE -p $pid -o pid | grep "$pid" | tail -1`
;;
'/bin/ps')
pidtest=`$PSEXE -p $pid -o pid | grep "$pid" | tail -1`
;;
*)
echo "Unsupported ps command $PSEXE"
exit 1
;;
esac
;;
*)
pidtest=`$PSEXE -p $pid -o pid | grep "$pid" | tail -1`
;;
esac
fi
if [ "X$pidtest" = "X" ]
then
# This is a stale pid file.
rm -f "$PIDFILE"
eval echo `gettext 'Removed stale pid file: $PIDFILE'`
pid=""
fi
fi
else
eval echo `gettext 'Cannot read $PIDFILE.'`
exit 1
fi
fi
}
getstatus() {
STATUS=
if [ -f "$STATUSFILE" ]
then
if [ -r "$STATUSFILE" ]
then
STATUS=`cat "$STATUSFILE"`
fi
fi
if [ "X$STATUS" = "X" ]
then
STATUS="Unknown"
fi
JAVASTATUS=
if [ -f "$JAVASTATUSFILE" ]
then
if [ -r "$JAVASTATUSFILE" ]
then
JAVASTATUS=`cat "$JAVASTATUSFILE"`
fi
fi
if [ "X$JAVASTATUS" = "X" ]
then
JAVASTATUS="Unknown"
fi
}
testpid() {
case "$DIST_OS" in
'solaris')
case "$PSEXE" in
'/usr/ucb/ps')
pid=`$PSEXE $pid | grep $pid | grep -v grep | awk '{print $1}' | tail -1`
;;
'/usr/bin/ps')
pid=`$PSEXE -p $pid | grep $pid | grep -v grep | awk '{print $1}' | tail -1`
;;
'/bin/ps')
pid=`$PSEXE -p $pid | grep $pid | grep -v grep | awk '{print $1}' | tail -1`
;;
*)
echo "Unsupported ps command $PSEXE"
exit 1
;;
esac
;;
*)
pid=`$PSEXE -p $pid | grep $pid | grep -v grep | awk '{print $1}' | tail -1` 2>/dev/null
;;
esac
if [ "X$pid" = "X" ]
then
# Process is gone so remove the pid file.
rm -f "$PIDFILE"
pid=""
fi
}
launchdtrap() {
stopit
exit
}
waitforwrapperstop() {
getpid
while [ "X$pid" != "X" ] ; do
sleep 1
getpid
done
}
launchinternal() {
getpid
trap launchdtrap TERM
if [ "X$pid" = "X" ]
then
prepAdditionalParams "$@"
# The string passed to eval must handles spaces in paths correctly.
COMMAND_LINE="$CMDNICE \"$WRAPPER_CMD\" \"$WRAPPER_CONF\" wrapper.syslog.ident=\"$APP_NAME\" wrapper.pidfile=\"$PIDFILE\" wrapper.name=\"$APP_NAME\" wrapper.displayname=\"$APP_LONG_NAME\" wrapper.daemonize=TRUE $ANCHORPROP $IGNOREPROP $STATUSPROP $COMMANDPROP $LOCKPROP wrapper.script.version=3.5.22 $ADDITIONAL_PARA"
eval $COMMAND_LINE
else
eval echo `gettext '$APP_LONG_NAME is already running.'`
exit 1
fi
# launchd expects that this script stay up and running so we need to do our own monitoring of the Wrapper process.
if [ $WAIT_FOR_STARTED_STATUS = true ]
then
waitforwrapperstop
fi
}
console() {
eval echo `gettext 'Running $APP_LONG_NAME...'`
getpid
if [ "X$pid" = "X" ]
then
trap '' 3
prepAdditionalParams "$@"
# The string passed to eval must handles spaces in paths correctly.
COMMAND_LINE="$CMDNICE \"$WRAPPER_CMD\" \"$WRAPPER_CONF\" wrapper.syslog.ident=\"$APP_NAME\" wrapper.pidfile=\"$PIDFILE\" wrapper.name=\"$APP_NAME\" wrapper.displayname=\"$APP_LONG_NAME\" $ANCHORPROP $STATUSPROP $COMMANDPROP $LOCKPROP wrapper.script.version=3.5.22 $ADDITIONAL_PARA"
eval $COMMAND_LINE
else
eval echo `gettext '$APP_LONG_NAME is already running.'`
exit 1
fi
}
waitforjavastartup() {
getstatus
eval echo $ECHOOPT `gettext 'Waiting for $APP_LONG_NAME...'`
# Wait until the timeout or we have something besides Unknown.
counter=15
while [ "$JAVASTATUS" = "Unknown" -a $counter -gt 0 -a -n "$JAVASTATUS" ] ; do
echo $ECHOOPT"."
sleep 1
getstatus
counter=`expr $counter - 1`
done
if [ -n "$WAIT_FOR_STARTED_TIMEOUT" ] ; then
counter=$WAIT_FOR_STARTED_TIMEOUT
else
counter=120
fi
while [ "$JAVASTATUS" != "STARTED" -a "$JAVASTATUS" != "Unknown" -a $counter -gt 0 -a -n "$JAVASTATUS" ] ; do
echo $ECHOOPT"."
sleep 1
getstatus
counter=`expr $counter - 1`
done
if [ "X$ECHOOPT" != "X" ] ; then
echo ""
fi
}
startwait() {
if [ $WAIT_FOR_STARTED_STATUS = true ]
then
waitforjavastartup
fi
# Sleep for a few seconds to allow for intialization if required
# then test to make sure we're still running.
#
i=0
while [ $i -lt $WAIT_AFTER_STARTUP ]
do
sleep 1
echo $ECHOOPT"."
i=`expr $i + 1`
done
if [ $WAIT_AFTER_STARTUP -gt 0 -o $WAIT_FOR_STARTED_STATUS = true ]
then
getpid
if [ "X$pid" = "X" ]
then
eval echo `gettext ' WARNING: $APP_LONG_NAME may have failed to start.'`
exit 1
else
eval echo `gettext ' running: PID:$pid'`
fi
else
echo ""
fi
}
macosxstart() {
# The daemon has been installed.
eval echo `gettext 'Starting $APP_LONG_NAME. Detected Mac OSX and installed launchd daemon.'`
if [ `id | sed 's/^uid=//;s/(.*$//'` != "0" ] ; then
eval echo `gettext 'Must be root to perform this action.'`
exit 1
fi
getpid
if [ "X$pid" != "X" ] ; then
eval echo `gettext '$APP_LONG_NAME is already running.'`
exit 1
fi
# If the daemon was just installed, it may not be loaded.
LOADED_PLIST=`launchctl list | grep ${APP_PLIST_BASE}`
if [ "X${LOADED_PLIST}" = "X" ] ; then
launchctl load /Library/LaunchDaemons/${APP_PLIST}
fi
# If launchd is set to run the daemon already at Load, we don't need to call start
getpid
if [ "X$pid" == "X" ] ; then
launchctl start ${APP_PLIST_BASE}
fi
startwait
}
upstartstart() {
# The daemon has been installed.
eval echo `gettext 'Starting $APP_LONG_NAME. Detected Linux and installed upstart.'`
if [ `id | sed 's/^uid=//;s/(.*$//'` != "0" ] ; then
eval echo `gettext 'Must be root to perform this action.'`
exit 1
fi
getpid
if [ "X$pid" != "X" ] ; then
eval echo `gettext '$APP_LONG_NAME is already running.'`
exit 1
fi
/sbin/start ${APP_NAME}
startwait
}
start() {
eval echo `gettext 'Starting $APP_LONG_NAME...'`
getpid
if [ "X$pid" = "X" ]
then
prepAdditionalParams "$@"
# The string passed to eval must handles spaces in paths correctly.
COMMAND_LINE="$CMDNICE \"$WRAPPER_CMD\" \"$WRAPPER_CONF\" wrapper.syslog.ident=\"$APP_NAME\" wrapper.pidfile=\"$PIDFILE\" wrapper.name=\"$APP_NAME\" wrapper.displayname=\"$APP_LONG_NAME\" wrapper.daemonize=TRUE $ANCHORPROP $IGNOREPROP $STATUSPROP $COMMANDPROP $LOCKPROP wrapper.script.version=3.5.22 $ADDITIONAL_PARA"
eval $COMMAND_LINE
else
eval echo `gettext '$APP_LONG_NAME is already running.'`
exit 1
fi
startwait
}
stopit() {
# $1 exit if down flag
eval echo `gettext 'Stopping $APP_LONG_NAME...'`
getpid
if [ "X$pid" = "X" ]
then
eval echo `gettext '$APP_LONG_NAME was not running.'`
if [ "X$1" = "X1" ]
then
exit 1
fi
else
if [ "X$IGNORE_SIGNALS" = "X" ]
then
# Running so try to stop it.
kill $pid
if [ $? -ne 0 ]
then
# An explanation for the failure should have been given
eval echo `gettext 'Unable to stop $APP_LONG_NAME.'`
exit 1
fi
else
rm -f "$ANCHORFILE"
if [ -f "$ANCHORFILE" ]
then
# An explanation for the failure should have been given
eval echo `gettext 'Unable to stop $APP_LONG_NAME.'`
exit 1
fi
fi
# We can not predict how long it will take for the wrapper to
# actually stop as it depends on settings in wrapper.conf.
# Loop until it does.
savepid=$pid
CNT=0
TOTCNT=0
while [ "X$pid" != "X" ]
do
# Show a waiting message every 5 seconds.
if [ "$CNT" -lt "5" ]
then
CNT=`expr $CNT + 1`
else
eval echo `gettext 'Waiting for $APP_LONG_NAME to exit...'`
CNT=0
fi
TOTCNT=`expr $TOTCNT + 1`
sleep 1
testpid
done
pid=$savepid
testpid
if [ "X$pid" != "X" ]
then
eval echo `gettext 'Failed to stop $APP_LONG_NAME.'`
exit 1
else
eval echo `gettext 'Stopped $APP_LONG_NAME.'`
fi
fi
}
pause() {
eval echo `gettext 'Pausing $APP_LONG_NAME.'`
}
resume() {
eval echo `gettext 'Resuming $APP_LONG_NAME.'`
}
status() {
getpid
if [ "X$pid" = "X" ]
then
eval echo `gettext '$APP_LONG_NAME is not running.'`
exit 1
else
if [ "X$DETAIL_STATUS" = "X" ]
then
eval echo `gettext '$APP_LONG_NAME is running: PID:$pid'`
else
getstatus
eval echo `gettext '$APP_LONG_NAME is running: PID:$pid, Wrapper:$STATUS, Java:$JAVASTATUS'`
fi
exit 0
fi
}
installUpstart() {
eval echo `gettext ' Installing the $APP_LONG_NAME daemon using upstart..'`
if [ -f "${REALDIR}/${APP_NAME}.install" ] ; then
eval echo `gettext ' a custom upstart conf file ${APP_NAME}.install found'`
cp "${REALDIR}/${APP_NAME}.install" "/etc/init/${APP_NAME}.conf"
else
eval echo `gettext ' creating default upstart conf file..'`
echo "# ${APP_NAME} - ${APP_LONG_NAME}" > "/etc/init/${APP_NAME}.conf"
echo "description \"${APP_LONG_NAME}\"" >> "/etc/init/${APP_NAME}.conf"
echo "author \"Tanuki Software Ltd. \"" >> "/etc/init/${APP_NAME}.conf"
echo "start on runlevel [2345]" >> "/etc/init/${APP_NAME}.conf"
echo "stop on runlevel [!2345]" >> "/etc/init/${APP_NAME}.conf"
echo "env LANG=${LANG}" >> "/etc/init/${APP_NAME}.conf"
echo "exec \"${REALPATH}\" upstartinternal" >> "/etc/init/${APP_NAME}.conf"
fi
}
installdaemon() {
if [ `id | sed 's/^uid=//;s/(.*$//'` != "0" ] ; then
eval echo `gettext 'Must be root to perform this action.'`
exit 1
else
APP_NAME_LOWER=`echo "$APP_NAME" | $TREXE "[A-Z]" "[a-z]"`
if [ "$DIST_OS" = "solaris" ] ; then
eval echo `gettext 'Detected Solaris:'`
if [ -f "/etc/init.d/$APP_NAME" -o -L "/etc/init.d/$APP_NAME" ] ; then
eval echo `gettext ' The $APP_LONG_NAME daemon is already installed.'`
exit 1
else
eval echo `gettext ' Installing the $APP_LONG_NAME daemon..'`
ln -s "$REALPATH" "/etc/init.d/$APP_NAME"
for i in `ls "/etc/rc3.d/K"??"$APP_NAME_LOWER" "/etc/rc3.d/S"??"$APP_NAME_LOWER" 2>/dev/null` ; do
eval echo `gettext ' Removing unexpected file before proceeding: $i'`
rm -f $i
done
ln -s "/etc/init.d/$APP_NAME" "/etc/rc3.d/K${APP_RUN_LEVEL_K}$APP_NAME_LOWER"
ln -s "/etc/init.d/$APP_NAME" "/etc/rc3.d/S${APP_RUN_LEVEL_S}$APP_NAME_LOWER"
fi
elif [ "$DIST_OS" = "linux" ] ; then
if [ -f /etc/redhat-release -o -f /etc/redhat_version -o -f /etc/fedora-release ] ; then
eval echo `gettext 'Detected RHEL or Fedora:'`
if [ -f "/etc/init.d/$APP_NAME" -o -L "/etc/init.d/$APP_NAME" -o -f "/etc/init/${APP_NAME}.conf" ] ; then
eval echo `gettext ' The $APP_LONG_NAME daemon is already installed.'`
exit 1
else
if [ -n "$USE_UPSTART" -a -d "/etc/init" ] ; then
installUpstart
else
eval echo `gettext ' Installing the $APP_LONG_NAME daemon..'`
ln -s "$REALPATH" "/etc/init.d/$APP_NAME"
/sbin/chkconfig --add "$APP_NAME"
/sbin/chkconfig "$APP_NAME" on
fi
fi
elif [ -f /etc/SuSE-release ] ; then
eval echo `gettext 'Detected SuSE or SLES:'`
if [ -f "/etc/init.d/$APP_NAME" -o -L "/etc/init.d/$APP_NAME" ] ; then
eval echo `gettext ' The $APP_LONG_NAME daemon is already installed.'`
exit 1
else
eval echo `gettext ' Installing the $APP_LONG_NAME daemon..'`
ln -s "$REALPATH" "/etc/init.d/$APP_NAME"
insserv "/etc/init.d/$APP_NAME"
fi
elif [ -f /etc/lsb-release -o -f /etc/debian_version -o -f /etc/debian_release ] ; then
eval echo `gettext 'Detected Ubuntu or Debian:'`
if [ -f "/etc/init.d/$APP_NAME" -o -L "/etc/init.d/$APP_NAME" -o -f "/etc/init/${APP_NAME}.conf" ] ; then
eval echo `gettext ' The $APP_LONG_NAME daemon is already installed.'`
exit 1
else
if [ -n "$USE_UPSTART" -a -d "/etc/init" ] ; then
installUpstart
else
eval echo `gettext ' Installing the $APP_LONG_NAME daemon using init.d..'`
ln -s "$REALPATH" "/etc/init.d/$APP_NAME"
update-rc.d "$APP_NAME" defaults
fi
fi
else
eval echo `gettext 'Detected Linux:'`
if [ -f "/etc/init.d/$APP_NAME" -o -L "/etc/init.d/$APP_NAME" ] ; then
eval echo `gettext ' The $APP_LONG_NAME daemon is already installed.'`
exit 1
else
eval echo `gettext ' Installing the $APP_LONG_NAME daemon..'`
ln -s "$REALPATH" /etc/init.d/$APP_NAME
for i in `ls "/etc/rc3.d/K"??"$APP_NAME_LOWER" "/etc/rc5.d/K"??"$APP_NAME_LOWER" "/etc/rc3.d/S"??"$APP_NAME_LOWER" "/etc/rc5.d/S"??"$APP_NAME_LOWER" 2>/dev/null` ; do
eval echo `gettext ' Removing unexpected file before proceeding: $i'`
rm -f $i
done
ln -s "/etc/init.d/$APP_NAME" "/etc/rc3.d/K${APP_RUN_LEVEL_K}$APP_NAME_LOWER"
ln -s "/etc/init.d/$APP_NAME" "/etc/rc3.d/S${APP_RUN_LEVEL_S}$APP_NAME_LOWER"
ln -s "/etc/init.d/$APP_NAME" "/etc/rc5.d/S${APP_RUN_LEVEL_S}$APP_NAME_LOWER"
ln -s "/etc/init.d/$APP_NAME" "/etc/rc5.d/K${APP_RUN_LEVEL_K}$APP_NAME_LOWER"
fi
fi
elif [ "$DIST_OS" = "hpux" ] ; then
eval echo `gettext 'Detected HP-UX:'`
if [ -f "/sbin/init.d/$APP_NAME" -o -L "/sbin/init.d/$APP_NAME" ] ; then
eval echo `gettext ' The $APP_LONG_NAME daemon is already installed.'`
exit 1
else
eval echo `gettext ' Installing the $APP_LONG_NAME daemon..'`
ln -s "$REALPATH" "/sbin/init.d/$APP_NAME"
for i in `ls "/etc/rc3.d/K"??"$APP_NAME_LOWER" "/etc/rc3.d/S"??"$APP_NAME_LOWER" 2>/dev/null` ; do
eval echo `gettext ' Removing unexpected file before proceeding: $i'`
rm -f $i
done
ln -s "/sbin/init.d/$APP_NAME" "/sbin/rc3.d/K${APP_RUN_LEVEL_K}$APP_NAME_LOWER"
ln -s "/sbin/init.d/$APP_NAME" "/sbin/rc3.d/S${APP_RUN_LEVEL_S}$APP_NAME_LOWER"
fi
elif [ "$DIST_OS" = "aix" ] ; then
eval echo `gettext 'Detected AIX:'`
if [ -f "/etc/rc.d/init.d/$APP_NAME" ] ; then
eval echo `gettext ' The $APP_LONG_NAME daemon is already installed as rc.d script.'`
exit 1
elif [ -n "`/usr/sbin/lsitab $APP_NAME`" -a -n "`/usr/bin/lssrc -S -s $APP_NAME`" ] ; then
eval echo `gettext ' The $APP_LONG_NAME daemon is already installed as SRC service.'`
exit 1
else
eval echo `gettext ' Installing the $APP_LONG_NAME daemon..'`
if [ -n "`/usr/sbin/lsitab install_assist`" ] ; then
eval echo `gettext ' The task /usr/sbin/install_assist was found in the inittab, this might cause problems for all subsequent tasks to launch at this process is known to block the init task. Please make sure this task is not needed anymore and remove/deactivate it.'`
fi
for i in `ls "/etc/rc.d/rc2.d/K"??"$APP_NAME_LOWER" "/etc/rc.d/rc2.d/S"??"$APP_NAME_LOWER" 2>/dev/null` ; do
eval echo `gettext ' Removing unexpected file before proceeding: $i'`
rm -f $i
done
/usr/bin/mkssys -s "$APP_NAME" -p "$REALPATH" -a "launchdinternal" -u 0 -f 9 -n 15 -S
/usr/sbin/mkitab "$APP_NAME":2:once:"/usr/bin/startsrc -s \"${APP_NAME}\" >/dev/console 2>&1"
fi
elif [ "$DIST_OS" = "freebsd" ] ; then
eval echo `gettext 'Detected FreeBSD:'`
if [ -f "/etc/rc.d/$APP_NAME" -o -L "/etc/rc.d/$APP_NAME" ] ; then
eval echo `gettext ' The $APP_LONG_NAME daemon is already installed.'`
exit 1
else
eval echo `gettext ' Installing the $APP_LONG_NAME daemon..'`
sed -i .bak "/${APP_NAME}_enable=\"YES\"/d" /etc/rc.conf
if [ -f "${REALDIR}/${APP_NAME}.install" ] ; then
ln -s "${REALDIR}/${APP_NAME}.install" "/etc/rc.d/$APP_NAME"
else
echo '#!/bin/sh' > "/etc/rc.d/$APP_NAME"
echo "#" >> "/etc/rc.d/$APP_NAME"
echo "# PROVIDE: $APP_NAME" >> "/etc/rc.d/$APP_NAME"
echo "# REQUIRE: NETWORKING" >> "/etc/rc.d/$APP_NAME"
echo "# KEYWORD: shutdown" >> "/etc/rc.d/$APP_NAME"
echo ". /etc/rc.subr" >> "/etc/rc.d/$APP_NAME"
echo "name=\"$APP_NAME\"" >> "/etc/rc.d/$APP_NAME"
echo "rcvar=\`set_rcvar\`" >> "/etc/rc.d/$APP_NAME"
echo "command=\"${REALPATH}\"" >> "/etc/rc.d/$APP_NAME"
echo 'start_cmd="${name}_start"' >> "/etc/rc.d/$APP_NAME"
echo 'load_rc_config $name' >> "/etc/rc.d/$APP_NAME"
echo 'status_cmd="${name}_status"' >> "/etc/rc.d/$APP_NAME"
echo 'stop_cmd="${name}_stop"' >> "/etc/rc.d/$APP_NAME"
echo "${APP_NAME}_status() {" >> "/etc/rc.d/$APP_NAME"
echo '${command} status' >> "/etc/rc.d/$APP_NAME"
echo '}' >> "/etc/rc.d/$APP_NAME"
echo "${APP_NAME}_stop() {" >> "/etc/rc.d/$APP_NAME"
echo '${command} stop' >> "/etc/rc.d/$APP_NAME"
echo '}' >> "/etc/rc.d/$APP_NAME"
echo "${APP_NAME}_start() {" >> "/etc/rc.d/$APP_NAME"
echo '${command} start' >> "/etc/rc.d/$APP_NAME"
echo '}' >> "/etc/rc.d/$APP_NAME"
echo 'run_rc_command "$1"' >> "/etc/rc.d/$APP_NAME"
fi
echo "${APP_NAME}_enable=\"YES\"" >> /etc/rc.conf
chmod 555 "/etc/rc.d/$APP_NAME"
fi
elif [ "$DIST_OS" = "macosx" ] ; then
eval echo `gettext 'Detected Mac OSX:'`
if [ -f "/Library/LaunchDaemons/${APP_PLIST}" -o -L "/Library/LaunchDaemons/${APP_PLIST}" ] ; then
eval echo `gettext ' The $APP_LONG_NAME daemon is already installed.'`
exit 1
else
eval echo `gettext ' Installing the $APP_LONG_NAME daemon..'`
if [ -f "${REALDIR}/${APP_PLIST}" ] ; then
ln -s "${REALDIR}/${APP_PLIST}" "/Library/LaunchDaemons/${APP_PLIST}"
else
echo "" > "/Library/LaunchDaemons/${APP_PLIST}"
echo "> "/Library/LaunchDaemons/${APP_PLIST}"
echo "\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">" >> "/Library/LaunchDaemons/${APP_PLIST}"
echo "" >> "/Library/LaunchDaemons/${APP_PLIST}"
echo " " >> "/Library/LaunchDaemons/${APP_PLIST}"
echo " Label" >> "/Library/LaunchDaemons/${APP_PLIST}"
echo " ${APP_PLIST_BASE}" >> "/Library/LaunchDaemons/${APP_PLIST}"
echo " ProgramArguments" >> "/Library/LaunchDaemons/${APP_PLIST}"
echo " " >> "/Library/LaunchDaemons/${APP_PLIST}"
echo " ${REALPATH}" >> "/Library/LaunchDaemons/${APP_PLIST}"
echo " launchdinternal" >> "/Library/LaunchDaemons/${APP_PLIST}"
echo " " >> "/Library/LaunchDaemons/${APP_PLIST}"
echo " OnDemand" >> "/Library/LaunchDaemons/${APP_PLIST}"
echo " " >> "/Library/LaunchDaemons/${APP_PLIST}"
echo " RunAtLoad" >> "/Library/LaunchDaemons/${APP_PLIST}"
echo " " >> "/Library/LaunchDaemons/${APP_PLIST}"
if [ "X$RUN_AS_USER" != "X" ] ; then
echo " UserName" >> "/Library/LaunchDaemons/${APP_PLIST}"
echo " ${RUN_AS_USER}" >> "/Library/LaunchDaemons/${APP_PLIST}"
fi
echo " " >> "/Library/LaunchDaemons/${APP_PLIST}"
echo "" >> "/Library/LaunchDaemons/${APP_PLIST}"
fi
chmod 555 "/Library/LaunchDaemons/${APP_PLIST}"
fi
elif [ "$DIST_OS" = "zos" ] ; then
eval echo `gettext 'Detected z/OS:'`
if [ -f /etc/rc.bak ] ; then
eval echo `gettext ' The $APP_LONG_NAME daemon is already installed.'`
exit 1
else
eval echo `gettext ' Installing the $APP_LONG_NAME daemon..'`
cp /etc/rc /etc/rc.bak
sed "s:echo /etc/rc script executed, \`date\`::g" /etc/rc.bak > /etc/rc
echo "_BPX_JOBNAME='${APP_NAME}' \"${REALDIR}/${APP_NAME}\" start" >>/etc/rc
echo '/etc/rc script executed, `date`' >>/etc/rc
fi
else
eval echo `gettext 'Install not currently supported for $DIST_OS'`
exit 1
fi
fi
}
removedaemon() {
if [ `id | sed 's/^uid=//;s/(.*$//'` != "0" ] ; then
eval echo `gettext 'Must be root to perform this action.'`
exit 1
else
APP_NAME_LOWER=`echo "$APP_NAME" | $TREXE "[A-Z]" "[a-z]"`
if [ "$DIST_OS" = "solaris" ] ; then
eval echo `gettext 'Detected Solaris:'`
if [ -f "/etc/init.d/$APP_NAME" -o -L "/etc/init.d/$APP_NAME" ] ; then
stopit "0"
eval echo `gettext ' Removing $APP_LONG_NAME daemon...'`
for i in `ls "/etc/rc3.d/K"??"$APP_NAME_LOWER" "/etc/rc3.d/S"??"$APP_NAME_LOWER" "/etc/init.d/$APP_NAME" 2>/dev/null` ; do
rm -f $i
done
else
eval echo `gettext ' The $APP_LONG_NAME daemon is not currently installed.'`
exit 1
fi
elif [ "$DIST_OS" = "linux" ] ; then
if [ -f /etc/redhat-release -o -f /etc/redhat_version -o -f /etc/fedora-release ] ; then
eval echo `gettext 'Detected RHEL or Fedora:'`
if [ -f "/etc/init.d/$APP_NAME" -o -L "/etc/init.d/$APP_NAME" ] ; then
stopit "0"
eval echo `gettext ' Removing $APP_LONG_NAME daemon...'`
/sbin/chkconfig "$APP_NAME" off
/sbin/chkconfig --del "$APP_NAME"
rm -f "/etc/init.d/$APP_NAME"
elif [ -f "/etc/init/${APP_NAME}.conf" ] ; then
stopit "0"
eval echo `gettext ' Removing $APP_LONG_NAME daemon from upstart...'`
rm "/etc/init/${APP_NAME}.conf"
else
eval echo `gettext ' The $APP_LONG_NAME daemon is not currently installed.'`
exit 1
fi
elif [ -f /etc/SuSE-release ] ; then
eval echo `gettext 'Detected SuSE or SLES:'`
if [ -f "/etc/init.d/$APP_NAME" -o -L "/etc/init.d/$APP_NAME" ] ; then
stopit "0"
eval echo `gettext ' Removing $APP_LONG_NAME daemon...'`
insserv -r "/etc/init.d/$APP_NAME"
rm -f "/etc/init.d/$APP_NAME"
else
eval echo `gettext ' The $APP_LONG_NAME daemon is not currently installed.'`
exit 1
fi
elif [ -f /etc/lsb-release -o -f /etc/debian_version -o -f /etc/debian_release ] ; then
eval echo `gettext 'Detected Ubuntu or Debian:'`
if [ -f "/etc/init.d/$APP_NAME" -o -L "/etc/init.d/$APP_NAME" ] ; then
stopit "0"
eval echo `gettext ' Removing $APP_LONG_NAME daemon from init.d...'`
update-rc.d -f "$APP_NAME" remove
rm -f "/etc/init.d/$APP_NAME"
elif [ -f "/etc/init/${APP_NAME}.conf" ] ; then
stopit "0"
eval echo `gettext ' Removing $APP_LONG_NAME daemon from upstart...'`
rm "/etc/init/${APP_NAME}.conf"
else
eval echo `gettext ' The $APP_LONG_NAME daemon is not currently installed.'`
exit 1
fi
else
eval echo `gettext 'Detected Linux:'`
if [ -f "/etc/init.d/$APP_NAME" -o -L "/etc/init.d/$APP_NAME" ] ; then
stopit "0"
eval echo `gettext ' Removing $APP_LONG_NAME daemon...'`
for i in `ls "/etc/rc3.d/K"??"$APP_NAME_LOWER" "/etc/rc5.d/K"??"$APP_NAME_LOWER" "/etc/rc3.d/S"??"$APP_NAME_LOWER" "/etc/rc5.d/S"??"$APP_NAME_LOWER" "/etc/init.d/$APP_NAME" 2>/dev/null` ; do
rm -f $i
done
else
eval echo `gettext ' The $APP_LONG_NAME daemon is not currently installed.'`
exit 1
fi
fi
elif [ "$DIST_OS" = "hpux" ] ; then
eval echo `gettext 'Detected HP-UX:'`
if [ -f "/sbin/init.d/$APP_NAME" -o -L "/sbin/init.d/$APP_NAME" ] ; then
stopit "0"
eval echo `gettext ' Removing $APP_LONG_NAME daemon...'`
for i in `ls "/etc/rc3.d/K"??"$APP_NAME_LOWER" "/etc/rc3.d/S"??"$APP_NAME_LOWER" "/etc/init.d/$APP_NAME" 2>/dev/null` ; do
rm -f $i
done
else
eval echo `gettext ' The $APP_LONG_NAME daemon is not currently installed.'`
exit 1
fi
elif [ "$DIST_OS" = "aix" ] ; then
eval echo `gettext 'Detected AIX:'`
if [ -f "/etc/rc.d/init.d/$APP_NAME" -o -L "/etc/rc.d/init.d/$APP_NAME" -o -n "`/usr/sbin/lsitab $APP_NAME`" -o -n "`/usr/bin/lssrc -S -s $APP_NAME`" ] ; then
stopit "0"
eval echo `gettext ' Removing $APP_LONG_NAME daemon...'`
if [ -f "/etc/rc.d/init.d/$APP_NAME" -o -L "/etc/rc.d/init.d/$APP_NAME" ] ; then
for i in `ls "/etc/rc.d/rc2.d/K"??"$APP_NAME_LOWER" "/etc/rc.d/rc2.d/S"??"$APP_NAME_LOWER" "/etc/rc.d/init.d/$APP_NAME" 2>/dev/null` ; do
rm -f $i
done
fi
if [ -n "`/usr/sbin/lsitab $APP_NAME`" -o -n "`/usr/bin/lssrc -S -s $APP_NAME`" ] ; then
/usr/sbin/rmitab $APP_NAME
/usr/bin/rmssys -s $APP_NAME
fi
else
eval echo `gettext ' The $APP_LONG_NAME daemon is not currently installed.'`
exit 1
fi
elif [ "$DIST_OS" = "freebsd" ] ; then
eval echo `gettext 'Detected FreeBSD:'`
if [ -f "/etc/rc.d/$APP_NAME" -o -L "/etc/rc.d/$APP_NAME" ] ; then
stopit "0"
eval echo `gettext ' Removing $APP_LONG_NAME daemon...'`
for i in "/etc/rc.d/$APP_NAME"
do
rm -f $i
done
sed -i .bak "/${APP_NAME}_enable=\"YES\"/d" /etc/rc.conf
else
eval echo `gettext ' The $APP_LONG_NAME daemon is not currently installed.'`
exit 1
fi
elif [ "$DIST_OS" = "macosx" ] ; then
eval echo `gettext 'Detected Mac OSX:'`
if [ -f "/Library/LaunchDaemons/${APP_PLIST}" -o -L "/Library/LaunchDaemons/${APP_PLIST}" ] ; then
stopit "0"
eval echo `gettext ' Removing $APP_LONG_NAME daemon...'`
# Make sure the plist is installed
LOADED_PLIST=`launchctl list | grep ${APP_PLIST_BASE}`
if [ "X${LOADED_PLIST}" != "X" ] ; then
launchctl unload "/Library/LaunchDaemons/${APP_PLIST}"
fi
rm -f "/Library/LaunchDaemons/${APP_PLIST}"
else
eval echo `gettext ' The $APP_LONG_NAME daemon is not currently installed.'`
exit 1
fi
elif [ "$DIST_OS" = "zos" ] ; then
eval echo `gettext 'Detected z/OS:'`
if [ -f /etc/rc.bak ] ; then
stopit "0"
eval echo `gettext ' Removing $APP_LONG_NAME daemon...'`
cp /etc/rc /etc/rc.bak
sed "s/_BPX_JOBNAME=\'APP_NAME\'.*//g" /etc/rc.bak > /etc/rc
rm /etc/rc.bak
else
eval echo `gettext ' The $APP_LONG_NAME daemon is not currently installed.'`
exit 1
fi
else
eval echo `gettext 'Remove not currently supported for $DIST_OS'`
exit 1
fi
fi
}
dump() {
eval echo `gettext 'Dumping $APP_LONG_NAME...'`
getpid
if [ "X$pid" = "X" ]
then
eval echo `gettext '$APP_LONG_NAME was not running.'`
else
kill -3 $pid
if [ $? -ne 0 ]
then
eval echo `gettext 'Failed to dump $APP_LONG_NAME.'`
exit 1
else
eval echo `gettext 'Dumped $APP_LONG_NAME.'`
fi
fi
}
# Used by HP-UX init scripts.
startmsg() {
getpid
if [ "X$pid" = "X" ]
then
eval echo `gettext 'Starting $APP_LONG_NAME... Wrapper:Stopped'`
else
if [ "X$DETAIL_STATUS" = "X" ]
then
eval echo `gettext 'Starting $APP_LONG_NAME... Wrapper:Running'`
else
getstatus
eval echo `gettext 'Starting $APP_LONG_NAME... Wrapper:$STATUS, Java:$JAVASTATUS'`
fi
fi
}
# Used by HP-UX init scripts.
stopmsg() {
getpid
if [ "X$pid" = "X" ]
then
eval echo `gettext 'Stopping $APP_LONG_NAME... Wrapper:Stopped'`
else
if [ "X$DETAIL_STATUS" = "X" ]
then
eval echo `gettext 'Stopping $APP_LONG_NAME... Wrapper:Running'`
else
getstatus
eval echo `gettext 'Stopping $APP_LONG_NAME... Wrapper:$STATUS, Java:$JAVASTATUS'`
fi
fi
}
showUsage() {
# $1 bad command
if [ -n "$1" ]
then
eval echo `gettext 'Unexpected command: $1'`
echo "";
fi
eval MSG=`gettext 'Usage: '`
if [ -n "$FIXED_COMMAND" ] ; then
if [ -n "$PASS_THROUGH" ] ; then
echo "${MSG} $0 {JavaAppArgs}"
else
echo "${MSG} $0"
fi
else
if [ -n "$PAUSABLE" ] ; then
if [ -n "$PASS_THROUGH" ] ; then
echo "${MSG} $0 [ console {JavaAppArgs} | start {JavaAppArgs} | stop | restart {JavaAppArgs} | condrestart {JavaAppArgs} | pause | resume | status | install | remove | dump ]"
else
echo "${MSG} $0 [ console | start | stop | restart | condrestart | pause | resume | status | install | remove | dump ]"
fi
else
if [ -n "$PASS_THROUGH" ] ; then
echo "${MSG} $0 [ console {JavaAppArgs} | start {JavaAppArgs} | stop | restart {JavaAppArgs} | condrestart {JavaAppArgs} | status | install | remove | dump ]"
else
echo "${MSG} $0 [ console | start | stop | restart | condrestart | status | install | remove | dump ]"
fi
fi
fi
if [ ! -n "$BRIEF_USAGE" ]
then
echo "";
if [ ! -n "$FIXED_COMMAND" ] ; then
echo "`gettext 'Commands:'`"
echo "`gettext ' console Launch in the current console.'`"
echo "`gettext ' start Start in the background as a daemon process.'`"
echo "`gettext ' stop Stop if running as a daemon or in another console.'`"
echo "`gettext ' restart Stop if running and then start.'`"
echo "`gettext ' condrestart Restart only if already running.'`"
if [ -n "$PAUSABLE" ] ; then
echo "`gettext ' pause Pause if running.'`"
echo "`gettext ' resume Resume if paused.'`"
fi
echo "`gettext ' status Query the current status.'`"
echo "`gettext ' install Install to start automatically when system boots.'`"
echo "`gettext ' remove Uninstall.'`"
echo "`gettext ' dump Request a Java thread dump if running.'`"
echo "";
fi
if [ -n "$PASS_THROUGH" ] ; then
echo "`gettext 'JavaAppArgs: Zero or more arguments which will be passed to the Java application.'`"
echo "";
fi
fi
exit 1
}
docommand() {
case "$COMMAND" in
'console')
checkUser touchlock "$@"
if [ ! -n "$FIXED_COMMAND" ] ; then
shift
fi
console "$@"
;;
'start')
if [ "$DIST_OS" = "macosx" -a -f "/Library/LaunchDaemons/${APP_PLIST}" ] ; then
macosxstart
elif [ "$DIST_OS" = "linux" -a -f "/etc/init/${APP_NAME}.conf" ] ; then
upstartstart
else
checkUser touchlock "$@"
if [ ! -n "$FIXED_COMMAND" ] ; then
shift
fi
start "$@"
fi
;;
'stop')
checkUser "" "$COMMAND"
stopit "0"
;;
'restart')
checkUser touchlock "$COMMAND"
if [ ! -n "$FIXED_COMMAND" ] ; then
shift
fi
stopit "0"
start "$@"
;;
'condrestart')
checkUser touchlock "$COMMAND"
if [ ! -n "$FIXED_COMMAND" ] ; then
shift
fi
stopit "1"
start "$@"
;;
'pause')
if [ -n "$PAUSABLE" ]
then
pause
else
showUsage "$COMMAND"
fi
;;
'resume')
if [ -n "$PAUSABLE" ]
then
resume
else
showUsage "$COMMAND"
fi
;;
'status')
status
;;
'install')
installdaemon
;;
'remove')
removedaemon
;;
'dump')
checkUser "" "$COMMAND"
dump
;;
'start_msg')
# Internal command called by launchd on HP-UX.
checkUser "" "$COMMAND"
startmsg
;;
'stop_msg')
# Internal command called by launchd on HP-UX.
checkUser "" "$COMMAND"
stopmsg
;;
'launchdinternal' | 'upstartinternal')
if [ ! "$DIST_OS" = "macosx" -o ! -f "/Library/LaunchDaemons/${APP_PLIST}" ] ; then
checkUser touchlock "$@"
fi
# Internal command called by launchd on Max OSX.
# We do not want to call checkUser here as it is handled in the launchd plist file. Doing it here would confuse launchd.
if [ ! -n "$FIXED_COMMAND" ] ; then
shift
fi
launchinternal "$@"
;;
*)
showUsage "$COMMAND"
;;
esac
}
docommand "$@"
exit 0
wrapper_3.5.22_src/src/c/MSG00001.bin 100644 0 0 300 12224722007 14024 0 ustar 0 0 d d jvm1
jvm2
jvm3
jvm4
jvm5
jvm6
jvm7
jvm8
jvm9
jvmxx
wrapper
wrapperp
%2
wrapper_3.5.22_src/src/c/Makefile-aix-ppc-32.gmake 100644 0 0 2214 12224722005 16653 0 ustar 0 0 # Copyright (c) 1999, 2012 Tanuki Software, Ltd.
# http://www.tanukisoftware.com
# All rights reserved.
#
# This software is the proprietary information of Tanuki Software.
# You shall use it only in accordance with the terms of the
# license agreement you entered into with Tanuki Software.
# http://wrapper.tanukisoftware.com/doc/english/licenseOverview.html
COMPILE = gcc -DAIX -D_THREAD_SAFE -DUNICODE -D_UNICODE
INCLUDE=$(JAVA_HOME)/include
DEFS = -I$(INCLUDE) -I$(INCLUDE)/aix
wrapper_SOURCE = wrapper.c wrapperinfo.c wrappereventloop.c wrapper_unix.c property.c logger.c wrapper_file.c wrapper_i18n.c
libwrapper_a_OBJECTS = wrapper_i18n.o wrapperjni_unix.o wrapperinfo.o wrapperjni.o
BIN = ../../bin
LIB = ../../lib
all: init wrapper libwrapper.a
clean:
rm -f *.o
cleanall: clean
rm -rf *~ .deps
rm -f $(BIN)/wrapper $(LIB)/libwrapper.a
init:
if test ! -d .deps; then mkdir .deps; fi
wrapper: $(wrapper_SOURCE)
$(COMPILE) -lpthread -lnsl -lm $(wrapper_SOURCE) -o $(BIN)/wrapper
libwrapper.a: $(libwrapper_a_OBJECTS)
${COMPILE} -shared $(libwrapper_a_OBJECTS) -o $(LIB)/libwrapper.a
%.o: %.c
${COMPILE} -c ${DEFS} $<
wrapper_3.5.22_src/src/c/Makefile-aix-ppc-32.make 100644 0 0 2660 12224722006 16512 0 ustar 0 0 # Copyright (c) 1999, 2013 Tanuki Software, Ltd.
# http://www.tanukisoftware.com
# All rights reserved.
#
# This software is the proprietary information of Tanuki Software.
# You shall use it only in accordance with the terms of the
# license agreement you entered into with Tanuki Software.
# http://wrapper.tanukisoftware.com/doc/english/licenseOverview.html
COMPILE = gcc -O3 -fPIC --pedantic -DAIX -D_FILE_OFFSET_BITS=64 -liconv -DUNICODE -D_UNICODE -D_THREAD_SAFE
INCLUDE=$(JAVA_HOME)/include
DEFS = -I$(INCLUDE) -I$(INCLUDE)/aix
wrapper_SOURCE = wrapper.c wrapperinfo.c wrappereventloop.c wrapper_unix.c property.c logger.c wrapper_file.c wrapper_i18n.c wrapper_hashmap.c
libwrapper_a_SOURCE = wrapper_i18n.c wrapperjni_unix.c wrapperinfo.c wrapperjni.c
BIN = ../../bin
LIB = ../../lib
all: init wrapper libwrapper.a
clean:
rm -f *.o
cleanall: clean
rm -rf *~ .deps
rm -f $(BIN)/wrapper $(LIB)/libwrapper.a
init:
if test ! -d .deps; then mkdir .deps; fi
wrapper: $(wrapper_SOURCE)
$(COMPILE) -lpthread -lnsl -lm $(wrapper_SOURCE) -o $(BIN)/wrapper
libwrapper.a: $(libwrapper_a_SOURCE)
${COMPILE} $(DEFS) -shared -lpthread $(libwrapper_a_SOURCE) -o $(LIB)/libwrapper.a
%.o: %.c
@echo '$(COMPILE) -c $<'; \
$(COMPILE) $(DEFS) -Wp,-MD,.deps/$(*F).pp -c $<
@-cp .deps/$(*F).pp .deps/$(*F).P; \
tr ' ' '\012' < .deps/$(*F).pp \
| sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
>> .deps/$(*F).P; \
rm .deps/$(*F).pp
wrapper_3.5.22_src/src/c/Makefile-aix-ppc-64.gmake 100644 0 0 2210 12224722007 16656 0 ustar 0 0 # Copyright (c) 1999, 2012 Tanuki Software, Ltd.
# http://www.tanukisoftware.com
# All rights reserved.
#
# This software is the proprietary information of Tanuki Software.
# You shall use it only in accordance with the terms of the
# license agreement you entered into with Tanuki Software.
# http://wrapper.tanukisoftware.com/doc/english/licenseOverview.html
COMPILE = gcc -DAIX -DJSW64 -maix64 -DUNICODE -D_UNICODE -D_THREAD_SAFE
INCLUDE=$(JAVA_HOME)/include
DEFS = -I$(INCLUDE) -I$(INCLUDE)/aix
wrapper_SOURCE = wrapper.c wrapperinfo.c wrappereventloop.c wrapper_unix.c property.c logger.c wrapper_file.c wrapper_i18n.c
libwrapper_a_OBJECTS = wrapper_i18n.o wrapperjni_unix.o wrapperinfo.o wrapperjni.o
BIN = ../../bin
LIB = ../../lib
all: init wrapper libwrapper.a
clean:
rm -f *.o
cleanall: clean
rm -rf *~ .deps
rm -f $(BIN)/wrapper $(LIB)/libwrapper.a
init:
if test ! -d .deps; then mkdir .deps; fi
wrapper: $(wrapper_SOURCE)
$(COMPILE) -lpthread -lnsl -lm $(wrapper_SOURCE) -o $(BIN)/wrapper
libwrapper.a: $(libwrapper_a_OBJECTS)
${COMPILE} -shared $(libwrapper_a_OBJECTS) -o $(LIB)/libwrapper.a
%.o: %.c
${COMPILE} -c ${DEFS} $<
wrapper_3.5.22_src/src/c/Makefile-aix-ppc-64.make 100644 0 0 2700 12224722006 16512 0 ustar 0 0 # Copyright (c) 1999, 2013 Tanuki Software, Ltd.
# http://www.tanukisoftware.com
# All rights reserved.
#
# This software is the proprietary information of Tanuki Software.
# You shall use it only in accordance with the terms of the
# license agreement you entered into with Tanuki Software.
# http://wrapper.tanukisoftware.com/doc/english/licenseOverview.html
COMPILE = gcc -O3 -fPIC --pedantic -DAIX -DJSW64 -maix64 -D_FILE_OFFSET_BITS=64 -liconv -DUNICODE -D_UNICODE -D_THREAD_SAFE
INCLUDE=$(JAVA_HOME)/include
DEFS = -I$(INCLUDE) -I$(INCLUDE)/aix
wrapper_SOURCE = wrapper.c wrapperinfo.c wrappereventloop.c wrapper_unix.c property.c logger.c wrapper_file.c wrapper_i18n.c wrapper_hashmap.c
libwrapper_a_SOURCE = wrapper_i18n.c wrapperjni_unix.c wrapperinfo.c wrapperjni.c
BIN = ../../bin
LIB = ../../lib
all: init wrapper libwrapper.a
clean:
rm -f *.o
cleanall: clean
rm -rf *~ .deps
rm -f $(BIN)/wrapper $(LIB)/libwrapper.a
init:
if test ! -d .deps; then mkdir .deps; fi
wrapper: $(wrapper_SOURCE)
$(COMPILE) -lpthread -lnsl -lm $(wrapper_SOURCE) -o $(BIN)/wrapper
libwrapper.a: $(libwrapper_a_SOURCE)
${COMPILE} $(DEFS) -shared -lpthread $(libwrapper_a_SOURCE) -o $(LIB)/libwrapper.a
%.o: %.c
@echo '$(COMPILE) -c $<'; \
$(COMPILE) $(DEFS) -Wp,-MD,.deps/$(*F).pp -c $<
@-cp .deps/$(*F).pp .deps/$(*F).P; \
tr ' ' '\012' < .deps/$(*F).pp \
| sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
>> .deps/$(*F).P; \
rm .deps/$(*F).pp
wrapper_3.5.22_src/src/c/Makefile-freebsd-x86-32.gmake 100644 0 0 2276 12224722007 17361 0 ustar 0 0 # Copyright (c) 1999, 2013 Tanuki Software, Ltd.
# http://www.tanukisoftware.com
# All rights reserved.
#
# This software is the proprietary information of Tanuki Software.
# You shall use it only in accordance with the terms of the
# license agreement you entered into with Tanuki Software.
# http://wrapper.tanukisoftware.com/doc/english/licenseOverview.html
CC = gcc -Wall -pedantic -DFREEBSD -I/usr/local/include -L/usr/local/lib -liconv -DUNICODE -D_UNICODE
INCLUDE=$(JAVA_HOME)/include
CFLAGS = -I$(INCLUDE) -I$(INCLUDE)/freebsd
wrapper_SOURCE = wrapper.c wrapperinfo.c wrappereventloop.c wrapper_unix.c property.c logger.c wrapper_file.c wrapper_i18n.c wrapper_hashmap.c
libwrapper_so_OBJECTS = wrapper_i18n.o wrapperjni_unix.o wrapperinfo.o wrapperjni.o
BIN = ../../bin
LIB = ../../lib
all: init wrapper libwrapper.so
clean:
rm -f *.o
cleanall: clean
rm -rf *~ .deps
rm -f $(BIN)/wrapper $(LIB)/libwrapper.so
init:
if test ! -d .deps; then mkdir .deps; fi
wrapper: $(wrapper_SOURCE)
$(CC) $(wrapper_SOURCE) -lm -lcompat -pthread -o $(BIN)/wrapper
libwrapper.so: $(libwrapper_so_OBJECTS)
$(CC) -shared $(libwrapper_so_OBJECTS) -o $(LIB)/libwrapper.so
#%.o: %.c
# $(COMPILE) -c $(DEFS) $<
wrapper_3.5.22_src/src/c/Makefile-freebsd-x86-64.gmake 100644 0 0 2314 12224722006 17356 0 ustar 0 0 # Copyright (c) 1999, 2013 Tanuki Software, Ltd.
# http://www.tanukisoftware.com
# All rights reserved.
#
# This software is the proprietary information of Tanuki Software.
# You shall use it only in accordance with the terms of the
# license agreement you entered into with Tanuki Software.
# http://wrapper.tanukisoftware.com/doc/english/licenseOverview.html
CC = gcc -Wall -pedantic -DFREEBSD -DJSW64 -fPIC -I/usr/local/include -L/usr/local/lib -liconv -DUNICODE -D_UNICODE
INCLUDE=$(JAVA_HOME)/include
CFLAGS = -I$(INCLUDE) -I$(INCLUDE)/freebsd
wrapper_SOURCE = wrapper.c wrapperinfo.c wrappereventloop.c wrapper_unix.c property.c logger.c wrapper_file.c wrapper_i18n.c wrapper_hashmap.c
libwrapper_so_OBJECTS = wrapper_i18n.o wrapperjni_unix.o wrapperinfo.o wrapperjni.o
BIN = ../../bin
LIB = ../../lib
all: init wrapper libwrapper.so
clean:
rm -f *.o
cleanall: clean
rm -rf *~ .deps
rm -f $(BIN)/wrapper $(LIB)/libwrapper.so
init:
if test ! -d .deps; then mkdir .deps; fi
wrapper: $(wrapper_SOURCE)
$(CC) $(wrapper_SOURCE) -lm -lcompat -pthread -o $(BIN)/wrapper
libwrapper.so: $(libwrapper_so_OBJECTS)
$(CC) -shared $(libwrapper_so_OBJECTS) -o $(LIB)/libwrapper.so
#%.o: %.c
# $(COMPILE) -c $(DEFS) $<
wrapper_3.5.22_src/src/c/Makefile-hpux-ia-32.gmake 100644 0 0 2314 12224722006 16667 0 ustar 0 0 # Copyright (c) 1999, 2012 Tanuki Software, Ltd.
# http://www.tanukisoftware.com
# All rights reserved.
#
# This software is the proprietary information of Tanuki Software.
# You shall use it only in accordance with the terms of the
# license agreement you entered into with Tanuki Software.
# http://wrapper.tanukisoftware.com/doc/english/licenseOverview.html
COMPILE = gcc -O3 -Wall --pedantic -DHPUX -D_INCLUDE__STDC_A1_SOURCE -DARCH_IA -D_XOPEN_SOURCE_EXTENDED -DUNICODE -D_UNICODE
INCLUDE=$(JAVA_HOME)/include
DEFS = -I$(INCLUDE) -I$(INCLUDE)/hp-ux
wrapper_SOURCE = wrapper.c wrapperinfo.c wrappereventloop.c wrapper_unix.c property.c logger.c wrapper_file.c wrapper_i18n.c
libwrapper_so_OBJECTS = wrapper_i18n.o wrapperjni_unix.o wrapperinfo.o wrapperjni.o
BIN = ../../bin
LIB = ../../lib
all: init wrapper libwrapper.so
clean:
rm -f *.o
cleanall: clean
rm -rf *~ .deps
rm -f $(BIN)/wrapper $(LIB)/libwrapper.so
init:
if test ! -d .deps; then mkdir .deps; fi
wrapper: $(wrapper_SOURCE)
$(COMPILE) $(wrapper_SOURCE) -lm -lpthread -o $(BIN)/wrapper
libwrapper.so: $(libwrapper_so_OBJECTS)
${COMPILE} -fPIC -shared $(libwrapper_so_OBJECTS) -o $(LIB)/libwrapper.so
%.o: %.c
${COMPILE} -fPIC -c ${DEFS} $<
wrapper_3.5.22_src/src/c/Makefile-hpux-ia-32.make 100644 0 0 2257 12224722007 16527 0 ustar 0 0 # Copyright (c) 1999, 2013 Tanuki Software, Ltd.
# http://www.tanukisoftware.com
# All rights reserved.
#
# This software is the proprietary information of Tanuki Software.
# You shall use it only in accordance with the terms of the
# license agreement you entered into with Tanuki Software.
# http://wrapper.tanukisoftware.com/doc/english/licenseOverview.html
COMPILE = cc -DHPUX -Ae +Z -D_INCLUDE__STDC_A1_SOURCE -DUNICODE -D_UNICODE
INCLUDE=$(JAVA_HOME)/include
DEFS = -I$(INCLUDE) -I$(INCLUDE)/hp-ux
wrapper_SOURCE = wrapper.c wrapperinfo.c wrappereventloop.c wrapper_unix.c property.c logger.c wrapper_file.c wrapper_i18n.c wrapper_hashmap.c
libwrapper_so_SOURCE = wrapper_i18n.c wrapperjni_unix.c wrapperinfo.c wrapperjni.c
BIN = ../../bin
LIB = ../../lib
all: init wrapper libwrapper.so
clean:
rm -f *.o
cleanall: clean
rm -rf *~ .deps
rm -f $(BIN)/wrapper $(LIB)/libwrapper.so
init:
if test ! -d .deps; then mkdir .deps; fi
wrapper: $(wrapper_SOURCE)
$(COMPILE) $(wrapper_SOURCE) -lm -lpthread -o $(BIN)/wrapper
libwrapper.so: $(libwrapper_so_SOURCE)
${COMPILE} ${DEFS} $(libwrapper_so_SOURCE) -b -lm -lpthread -o $(LIB)/libwrapper.so
%.o: %.c
${COMPILE} -c ${DEFS} $<
wrapper_3.5.22_src/src/c/Makefile-hpux-ia-64.gmake 100644 0 0 2301 12224722006 16670 0 ustar 0 0 # Copyright (c) 1999, 2012 Tanuki Software, Ltd.
# http://www.tanukisoftware.com
# All rights reserved.
#
# This software is the proprietary information of Tanuki Software.
# You shall use it only in accordance with the terms of the
# license agreement you entered into with Tanuki Software.
# http://wrapper.tanukisoftware.com/doc/english/licenseOverview.html
COMPILE = gcc -O3 -Wall -mlp64 --pedantic -DHPUX -DJSW64 -DARCH_IA -D_XOPEN_SOURCE_EXTENDED -DUNICODE -D_UNICODE
INCLUDE=$(JAVA_HOME)/include
DEFS = -I$(INCLUDE) -I$(INCLUDE)/hp-ux
wrapper_SOURCE = wrapper.c wrapperinfo.c wrappereventloop.c wrapper_unix.c property.c logger.c wrapper_file.c wrapper_i18n.c
libwrapper_so_OBJECTS = wrapper_i18n.o wrapperjni_unix.o wrapperinfo.o wrapperjni.o
BIN = ../../bin
LIB = ../../lib
all: init wrapper libwrapper.so
clean:
rm -f *.o
cleanall: clean
rm -rf *~ .deps
rm -f $(BIN)/wrapper $(LIB)/libwrapper.so
init:
if test ! -d .deps; then mkdir .deps; fi
wrapper: $(wrapper_SOURCE)
$(COMPILE) $(wrapper_SOURCE) -lm -lpthread -o $(BIN)/wrapper
libwrapper.so: $(libwrapper_so_OBJECTS)
${COMPILE} -fPIC -shared $(libwrapper_so_OBJECTS) -o $(LIB)/libwrapper.so
%.o: %.c
${COMPILE} -fPIC -c ${DEFS} $<
wrapper_3.5.22_src/src/c/Makefile-hpux-ia-64.make 100644 0 0 2274 12224722006 16532 0 ustar 0 0 # Copyright (c) 1999, 2013 Tanuki Software, Ltd.
# http://www.tanukisoftware.com
# All rights reserved.
#
# This software is the proprietary information of Tanuki Software.
# You shall use it only in accordance with the terms of the
# license agreement you entered into with Tanuki Software.
# http://wrapper.tanukisoftware.com/doc/english/licenseOverview.html
COMPILE = cc +z +DD64 -O3 -DHPUX -DJSW64 -D_INCLUDE__STDC_A1_SOURCE -DUNICODE -D_UNICODE
INCLUDE=$(JAVA_HOME)/include
DEFS = -I$(INCLUDE) -I$(INCLUDE)/hp-ux
wrapper_SOURCE = wrapper.c wrapperinfo.c wrappereventloop.c wrapper_unix.c property.c logger.c wrapper_i18n.c wrapper_file.c wrapper_hashmap.c
libwrapper_so_SOURCE = wrapper_i18n.c wrapperjni_unix.c wrapperinfo.c wrapperjni.c
BIN = ../../bin
LIB = ../../lib
all: init wrapper libwrapper.so
clean:
rm -f *.o
cleanall: clean
rm -rf *~ .deps
rm -f $(BIN)/wrapper $(LIB)/libwrapper.so
init:
if test ! -d .deps; then mkdir .deps; fi
wrapper: $(wrapper_SOURCE)
$(COMPILE) $(wrapper_SOURCE) -lm -lpthread -o $(BIN)/wrapper
libwrapper.so: $(libwrapper_so_SOURCE)
${COMPILE} ${DEFS} $(libwrapper_so_SOURCE) -b -lm -lpthread -o $(LIB)/libwrapper.so
%.o: %.c
${COMPILE} -c ${DEFS} $<
wrapper_3.5.22_src/src/c/Makefile-hpux-parisc-32.gmake 100644 0 0 2302 12224722005 17553 0 ustar 0 0 # Copyright (c) 1999, 2012 Tanuki Software, Ltd.
# http://www.tanukisoftware.com
# All rights reserved.
#
# This software is the proprietary information of Tanuki Software.
# You shall use it only in accordance with the terms of the
# license agreement you entered into with Tanuki Software.
# http://wrapper.tanukisoftware.com/doc/english/licenseOverview.html
COMPILE = gcc -O3 -Wall -D_INCLUDE__STDC_A1_SOURCE --pedantic -DHPUX -D_XOPEN_SOURCE_EXTENDED -DUNICODE -D_UNICODE
INCLUDE=$(JAVA_HOME)/include
DEFS = -I$(INCLUDE) -I$(INCLUDE)/hp-ux
wrapper_SOURCE = wrapper.c wrapperinfo.c wrappereventloop.c wrapper_unix.c property.c logger.c wrapper_file.c wrapper_i18n.c
libwrapper_sl_OBJECTS = wrapper_i18n.o wrapperjni_unix.o wrapperinfo.o wrapperjni.o
BIN = ../../bin
LIB = ../../lib
all: init wrapper libwrapper.sl
clean:
rm -f *.o
cleanall: clean
rm -rf *~ .deps
rm -f $(BIN)/wrapper $(LIB)/libwrapper.sl
init:
if test ! -d .deps; then mkdir .deps; fi
wrapper: $(wrapper_SOURCE)
$(COMPILE) $(wrapper_SOURCE) -lm -lpthread -o $(BIN)/wrapper
libwrapper.sl: $(libwrapper_sl_OBJECTS)
${COMPILE} -fPIC -shared $(libwrapper_sl_OBJECTS) -o $(LIB)/libwrapper.sl
%.o: %.c
${COMPILE} -fPIC -c ${DEFS} $<
wrapper_3.5.22_src/src/c/Makefile-hpux-parisc-32.make 100644 0 0 2300 12224722007 17404 0 ustar 0 0 # Copyright (c) 1999, 2013 Tanuki Software, Ltd.
# http://www.tanukisoftware.com
# All rights reserved.
#
# This software is the proprietary information of Tanuki Software.
# You shall use it only in accordance with the terms of the
# license agreement you entered into with Tanuki Software.
# http://wrapper.tanukisoftware.com/doc/english/licenseOverview.html
COMPILE = cc -DHPUX -Ae -D_INCLUDE__STDC_A1_SOURCE +Z +DAportable +DS1.1 -DUNICODE -D_UNICODE
INCLUDE=$(JAVA_HOME)/include
DEFS = -I$(INCLUDE) -I$(INCLUDE)/hp-ux
wrapper_SOURCE = wrapper.c wrapperinfo.c wrappereventloop.c wrapper_unix.c property.c logger.c wrapper_file.c wrapper_i18n.c wrapper_hashmap.c
libwrapper_sl_SOURCE = wrapper_i18n.c wrapperjni_unix.c wrapperinfo.c wrapperjni.c
BIN = ../../bin
LIB = ../../lib
all: init wrapper libwrapper.sl
clean:
rm -f *.o
cleanall: clean
rm -rf *~ .deps
rm -f $(BIN)/wrapper $(LIB)/libwrapper.sl
init:
if test ! -d .deps; then mkdir .deps; fi
wrapper: $(wrapper_SOURCE)
$(COMPILE) $(wrapper_SOURCE) -lm -lpthread -o $(BIN)/wrapper
libwrapper.sl: $(libwrapper_sl_SOURCE)
${COMPILE} ${DEFS} $(libwrapper_sl_SOURCE) -b -lm -lpthread -o $(LIB)/libwrapper.sl
%.o: %.c
${COMPILE} -c ${DEFS} $<
wrapper_3.5.22_src/src/c/Makefile-hpux-parisc-64.make 100644 0 0 2301 12224722006 17411 0 ustar 0 0 # Copyright (c) 1999, 2013 Tanuki Software, Ltd.
# http://www.tanukisoftware.com
# All rights reserved.
#
# This software is the proprietary information of Tanuki Software.
# You shall use it only in accordance with the terms of the
# license agreement you entered into with Tanuki Software.
# http://wrapper.tanukisoftware.com/doc/english/licenseOverview.html
COMPILE = cc +z +DD64 -D_INCLUDE__STDC_A1_SOURCE -O3 -Wall -DHPUX -DJSW64 -DUNICODE -D_UNICODE
INCLUDE=$(JAVA_HOME)/include
DEFS = -I$(INCLUDE) -I$(INCLUDE)/hp-ux
wrapper_SOURCE = wrapper.c wrapperinfo.c wrappereventloop.c wrapper_unix.c property.c logger.c wrapper_i18n.c wrapper_file.c wrapper_hashmap.c
libwrapper_sl_SOURCE = wrapper_i18n.c wrapperjni_unix.c wrapperinfo.c wrapperjni.c
BIN = ../../bin
LIB = ../../lib
all: init wrapper libwrapper.sl
clean:
rm -f *.o
cleanall: clean
rm -rf *~ .deps
rm -f $(BIN)/wrapper $(LIB)/libwrapper.sl
init:
if test ! -d .deps; then mkdir .deps; fi
wrapper: $(wrapper_SOURCE)
$(COMPILE) $(wrapper_SOURCE) -lm -lpthread -o $(BIN)/wrapper
libwrapper.sl: $(libwrapper_sl_SOURCE)
${COMPILE} ${DEFS} $(libwrapper_sl_SOURCE) -b -lm -lpthread -o $(LIB)/libwrapper.sl
%.o: %.c
${COMPILE} -c ${DEFS} $<
wrapper_3.5.22_src/src/c/Makefile-irix-mips-32.cc 100644 0 0 2463 12224722006 16543 0 ustar 0 0 # Copyright (c) 1999, 2013 Tanuki Software, Ltd.
# http://www.tanukisoftware.com
# All rights reserved.
#
# This software is the proprietary information of Tanuki Software.
# You shall use it only in accordance with the terms of the
# license agreement you entered into with Tanuki Software.
# http://wrapper.tanukisoftware.com/doc/english/licenseOverview.html
# Makefile for SGI IRIX 6.5 (may work on other versions as well but not tested)
# MIPSpro Compilers: Version 7.3.1.3m
COMPILE = cc -DIRIX -KPIC -DUNICODE -D_UNICODE
INCLUDE=$(JAVA_HOME)/include
DEFS = -I$(INCLUDE) -I$(INCLUDE)/irix
wrapper_OBJECTS = wrapper.o wrapperinfo.o wrappereventloop.o wrapper_unix.o property.o logger.o wrapper_file.o wrapper_i18n.o wrapper_hashmap.c
libwrapper_so_OBJECTS = wrapperjni_unix.o wrapperinfo.o wrapperjni.o wrapper_i18n.o
BIN = ../../bin
LIB = ../../lib
all: init wrapper libwrapper.so
clean:
rm -f *.o
cleanall: clean
rm -rf *~ .deps
rm -f $(BIN)/wrapper $(LIB)/libwrapper.so
init:
if test ! -d .deps; then mkdir .deps; fi
wrapper: $(wrapper_OBJECTS)
$(COMPILE) $(wrapper_OBJECTS) -o $(BIN)/wrapper -lm -lpthread
libwrapper.so: $(libwrapper_so_OBJECTS)
${COMPILE} -shared -no_unresolved -n32 -all $(libwrapper_so_OBJECTS) -o $(LIB)/libwrapper.so
%.o: %.c
@echo '$(COMPILE) -c $<'; \
$(COMPILE) $(DEFS) -c $<
wrapper_3.5.22_src/src/c/Makefile-irix-mips-32.gmake 100644 0 0 2610 12224722005 17233 0 ustar 0 0 # Copyright (c) 1999, 2013 Tanuki Software, Ltd.
# http://www.tanukisoftware.com
# All rights reserved.
#
# This software is the proprietary information of Tanuki Software.
# You shall use it only in accordance with the terms of the
# license agreement you entered into with Tanuki Software.
# http://wrapper.tanukisoftware.com/doc/english/licenseOverview.html
COMPILE = gcc -DIRIX -D_GNU_SOURCE -DUNICODE -D_UNICODE
INCLUDE=$(JAVA_HOME)/include
DEFS = -I$(INCLUDE) -I$(INCLUDE)/irix -DUNICODE -D_UNICODE
wrapper_OBJECTS = wrapper.o wrapperinfo.o wrappereventloop.o wrapper_unix.o property.o logger.o wrapper_file.o wrapper_i18n.o wrapper_hashmap.c
libwrapper_so_OBJECTS = wrapper_i18n.o wrapperjni_unix.o wrapperinfo.o wrapperjni.o
BIN = ../../bin
LIB = ../../lib
all: init wrapper libwrapper.so
clean:
rm -f *.o
cleanall: clean
rm -rf *~ .deps
rm -f $(BIN)/wrapper $(LIB)/libwrapper.so
init:
if test ! -d .deps; then mkdir .deps; fi
wrapper: $(wrapper_OBJECTS)
$(COMPILE) $(wrapper_OBJECTS) -o $(BIN)/wrapper -lm -lpthread
libwrapper.so: $(libwrapper_so_OBJECTS)
${COMPILE} -shared $(libwrapper_so_OBJECTS) -o $(LIB)/libwrapper.so
%.o: %.c
@echo '$(COMPILE) -c $<'; \
$(COMPILE) $(DEFS) -Wp,-MD,.deps/$(*F).pp -c $<
@-cp .deps/$(*F).pp .deps/$(*F).P; \
tr ' ' '\012' < .deps/$(*F).pp \
| sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
>> .deps/$(*F).P; \
rm .deps/$(*F).pp
wrapper_3.5.22_src/src/c/Makefile-linux-armel-32.make 100644 0 0 2660 12224722005 17405 0 ustar 0 0 # Copyright (c) 1999, 2013 Tanuki Software, Ltd.
# http://www.tanukisoftware.com
# All rights reserved.
#
# This software is the proprietary information of Tanuki Software.
# You shall use it only in accordance with the terms of the
# license agreement you entered into with Tanuki Software.
# http://wrapper.tanukisoftware.com/doc/english/licenseOverview.html
COMPILE = gcc -O3 -fPIC -Wall --pedantic -DLINUX -D_FILE_OFFSET_BITS=64 -fpic -D_GNU_SOURCE -DUNICODE -D_UNICODE
INCLUDE=$(JAVA_HOME)/include
DEFS = -I$(INCLUDE) -I$(INCLUDE)/linux
wrapper_SOURCE = wrapper.c wrapperinfo.c wrappereventloop.c wrapper_unix.c property.c logger.c wrapper_file.c wrapper_i18n.c test.c wrapper_hashmap.c
libwrapper_so_OBJECTS = wrapper_i18n.o wrapperjni_unix.o wrapperinfo.o wrapperjni.o
BIN = ../../bin
LIB = ../../lib
all: init wrapper libwrapper.so
clean:
rm -f *.o
cleanall: clean
rm -rf *~ .deps
rm -f $(BIN)/wrapper $(LIB)/libwrapper.so
init:
if test ! -d .deps; then mkdir .deps; fi
wrapper: $(wrapper_SOURCE)
$(COMPILE) -pthread $(wrapper_SOURCE) -lm -o $(BIN)/wrapper
libwrapper.so: $(libwrapper_so_OBJECTS)
${COMPILE} -shared $(libwrapper_so_OBJECTS) -o $(LIB)/libwrapper.so
%.o: %.c
@echo '$(COMPILE) -c $<'; \
$(COMPILE) $(DEFS) -Wp,-MD,.deps/$(*F).pp -c $<
@-cp .deps/$(*F).pp .deps/$(*F).P; \
tr ' ' '\012' < .deps/$(*F).pp \
| sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
>> .deps/$(*F).P; \
rm .deps/$(*F).pp
wrapper_3.5.22_src/src/c/Makefile-linux-armhf-32.make 100644 0 0 2660 12224722006 17403 0 ustar 0 0 # Copyright (c) 1999, 2013 Tanuki Software, Ltd.
# http://www.tanukisoftware.com
# All rights reserved.
#
# This software is the proprietary information of Tanuki Software.
# You shall use it only in accordance with the terms of the
# license agreement you entered into with Tanuki Software.
# http://wrapper.tanukisoftware.com/doc/english/licenseOverview.html
COMPILE = gcc -O3 -fPIC -Wall --pedantic -DLINUX -D_FILE_OFFSET_BITS=64 -fpic -D_GNU_SOURCE -DUNICODE -D_UNICODE
INCLUDE=$(JAVA_HOME)/include
DEFS = -I$(INCLUDE) -I$(INCLUDE)/linux
wrapper_SOURCE = wrapper.c wrapperinfo.c wrappereventloop.c wrapper_unix.c property.c logger.c wrapper_file.c wrapper_i18n.c test.c wrapper_hashmap.c
libwrapper_so_OBJECTS = wrapper_i18n.o wrapperjni_unix.o wrapperinfo.o wrapperjni.o
BIN = ../../bin
LIB = ../../lib
all: init wrapper libwrapper.so
clean:
rm -f *.o
cleanall: clean
rm -rf *~ .deps
rm -f $(BIN)/wrapper $(LIB)/libwrapper.so
init:
if test ! -d .deps; then mkdir .deps; fi
wrapper: $(wrapper_SOURCE)
$(COMPILE) -pthread $(wrapper_SOURCE) -lm -o $(BIN)/wrapper
libwrapper.so: $(libwrapper_so_OBJECTS)
${COMPILE} -shared $(libwrapper_so_OBJECTS) -o $(LIB)/libwrapper.so
%.o: %.c
@echo '$(COMPILE) -c $<'; \
$(COMPILE) $(DEFS) -Wp,-MD,.deps/$(*F).pp -c $<
@-cp .deps/$(*F).pp .deps/$(*F).P; \
tr ' ' '\012' < .deps/$(*F).pp \
| sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
>> .deps/$(*F).P; \
rm .deps/$(*F).pp
wrapper_3.5.22_src/src/c/Makefile-linux-ia-64.make 100644 0 0 2664 12224722006 16710 0 ustar 0 0 # Copyright (c) 1999, 2013 Tanuki Software, Ltd.
# http://www.tanukisoftware.com
# All rights reserved.
#
# This software is the proprietary information of Tanuki Software.
# You shall use it only in accordance with the terms of the
# license agreement you entered into with Tanuki Software.
# http://wrapper.tanukisoftware.com/doc/english/licenseOverview.html
COMPILE = gcc -O3 -fPIC -Wall --pedantic -DLINUX -DJSW64 -D_FILE_OFFSET_BITS=64 -fpic -D_GNU_SOURCE -DUNICODE -D_UNICODE
INCLUDE=$(JAVA_HOME)/include
DEFS = -I$(INCLUDE) -I$(INCLUDE)/linux
wrapper_SOURCE = wrapper.c wrapperinfo.c wrappereventloop.c wrapper_unix.c property.c logger.c wrapper_file.c wrapper_i18n.c wrapper_hashmap.c
libwrapper_so_OBJECTS = wrapper_i18n.o wrapperjni_unix.o wrapperinfo.o wrapperjni.o
BIN = ../../bin
LIB = ../../lib
all: init wrapper libwrapper.so
clean:
rm -f *.o
cleanall: clean
rm -rf *~ .deps
rm -f $(BIN)/wrapper $(LIB)/libwrapper.so
init:
if test ! -d .deps; then mkdir .deps; fi
wrapper: $(wrapper_SOURCE)
$(COMPILE) -lm -pthread $(wrapper_SOURCE) -o $(BIN)/wrapper
libwrapper.so: $(libwrapper_so_OBJECTS)
${COMPILE} -lm -shared $(libwrapper_so_OBJECTS) -o $(LIB)/libwrapper.so
%.o: %.c
@echo '$(COMPILE) -c $<'; \
$(COMPILE) $(DEFS) -Wp,-MD,.deps/$(*F).pp -c $<
@-cp .deps/$(*F).pp .deps/$(*F).P; \
tr ' ' '\012' < .deps/$(*F).pp \
| sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
>> .deps/$(*F).P; \
rm .deps/$(*F).pp
wrapper_3.5.22_src/src/c/Makefile-linux-ppc-32.make 100644 0 0 2655 12224722006 17074 0 ustar 0 0 # Copyright (c) 1999, 2013 Tanuki Software, Ltd.
# http://www.tanukisoftware.com
# All rights reserved.
#
# This software is the proprietary information of Tanuki Software.
# You shall use it only in accordance with the terms of the
# license agreement you entered into with Tanuki Software.
# http://wrapper.tanukisoftware.com/doc/english/licenseOverview.html
COMPILE = gcc -O3 -m32 -fPIC -Wall --pedantic -DLINUX -D_FILE_OFFSET_BITS=64 -fpic -D_GNU_SOURCE -DUNICODE -D_UNICODE
INCLUDE=$(JAVA_HOME)/include
DEFS = -I$(INCLUDE) -I$(INCLUDE)/linux
wrapper_SOURCE = wrapper.c wrapperinfo.c wrappereventloop.c wrapper_unix.c property.c logger.c wrapper_file.c wrapper_i18n.c wrapper_hashmap.c
libwrapper_so_OBJECTS = wrapper_i18n.o wrapperjni_unix.o wrapperinfo.o wrapperjni.o
BIN = ../../bin
LIB = ../../lib
all: init wrapper libwrapper.so
clean:
rm -f *.o
cleanall: clean
rm -rf *~ .deps
rm -f $(BIN)/wrapper $(LIB)/libwrapper.so
init:
if test ! -d .deps; then mkdir .deps; fi
wrapper: $(wrapper_SOURCE)
$(COMPILE) -lm -pthread $(wrapper_SOURCE) -o $(BIN)/wrapper
libwrapper.so: $(libwrapper_so_OBJECTS)
${COMPILE} -shared $(libwrapper_so_OBJECTS) -o $(LIB)/libwrapper.so
%.o: %.c
@echo '$(COMPILE) -c $<'; \
$(COMPILE) $(DEFS) -Wp,-MD,.deps/$(*F).pp -c $<
@-cp .deps/$(*F).pp .deps/$(*F).P; \
tr ' ' '\012' < .deps/$(*F).pp \
| sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
>> .deps/$(*F).P; \
rm .deps/$(*F).pp
wrapper_3.5.22_src/src/c/Makefile-linux-ppc-64.make 100644 0 0 2665 12224722007 17103 0 ustar 0 0 # Copyright (c) 1999, 2013 Tanuki Software, Ltd.
# http://www.tanukisoftware.com
# All rights reserved.
#
# This software is the proprietary information of Tanuki Software.
# You shall use it only in accordance with the terms of the
# license agreement you entered into with Tanuki Software.
# http://wrapper.tanukisoftware.com/doc/english/licenseOverview.html
COMPILE = gcc -O3 -m64 -fPIC -Wall --pedantic -DLINUX -DJSW64 -D_FILE_OFFSET_BITS=64 -fpic -D_GNU_SOURCE -DUNICODE -D_UNICODE
INCLUDE=$(JAVA_HOME)/include
DEFS = -I$(INCLUDE) -I$(INCLUDE)/linux
wrapper_SOURCE = wrapper.c wrapperinfo.c wrappereventloop.c wrapper_unix.c property.c logger.c wrapper_file.c wrapper_i18n.c wrapper_hashmap.c
libwrapper_so_OBJECTS = wrapper_i18n.o wrapperjni_unix.o wrapperinfo.o wrapperjni.o
BIN = ../../bin
LIB = ../../lib
all: init wrapper libwrapper.so
clean:
rm -f *.o
cleanall: clean
rm -rf *~ .deps
rm -f $(BIN)/wrapper $(LIB)/libwrapper.so
init:
if test ! -d .deps; then mkdir .deps; fi
wrapper: $(wrapper_SOURCE)
$(COMPILE) -lm -pthread $(wrapper_SOURCE) -o $(BIN)/wrapper
libwrapper.so: $(libwrapper_so_OBJECTS)
${COMPILE} -shared $(libwrapper_so_OBJECTS) -o $(LIB)/libwrapper.so
%.o: %.c
@echo '$(COMPILE) -c $<'; \
$(COMPILE) $(DEFS) -Wp,-MD,.deps/$(*F).pp -c $<
@-cp .deps/$(*F).pp .deps/$(*F).P; \
tr ' ' '\012' < .deps/$(*F).pp \
| sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
>> .deps/$(*F).P; \
rm .deps/$(*F).pp
wrapper_3.5.22_src/src/c/Makefile-linux-x86-32.make 100644 0 0 2661 12224722007 16735 0 ustar 0 0 # Copyright (c) 1999, 2013 Tanuki Software, Ltd.
# http://www.tanukisoftware.com
# All rights reserved.
#
# This software is the proprietary information of Tanuki Software.
# You shall use it only in accordance with the terms of the
# license agreement you entered into with Tanuki Software.
# http://wrapper.tanukisoftware.com/doc/english/licenseOverview.html
COMPILE = gcc -O3 -fPIC -Wall --pedantic -DLINUX -D_FILE_OFFSET_BITS=64 -fpic -D_GNU_SOURCE -DUNICODE -D_UNICODE
INCLUDE=$(JAVA_HOME)/include
DEFS = -I$(INCLUDE) -I$(INCLUDE)/linux
wrapper_SOURCE = wrapper.c wrapperinfo.c wrappereventloop.c wrapper_unix.c property.c logger.c wrapper_file.c wrapper_i18n.c test.c wrapper_hashmap.c
libwrapper_so_OBJECTS = wrapper_i18n.o wrapperjni_unix.o wrapperinfo.o wrapperjni.o
BIN = ../../bin
LIB = ../../lib
all: init wrapper libwrapper.so
clean:
rm -f *.o
cleanall: clean
rm -rf *~ .deps
rm -f $(BIN)/wrapper $(LIB)/libwrapper.so
init:
if test ! -d .deps; then mkdir .deps; fi
wrapper: $(wrapper_SOURCE)
$(COMPILE) -pthread $(wrapper_SOURCE) -lm -o $(BIN)/wrapper
libwrapper.so: $(libwrapper_so_OBJECTS)
${COMPILE} -shared $(libwrapper_so_OBJECTS) -o $(LIB)/libwrapper.so
%.o: %.c
@echo '$(COMPILE) -c $<'; \
$(COMPILE) $(DEFS) -Wp,-MD,.deps/$(*F).pp -c $<
@-cp .deps/$(*F).pp .deps/$(*F).P; \
tr ' ' '\012' < .deps/$(*F).pp \
| sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
>> .deps/$(*F).P; \
rm .deps/$(*F).pp
wrapper_3.5.22_src/src/c/Makefile-linux-x86-64.make 100644 0 0 2670 12224722006 16741 0 ustar 0 0 # Copyright (c) 1999, 2013 Tanuki Software, Ltd.
# http://www.tanukisoftware.com
# All rights reserved.
#
# This software is the proprietary information of Tanuki Software.
# You shall use it only in accordance with the terms of the
# license agreement you entered into with Tanuki Software.
# http://wrapper.tanukisoftware.com/doc/english/licenseOverview.html
COMPILE = gcc -O3 -fPIC -Wall --pedantic -DLINUX -DJSW64 -D_FILE_OFFSET_BITS=64 -fpic -D_GNU_SOURCE -DUNICODE -D_UNICODE
INCLUDE=$(JAVA_HOME)/include
DEFS = -I$(INCLUDE) -I$(INCLUDE)/linux
wrapper_SOURCE = wrapper.c wrapperinfo.c wrappereventloop.c wrapper_unix.c property.c logger.c wrapper_file.c wrapper_i18n.c test.c wrapper_hashmap.c
libwrapper_so_OBJECTS = wrapper_i18n.o wrapperjni_unix.o wrapperinfo.o wrapperjni.o
BIN = ../../bin
LIB = ../../lib
all: init wrapper libwrapper.so
clean:
rm -f *.o
cleanall: clean
rm -rf *~ .deps
rm -f $(BIN)/wrapper $(LIB)/libwrapper.so
init:
if test ! -d .deps; then mkdir .deps; fi
wrapper: $(wrapper_SOURCE)
$(COMPILE) -pthread $(wrapper_SOURCE) -lm -o $(BIN)/wrapper
libwrapper.so: $(libwrapper_so_OBJECTS)
${COMPILE} -shared $(libwrapper_so_OBJECTS) -o $(LIB)/libwrapper.so
%.o: %.c
@echo '$(COMPILE) -c $<'; \
$(COMPILE) $(DEFS) -Wp,-MD,.deps/$(*F).pp -c $<
@-cp .deps/$(*F).pp .deps/$(*F).P; \
tr ' ' '\012' < .deps/$(*F).pp \
| sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
>> .deps/$(*F).P; \
rm .deps/$(*F).pp
wrapper_3.5.22_src/src/c/Makefile-macosx-universal-32.make 100644 0 0 3612 12224722006 20447 0 ustar 0 0 # Copyright (c) 1999, 2013 Tanuki Software, Ltd.
# http://www.tanukisoftware.com
# All rights reserved.
#
# This software is the proprietary information of Tanuki Software.
# You shall use it only in accordance with the terms of the
# license agreement you entered into with Tanuki Software.
# http://wrapper.tanukisoftware.com/doc/english/licenseOverview.html
UNIVERSAL_SDK_HOME=/Developer/SDKs/MacOSX10.5.sdk
INCLUDE = -I/opt/local/include
COMPILE = gcc -O3 -Wall -DUSE_NANOSLEEP -DMACOSX -arch ppc -arch i386 -isysroot $(UNIVERSAL_SDK_HOME) $(INCLUDE) -mmacosx-version-min=10.4 -DUNICODE -D_UNICODE
COMPILET = gcc -O3 -Wall -DUSE_NANOSLEEP -DMACOSX -isysroot $(UNIVERSAL_SDK_HOME) $(INCLUDE) -mmacosx-version-min=10.4 -DUNICODE -D_UNICODE
#COMPILE = gcc -ggdb -O1 -Wall -DUSE_NANOSLEEP -DMACOSX -DVALGRIND -isysroot $(UNIVERSAL_SDK_HOME) $(INCLUDE) -mmacosx-version-min=10.4 -DUNICODE -D_UNICODE
# To debug:
# 1) Add "-ggdb"
# 2) Remove "-arch ppc -arch i386"
# 3) Change "-O3" to "-O1"
DEFS = -I$(UNIVERSAL_SDK_HOME)/System/Library/Frameworks/JavaVM.framework/Headers
wrapper_SOURCE = wrapper.c wrapperinfo.c wrappereventloop.c wrapper_unix.c property.c logger.c wrapper_file.c wrapper_i18n.c test.c wrapper_hashmap.c
libwrapper_so_OBJECTS = wrapper_i18n.o wrapperjni_unix.o wrapperinfo.o wrapperjni.o
BIN = ../../bin
LIB = ../../lib
TEST = ../../test
all: init testsuite wrapper libwrapper.jnilib
clean:
rm -f *.o
cleanall: clean
rm -rf *~ .deps
rm -f $(BIN)/wrapper $(LIB)/libwrapper.jnilib
init:
if test ! -d .deps; then mkdir .deps; fi
wrapper: $(wrapper_SOURCE)
$(COMPILE) -DMACOSX $(wrapper_SOURCE) -liconv -o $(BIN)/wrapper
libwrapper.jnilib: $(libwrapper_so_OBJECTS)
$(COMPILE) -bundle -liconv -o $(LIB)/libwrapper.jnilib $(libwrapper_so_OBJECTS)
testsuite: $(wrapper_SOURCE)
$(COMPILET) -DCUNIT $(wrapper_SOURCE) -liconv -lncurses -lcunit -o $(TEST)/testsuite
%.o: %.c
$(COMPILE) -c $(DEFS) $<
wrapper_3.5.22_src/src/c/Makefile-macosx-universal-64.make 100644 0 0 2525 12224722007 20457 0 ustar 0 0 # Copyright (c) 1999, 2013 Tanuki Software, Ltd.
# http://www.tanukisoftware.com
# All rights reserved.
#
# This software is the proprietary information of Tanuki Software.
# You shall use it only in accordance with the terms of the
# license agreement you entered into with Tanuki Software.
# http://wrapper.tanukisoftware.com/doc/english/licenseOverview.html
UNIVERSAL_SDK_HOME=/Developer/SDKs/MacOSX10.5.sdk
COMPILE = gcc -O3 -m64 -Wall -DUSE_NANOSLEEP -DMACOSX -DJSW64 -arch ppc64 -arch x86_64 -isysroot $(UNIVERSAL_SDK_HOME) -mmacosx-version-min=10.4 -DUNICODE -D_UNICODE
DEFS = -I$(UNIVERSAL_SDK_HOME)/System/Library/Frameworks/JavaVM.framework/Headers
wrapper_SOURCE = wrapper.c wrapperinfo.c wrappereventloop.c wrapper_unix.c property.c logger.c wrapper_file.c wrapper_i18n.c wrapper_hashmap.c
libwrapper_so_OBJECTS = wrapper_i18n.o wrapperjni_unix.o wrapperinfo.o wrapperjni.o
BIN = ../../bin
LIB = ../../lib
all: init wrapper libwrapper.jnilib
clean:
rm -f *.o
cleanall: clean
rm -rf *~ .deps
rm -f $(BIN)/wrapper $(LIB)/libwrapper.jnilib
init:
if test ! -d .deps; then mkdir .deps; fi
wrapper: $(wrapper_SOURCE)
$(COMPILE) -DMACOSX $(wrapper_SOURCE) -liconv -o $(BIN)/wrapper
libwrapper.jnilib: $(libwrapper_so_OBJECTS)
$(COMPILE) -bundle -liconv -o $(LIB)/libwrapper.jnilib $(libwrapper_so_OBJECTS)
%.o: %.c
$(COMPILE) -c $(DEFS) $<
wrapper_3.5.22_src/src/c/Makefile-osf1-alpha-64.gmake 100644 0 0 2236 12224722006 17257 0 ustar 0 0 # Copyright (c) 1999, 2013 Tanuki Software, Ltd.
# http://www.tanukisoftware.com
# All rights reserved.
#
# This software is the proprietary information of Tanuki Software.
# You shall use it only in accordance with the terms of the
# license agreement you entered into with Tanuki Software.
# http://wrapper.tanukisoftware.com/doc/english/licenseOverview.html
COMPILE = gcc -DOSF1 -DJSW64 -D_REENTRANT -DUNICODE -D_UNICODE
INCLUDE=$(JAVA_HOME)/include
DEFS = -I$(INCLUDE) -I$(INCLUDE)/alpha
wrapper_SOURCE = wrapper.c wrapperinfo.c wrappereventloop.c wrapper_unix.c property.c logger.c wrapper_file.c wrapper_i18n.c wrapper_hashmap.c
libwrapper_so_OBJECTS = wrapper_i18n.o wrapperjni_unix.o wrapperinfo.o wrapperjni.o
BIN = ../../bin
LIB = ../../lib
all: init wrapper libwrapper.so
clean:
rm -f *.o
cleanall: clean
rm -rf *~ .deps
rm -f $(BIN)/wrapper $(LIB)/libwrapper.so
init:
if test ! -d .deps; then mkdir .deps; fi
wrapper: $(wrapper_SOURCE)
$(COMPILE) -lpthread -lm -ldb -lrt $(wrapper_SOURCE) -o $(BIN)/wrapper
libwrapper.so: $(libwrapper_so_OBJECTS)
${COMPILE} -shared $(libwrapper_so_OBJECTS) -o $(LIB)/libwrapper.so
%.o: %.c
${COMPILE} -c ${DEFS} $<
wrapper_3.5.22_src/src/c/Makefile-solaris-sparc-32.gmake 100644 0 0 2341 12224722006 20076 0 ustar 0 0 # Copyright (c) 1999, 2013 Tanuki Software, Ltd.
# http://www.tanukisoftware.com
# All rights reserved.
#
# This software is the proprietary information of Tanuki Software.
# You shall use it only in accordance with the terms of the
# license agreement you entered into with Tanuki Software.
# http://wrapper.tanukisoftware.com/doc/english/licenseOverview.html
COMPILE = /opt/studio12/SUNWspro/bin/cc -mt -Kpic -O -DSOLARIS -DJSW64 -D_REENTRANT -DUNICODE -D_UNICODE
INCLUDE=$(JAVA_HOME)/include
DEFS = -I$(INCLUDE) -I$(INCLUDE)/solaris
wrapper_SOURCE = wrapper.c wrapperinfo.c wrappereventloop.c wrapper_unix.c property.c logger.c wrapper_i18n.c wrapper_file.c wrapper_hashmap.c
libwrapper_so_OBJECTS = wrapper_i18n.o wrapperjni_unix.o wrapperinfo.o wrapperjni.o
BIN = ../../bin
LIB = ../../lib
all: init wrapper libwrapper.so
clean:
rm -f *.o
cleanall: clean
rm -rf *~ .deps
rm -f $(BIN)/wrapper $(LIB)/libwrapper.so
init:
if test ! -d .deps; then mkdir .deps; fi
wrapper: $(wrapper_SOURCE)
$(COMPILE) -lsocket -lpthread -lnsl -lm -lposix4 $(wrapper_SOURCE) -o $(BIN)/wrapper
libwrapper.so: $(libwrapper_so_OBJECTS)
${COMPILE} -G -fPIC -lposix4 $(libwrapper_so_OBJECTS) -o $(LIB)/libwrapper.so
%.o: %.c
${COMPILE} -c ${DEFS} $<
wrapper_3.5.22_src/src/c/Makefile-solaris-sparc-32.make 100644 0 0 2615 12224722007 17734 0 ustar 0 0 # Copyright (c) 1999, 2012 Tanuki Software, Ltd.
# http://www.tanukisoftware.com
# All rights reserved.
#
# This software is the proprietary information of Tanuki Software.
# You shall use it only in accordance with the terms of the
# license agreement you entered into with Tanuki Software.
# http://wrapper.tanukisoftware.com/doc/english/licenseOverview.html
COMPILE = gcc -O3 -Wall --pedantic -DSOLARIS -DUNICODE -D_UNICODE
INCLUDE=$(JAVA_HOME)/include
DEFS = -I$(INCLUDE) -I$(INCLUDE)/solaris
wrapper_SOURCE = wrapper.c wrapperinfo.c wrappereventloop.c wrapper_unix.c property.c logger.c wrapper_file.c wrapper_i18n.c
libwrapper_so_OBJECTS = wrapper_i18n.o wrapperjni_unix.o wrapperinfo.o wrapperjni.o
BIN = ../../bin
LIB = ../../lib
all: init wrapper libwrapper.so
clean:
rm -f *.o
cleanall: clean
rm -rf *~ .deps
rm -f $(BIN)/wrapper $(LIB)/libwrapper.so
init:
if test ! -d .deps; then mkdir .deps; fi
wrapper: $(wrapper_SOURCE)
$(COMPILE) -lsocket -lpthread -lnsl -lm -lposix4 $(wrapper_SOURCE) -o $(BIN)/wrapper
libwrapper.so: $(libwrapper_so_OBJECTS)
${COMPILE} -G -fPIC -lposix4 $(libwrapper_so_OBJECTS) -o $(LIB)/libwrapper.so
%.o: %.c
@echo '$(COMPILE) -c $<'; \
$(COMPILE) $(DEFS) -Wp,-MD,.deps/$(*F).pp -c $<
@-cp .deps/$(*F).pp .deps/$(*F).P; \
tr ' ' '\012' < .deps/$(*F).pp \
| sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
>> .deps/$(*F).P; \
rm .deps/$(*F).pp
wrapper_3.5.22_src/src/c/Makefile-solaris-sparc-64.gmake 100644 0 0 2346 12224722006 20110 0 ustar 0 0 # Copyright (c) 1999, 2013 Tanuki Software, Ltd.
# http://www.tanukisoftware.com
# All rights reserved.
#
# This software is the proprietary information of Tanuki Software.
# You shall use it only in accordance with the terms of the
# license agreement you entered into with Tanuki Software.
# http://wrapper.tanukisoftware.com/doc/english/licenseOverview.html
COMPILE = /opt/studio12/SUNWspro/bin/cc -m64 -mt -Kpic -O -DSOLARIS -DJSW64 -D_REENTRANT -DUNICODE -D_UNICODE
INCLUDE=$(JAVA_HOME)/include
DEFS = -I$(INCLUDE) -I$(INCLUDE)/solaris
wrapper_SOURCE = wrapper.c wrapperinfo.c wrappereventloop.c wrapper_unix.c property.c logger.c wrapper_file.c wrapper_i18n.c wrapper_hashmap.c
libwrapper_so_OBJECTS = wrapper_i18n.o wrapperjni_unix.o wrapperinfo.o wrapperjni.o
BIN = ../../bin
LIB = ../../lib
all: init wrapper libwrapper.so
clean:
rm -f *.o
cleanall: clean
rm -rf *~ .deps
rm -f $(BIN)/wrapper $(LIB)/libwrapper.so
init:
if test ! -d .deps; then mkdir .deps; fi
wrapper: $(wrapper_SOURCE)
$(COMPILE) -lsocket -lpthread -lnsl -lm -lposix4 $(wrapper_SOURCE) -o $(BIN)/wrapper
libwrapper.so: $(libwrapper_so_OBJECTS)
${COMPILE} -G -fPIC -lposix4 $(libwrapper_so_OBJECTS) -o $(LIB)/libwrapper.so
%.o: %.c
${COMPILE} -c ${DEFS} $<
wrapper_3.5.22_src/src/c/Makefile-solaris-sparc-64.make 100644 0 0 2632 12224722006 17737 0 ustar 0 0 # Copyright (c) 1999, 2012 Tanuki Software, Ltd.
# http://www.tanukisoftware.com
# All rights reserved.
#
# This software is the proprietary information of Tanuki Software.
# You shall use it only in accordance with the terms of the
# license agreement you entered into with Tanuki Software.
# http://wrapper.tanukisoftware.com/doc/english/licenseOverview.html
COMPILE = gcc -m64 -O3 -Wall --pedantic -DJSW64 -DSOLARIS -DUNICODE -D_UNICODE
INCLUDE=$(JAVA_HOME)/include
DEFS = -I$(INCLUDE) -I$(INCLUDE)/solaris
wrapper_SOURCE = wrapper.c wrapperinfo.c wrappereventloop.c wrapper_unix.c property.c logger.c wrapper_file.c wrapper_i18n.c
libwrapper_so_OBJECTS = wrapper_i18n.o wrapperjni_unix.o wrapperinfo.o wrapperjni.o
BIN = ../../bin
LIB = ../../lib
all: init wrapper libwrapper.so
clean:
rm -f *.o
cleanall: clean
rm -rf *~ .deps
rm -f $(BIN)/wrapper $(LIB)/libwrapper.so
init:
if test ! -d .deps; then mkdir .deps; fi
wrapper: $(wrapper_SOURCE)
$(COMPILE) -lsocket -lpthread -lnsl -lm -lposix4 $(wrapper_SOURCE) -o $(BIN)/wrapper
libwrapper.so: $(libwrapper_so_OBJECTS)
${COMPILE} -G -fPIC -lposix4 $(libwrapper_so_OBJECTS) -o $(LIB)/libwrapper.so
%.o: %.c
@echo '$(COMPILE) -c $<'; \
$(COMPILE) $(DEFS) -Wp,-MD,.deps/$(*F).pp -c $<
@-cp .deps/$(*F).pp .deps/$(*F).P; \
tr ' ' '\012' < .deps/$(*F).pp \
| sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
>> .deps/$(*F).P; \
rm .deps/$(*F).pp
wrapper_3.5.22_src/src/c/Makefile-solaris-x86-32.gmake 100644 0 0 2421 12224722006 17412 0 ustar 0 0 # Copyright (c) 1999, 2013 Tanuki Software, Ltd.
# http://www.tanukisoftware.com
# All rights reserved.
#
# This software is the proprietary information of Tanuki Software.
# You shall use it only in accordance with the terms of the
# license agreement you entered into with Tanuki Software.
# http://wrapper.tanukisoftware.com/doc/english/licenseOverview.html
# gcc -O3 -Wall --pedantic -DSOLARIS -liconv -DUNICODE -D_UNICODE
COMPILE = /opt/SUNWspro/bin/cc -mt -Kpic -O -DSOLARIS -DUNICODE -D_UNICODE -D_REENTRANT
INCLUDE=$(JAVA_HOME)/include
DEFS = -I$(INCLUDE) -I$(INCLUDE)/solaris
wrapper_SOURCE = wrapper.c wrapperinfo.c wrappereventloop.c wrapper_unix.c property.c logger.c wrapper_file.c wrapper_i18n.c wrapper_hashmap.c
libwrapper_so_OBJECTS = wrapper_i18n.o wrapperjni_unix.o wrapperinfo.o wrapperjni.o
BIN = ../../bin
LIB = ../../lib
all: init wrapper libwrapper.so
clean:
rm -f *.o
cleanall: clean
rm -rf *~ .deps
rm -f $(BIN)/wrapper $(LIB)/libwrapper.so
init:
if test ! -d .deps; then mkdir .deps; fi
wrapper: $(wrapper_SOURCE)
$(COMPILE) -lsocket -lpthread -lnsl -lm -lposix4 $(wrapper_SOURCE) -o $(BIN)/wrapper
libwrapper.so: $(libwrapper_so_OBJECTS)
${COMPILE} -G -fPIC -lposix4 $(libwrapper_so_OBJECTS) -o $(LIB)/libwrapper.so
%.o: %.c
${COMPILE} -c ${DEFS} $<
wrapper_3.5.22_src/src/c/Makefile-solaris-x86-32.make 100644 0 0 2614 12224722006 17247 0 ustar 0 0 # Copyright (c) 1999, 2012 Tanuki Software, Ltd.
# http://www.tanukisoftware.com
# All rights reserved.
#
# This software is the proprietary information of Tanuki Software.
# You shall use it only in accordance with the terms of the
# license agreement you entered into with Tanuki Software.
# http://wrapper.tanukisoftware.com/doc/english/licenseOverview.html
COMPILE = gcc -O3 -Wall --pedantic -DSOLARIS -DUNICODE -D_UNICODE
INCLUDE=$(JAVA_HOME)/include
DEFS = -I$(INCLUDE) -I$(INCLUDE)/solaris
wrapper_SOURCE = wrapper.c wrapperinfo.c wrappereventloop.c wrapper_unix.c property.c logger.c wrapper_file.c wrapper_i18n.c
libwrapper_so_OBJECTS = wrapper_i18n.o wrapperjni_unix.o wrapperinfo.o wrapperjni.o
BIN = ../../bin
LIB = ../../lib
all: init wrapper libwrapper.so
clean:
rm -f *.o
cleanall: clean
rm -rf *~ .deps
rm -f $(BIN)/wrapper $(LIB)/libwrapper.so
init:
if test ! -d .deps; then mkdir .deps; fi
wrapper: $(wrapper_SOURCE)
$(COMPILE) -lsocket -lpthread -lnsl -lm -lposix4 $(wrapper_SOURCE) -o $(BIN)/wrapper
libwrapper.so: $(libwrapper_so_OBJECTS)
${COMPILE} -G -fPIC -lposix4 $(libwrapper_so_OBJECTS) -o $(LIB)/libwrapper.so
%.o: %.c
@echo '$(COMPILE) -c $<'; \
$(COMPILE) $(DEFS) -Wp,-MD,.deps/$(*F).pp -c $<
@-cp .deps/$(*F).pp .deps/$(*F).P; \
tr ' ' '\012' < .deps/$(*F).pp \
| sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
>> .deps/$(*F).P; \
rm .deps/$(*F).pp
wrapper_3.5.22_src/src/c/Makefile-solaris-x86-64.gmake 100644 0 0 3255 12224722006 17425 0 ustar 0 0 # Copyright (c) 1999, 2013 Tanuki Software, Ltd.
# http://www.tanukisoftware.com
# All rights reserved.
#
# This software is the proprietary information of Tanuki Software.
# You shall use it only in accordance with the terms of the
# license agreement you entered into with Tanuki Software.
# http://wrapper.tanukisoftware.com/doc/english/licenseOverview.html
# gcc - The JNI library generated with gcc does not work on 64-bit x86 systems
# due to a bug or simply a configuration problem. We need to use cc here.
# see Bug #1992039 for details.
# https://sourceforge.net/tracker/index.php?func=detail&aid=1992039&group_id=39428&atid=425187
#COMPILE = gcc -m64 -O3 -Wall --pedantic -DSOLARIS -DJSW64
COMPILE = /opt/SUNWspro/bin/cc -m64 -mt -Kpic -O -DSOLARIS -DJSW64 -DUNICODE -D_UNICODE -D_REENTRANT
INCLUDE=$(JAVA_HOME)/include
DEFS = -I$(INCLUDE) -I$(INCLUDE)/solaris
wrapper_SOURCE = wrapper.c wrapperinfo.c wrappereventloop.c wrapper_unix.c property.c logger.c wrapper_file.c wrapper_i18n.c wrapper_hashmap.c
libwrapper_so_OBJECTS = wrapper_i18n.o wrapperjni_unix.o wrapperinfo.o wrapperjni.o
BIN = ../../bin
LIB = ../../lib
all: init wrapper libwrapper.so
clean:
rm -f *.o
cleanall: clean
rm -rf *~ .deps
rm -f $(BIN)/wrapper $(LIB)/libwrapper.so
init:
if test ! -d .deps; then mkdir .deps; fi
wrapper: $(wrapper_SOURCE)
$(COMPILE) -lsocket -lpthread -lnsl -lm -lposix4 $(wrapper_SOURCE) -o $(BIN)/wrapper
#libwrapper.so: $(libwrapper_so_OBJECTS)
# ${COMPILE} -G -fPIC -lposix4 $(libwrapper_so_OBJECTS) -o $(LIB)/libwrapper.so
libwrapper.so: $(libwrapper_so_OBJECTS)
${COMPILE} -G -fPIC -lposix4 $(libwrapper_so_OBJECTS) -o $(LIB)/libwrapper.so
%.o: %.c
${COMPILE} -c ${DEFS} $<
wrapper_3.5.22_src/src/c/Makefile-solaris-x86-64.make 100644 0 0 2631 12224722007 17254 0 ustar 0 0 # Copyright (c) 1999, 2012 Tanuki Software, Ltd.
# http://www.tanukisoftware.com
# All rights reserved.
#
# This software is the proprietary information of Tanuki Software.
# You shall use it only in accordance with the terms of the
# license agreement you entered into with Tanuki Software.
# http://wrapper.tanukisoftware.com/doc/english/licenseOverview.html
COMPILE = gcc -m64 -O3 -Wall --pedantic -DSOLARIS -DJSW64 -DUNICODE -D_UNICODE
INCLUDE=$(JAVA_HOME)/include
DEFS = -I$(INCLUDE) -I$(INCLUDE)/solaris
wrapper_SOURCE = wrapper.c wrapperinfo.c wrappereventloop.c wrapper_unix.c property.c logger.c wrapper_file.c wrapper_i18n.c
libwrapper_so_OBJECTS = wrapper_i18n.o wrapperjni_unix.o wrapperinfo.o wrapperjni.o
BIN = ../../bin
LIB = ../../lib
all: init wrapper libwrapper.so
clean:
rm -f *.o
cleanall: clean
rm -rf *~ .deps
rm -f $(BIN)/wrapper $(LIB)/libwrapper.so
init:
if test ! -d .deps; then mkdir .deps; fi
wrapper: $(wrapper_SOURCE)
$(COMPILE) -lsocket -lpthread -lnsl -lm -lposix4 $(wrapper_SOURCE) -o $(BIN)/wrapper
libwrapper.so: $(libwrapper_so_OBJECTS)
${COMPILE} -G -fPIC -lposix4 $(libwrapper_so_OBJECTS) -o $(LIB)/libwrapper.so
%.o: %.c
@echo '$(COMPILE) -c $<'; \
$(COMPILE) $(DEFS) -Wp,-MD,.deps/$(*F).pp -c $<
@-cp .deps/$(*F).pp .deps/$(*F).P; \
tr ' ' '\012' < .deps/$(*F).pp \
| sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
>> .deps/$(*F).P; \
rm .deps/$(*F).pp
wrapper_3.5.22_src/src/c/Makefile-windows-x86-32.nmake 100644 0 0 6305 12224722006 17444 0 ustar 0 0 # Copyright (c) 1999, 2013 Tanuki Software, Ltd.
# http://www.tanukisoftware.com
# All rights reserved.
#
# This software is the proprietary information of Tanuki Software.
# You shall use it only in accordance with the terms of the
# license agreement you entered into with Tanuki Software.
# http://wrapper.tanukisoftware.com/doc/english/licenseOverview.html
PROJ = wrapper
COMPILE = cl /D "WIN32" /D "NDEBUG" /FD /EHsc /MT /W3 /nologo /c /Zi /errorReport:prompt /D "_CRT_SECURE_NO_DEPRECATE" /D "UNICODE" /D "_UNICODE" /D "_WIN32_WINNT=0x0500"
LINK = link /NOLOGO /MANIFEST /DEBUG /MACHINE:X86 /ERRORREPORT:PROMPT DelayImp.lib
RC = rc
# EXE Definitions
EXE_OUTDIR = $(PROJ)32_VC8__Win32_Release
EXE_OBJS = $(EXE_OUTDIR)\wrapper_i18n.obj $(EXE_OUTDIR)\logger.obj $(EXE_OUTDIR)\property.obj $(EXE_OUTDIR)\wrapper.obj $(EXE_OUTDIR)\wrapper_win.obj $(EXE_OUTDIR)\wrappereventloop.obj $(EXE_OUTDIR)\wrapper_file.obj $(EXE_OUTDIR)\wrapperinfo.obj $(EXE_OUTDIR)\wrapper_hashmap.obj
EXE_LIBS = mpr.lib shell32.lib netapi32.lib wsock32.lib shlwapi.lib advapi32.lib user32.lib Crypt32.lib Wintrust.lib pdh.lib
EXE_COMPILE_OPTS = /O2 /GL /D "_CONSOLE"
EXE_LINK_OPTS = /INCREMENTAL:NO /SUBSYSTEM:CONSOLE /MANIFESTFILE:"$(EXE_OUTDIR)\$(PROJ).exe.intermediate.manifest" /PDB:"$(EXE_OUTDIR)\$(PROJ).pdb" /OPT:REF /OPT:ICF /LTCG
# DLL Definitions
DLL_OUTDIR = $(PROJ)JNI32_VC8__Win32_Release
DLL_OBJS = $(DLL_OUTDIR)\wrapper_i18n.obj $(DLL_OUTDIR)\wrapperjni.obj $(DLL_OUTDIR)\wrapperjni_win.obj $(DLL_OUTDIR)\wrapperinfo.obj
DLL_LIBS = shell32.lib advapi32.lib user32.lib
DLL_COMPILE_OPTS = /Od /I "..\" /I ".\" /I "$(JAVA_HOME)\include" /I "$(JAVA_HOME)\include\win32" /D "_WINDOWS" /D "_USRDLL" /D "DECODERJNI_VC8_EXPORTS" /D "_WINDLL"
DLL_LINK_OPTS = /INCREMENTAL /DLL /SUBSYSTEM:WINDOWS /MANIFESTFILE:"$(DLL_OUTDIR)\$(PROJ).dll.intermediate.manifest" /PDB:"$(DLL_OUTDIR)\$(PROJ).pdb"
all: $(EXE_OUTDIR) $(DLL_OUTDIR) $(PROJ).exe $(PROJ).dll
# Define project specific macros
#----- If OUTDIR does not exist, then create directory
$(EXE_OUTDIR) :
if not exist "$(EXE_OUTDIR)/$(NULL)" mkdir $(EXE_OUTDIR)
$(DLL_OUTDIR) :
if not exist "$(DLL_OUTDIR)/$(NULL)" mkdir $(DLL_OUTDIR)
# Inference rule for updating the object files
.c{$(EXE_OUTDIR)}.obj:
$(COMPILE) $(EXE_COMPILE_OPTS) /Fo"$(EXE_OUTDIR)\\" /Fd"$(EXE_OUTDIR)\\" $**
.c{$(DLL_OUTDIR)}.obj:
$(COMPILE) $(DLL_COMPILE_OPTS) /Fo"$(DLL_OUTDIR)\\" /Fd"$(DLL_OUTDIR)\\" $**
# Build rule for resource file
$(EXE_OUTDIR)\$(PROJ).res: $(PROJ).rc $(RC_DEP)
$(RC) /fo"$(EXE_OUTDIR)/$(PROJ).res" $(PROJ).rc
$(DLL_OUTDIR)\$(PROJ).res: $(PROJ).rc $(RC_DEP)
$(RC) /fo"$(DLL_OUTDIR)/$(PROJ).res" $(PROJ).rc
$(PROJ).exe: $(BASE_OBJS) $(EXE_OBJS) $(EXE_OUTDIR)\$(PROJ).res
$(LINK) $(EXE_LINK_OPTS) $(EXE_OBJS) $(EXE_LIBS) $(EXE_OUTDIR)\$(PROJ).res /OUT:"..\..\bin\$(PROJ).exe"
$(PROJ).dll: $(BASE_OBJS) $(DLL_OBJS) $(DLL_OUTDIR)\$(PROJ).res
$(LINK) $(DLL_LINK_OPTS) $(DLL_OBJS) $(DLL_LIBS) $(DLL_OUTDIR)\$(PROJ).res /OUT:"..\..\lib\$(PROJ).dll"
clean:
if exist $(EXE_OUTDIR)/$(NULL) rd /s /q $(EXE_OUTDIR)
if exist $(DLL_OUTDIR)/$(NULL) rd /s /q $(DLL_OUTDIR)
if exist ..\..\bin\$(PROJ).exe del /q ..\..\bin\$(PROJ).exe
if exist ..\..\lib\$(PROJ).dll del /q ..\..\lib\$(PROJ).dll
wrapper_3.5.22_src/src/c/Wrapper.rc 100644 0 0 7344 12224722007 14330 0 ustar 0 0 //Microsoft Developer Studio generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// { resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_JPN)
#ifdef _WIN32
LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT
#pragma code_page(932)
#endif //_WIN32
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE DISCARDABLE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE DISCARDABLE
BEGIN
"#include \r\n"
"\0"
END
3 TEXTINCLUDE DISCARDABLE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
// http://msdn.microsoft.com/en-us/library/aa381058%28VS.85%29.aspx
VS_VERSION_INFO VERSIONINFO
FILEVERSION 3,5,22,0
PRODUCTVERSION 3,5,22,0
FILEFLAGSMASK 0x17L
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x4L
FILETYPE 0x1L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "000904b0"
BEGIN
VALUE "CompanyName", "Tanuki Software, Ltd."
VALUE "FileDescription", "Java Service Wrapper Community Edition 3.5.22"
VALUE "FileVersion", "3, 5, 22, 0"
VALUE "LegalCopyright", "Copyright (C) 1999, 2013 Tanuki Software, Ltd. All rights reserved."
VALUE "InternalName", "wrapper"
VALUE "OriginalFilename", "wrapper.exe"
VALUE "ProductName", "Java Service Wrapper Community"
VALUE "ProductVersion", "3, 5, 22, 0"
END
END
BLOCK "VarFileInfo"
BEGIN
/* The following line should only be modified for localized versions. */
/* It consists of any number of WORD,WORD pairs, with each pair */
/* describing a language,codepage combination supported by the file. */
/* */
/* For example, a file might have values "0x409,1252" indicating that it */
/* supports English language (0x409) in the Windows ANSI codepage (1252). */
VALUE "Translation", 0x9, 1200
//VALUE "Translation", 0x409, 1252
//VALUE "Translation", 0x411, 932
END
END
#endif // { resources
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
// p (ض) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif //_WIN32
/////////////////////////////////////////////////////////////////////////////
//
// Icon
//
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
IDI_WRAPPER ICON DISCARDABLE "wrapper.ico"
/////////////////////////////////////////////////////////////////////////////
//
// Messages
//
1 11 DISCARDABLE "MSG00001.bin"
#endif // p (ض) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED
wrapper_3.5.22_src/src/c/Wrapper32.dep.in 100644 0 0 1340 12224722006 15233 0 ustar 0 0 # Microsoft Developer Studio Generated Dependency File, included by Wrapper32.mak
.\logger.c : \
".\logger.h"\
".\messages.h"\
"@msvc.home@\vc98\include\basetsd.h"\
.\property.c : \
".\logger.h"\
".\property.h"\
"@msvc.home@\vc98\include\basetsd.h"\
.\wrapper.c : \
".\logger.h"\
".\property.h"\
".\wrapper.h"\
".\wrapperinfo.h"\
"@msvc.home@\vc98\include\basetsd.h"\
.\wrapper_win.c : \
".\logger.h"\
".\property.h"\
".\psapi.h"\
".\wrapper.h"\
".\wrapperinfo.h"\
"@msvc.home@\vc98\include\basetsd.h"\
.\wrappereventloop.c : \
".\logger.h"\
".\property.h"\
".\wrapper.h"\
"@msvc.home@\vc98\include\basetsd.h"\
.\wrapperinfo.c : \
".\wrapperinfo.h"\
.\messages.rc : \
".\MSG00001.bin"\
wrapper_3.5.22_src/src/c/Wrapper32.dsp 100644 0 0 12007 12224722006 14666 0 ustar 0 0 # Microsoft Developer Studio Project File - Name="Wrapper" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** ҏWȂł **
# TARGTYPE "Win32 (x86) Console Application" 0x0103
CFG=Wrapper - Win32 Debug
!MESSAGE ͗LҲ̧قł͂܂B ۼުĂނ邽߂ɂ NMAKE gpĂB
!MESSAGE [Ҳ̧ق̴߰] ނgpĎsĂ
!MESSAGE
!MESSAGE NMAKE /f "Wrapper32.mak".
!MESSAGE
!MESSAGE NMAKE ̎sɍ\wł܂
!MESSAGE ײݏϸۂ̐ݒ`܂B:
!MESSAGE
!MESSAGE NMAKE /f "Wrapper32.mak" CFG="Wrapper - Win32 Debug"
!MESSAGE
!MESSAGE I\ Ӱ:
!MESSAGE
!MESSAGE "Wrapper - Win32 Release" ("Win32 (x86) Console Application" p)
!MESSAGE "Wrapper - Win32 Debug" ("Win32 (x86) Console Application" p)
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "Wrapper - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release32"
# PROP Intermediate_Dir "Release32"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD BASE RSC /l 0x411 /d "NDEBUG"
# ADD RSC /l 0x411 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib shlwapi.lib /nologo /subsystem:console /machine:I386 /out:"../../bin/wrapper.exe"
!ELSEIF "$(CFG)" == "Wrapper - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug32"
# PROP Intermediate_Dir "Debug32"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "DEBUG" /FR /YX /FD /GZ /c
# ADD BASE RSC /l 0x411 /d "_DEBUG"
# ADD RSC /l 0x411 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib shlwapi.lib /nologo /subsystem:console /debug /machine:I386 /out:"../../bin/wrapper.exe" /pdbtype:sept
!ENDIF
# Begin Target
# Name "Wrapper - Win32 Release"
# Name "Wrapper - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=.\logger.c
# End Source File
# Begin Source File
SOURCE=.\property.c
# End Source File
# Begin Source File
SOURCE=.\wrapper.c
# End Source File
# Begin Source File
SOURCE=.\wrapper_unix.c
# End Source File
# Begin Source File
SOURCE=.\wrapper_win.c
# End Source File
# Begin Source File
SOURCE=.\wrappereventloop.c
# End Source File
# Begin Source File
SOURCE=.\wrapperinfo.c
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# Begin Source File
SOURCE=.\logger.h
# End Source File
# Begin Source File
SOURCE=.\messages.h
# End Source File
# Begin Source File
SOURCE=.\property.h
# End Source File
# Begin Source File
SOURCE=.\psapi.h
# End Source File
# Begin Source File
SOURCE=.\resource.h
# End Source File
# Begin Source File
SOURCE=.\wrapper.h
# End Source File
# Begin Source File
SOURCE=.\wrapperinfo.h
# End Source File
# End Group
# Begin Group "Resource Files"
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
# Begin Source File
SOURCE=.\MSG00001.bin
# End Source File
# Begin Source File
SOURCE=.\wrapper.ico
# End Source File
# Begin Source File
SOURCE=.\Wrapper32.rc
# PROP Exclude_From_Build 1
# End Source File
# End Group
# Begin Source File
SOURCE=.\messages.mc
# End Source File
# End Target
# End Project
wrapper_3.5.22_src/src/c/Wrapper32.dsw 100644 0 0 1271 12224722005 14655 0 ustar 0 0 Microsoft Developer Studio Workspace File, Format Version 6.00
# x: ܰ߰ ̧ ҏW܂͍폜Ȃł!
###############################################################################
Project: "Wrapper"=.\Wrapper.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Project: "WrapperJNI"=.\WrapperJNI.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Global:
Package=<5>
{{{
}}}
Package=<3>
{{{
}}}
###############################################################################
wrapper_3.5.22_src/src/c/Wrapper32.mak 100644 0 0 16333 12224722005 14655 0 ustar 0 0 # Microsoft Developer Studio Generated NMAKE File, Based on Wrapper32.dsp
!IF "$(CFG)" == ""
CFG=Wrapper - Win32 Debug
!MESSAGE Build mode not specified. Defaulting to "Wrapper - Win32 Debug".
!ENDIF
!IF "$(CFG)" != "Wrapper - Win32 Release" && "$(CFG)" != "Wrapper - Win32 Debug"
!MESSAGE The build target "$(CFG)" is invalid.
!MESSAGE Usage:
!MESSAGE
!MESSAGE NMAKE /f "Wrapper32.mak" CFG="Wrapper - Win32 Debug"
!MESSAGE
!MESSAGE Valid build modes:
!MESSAGE
!MESSAGE "Wrapper - Win32 Release" ("Win32 (x86) Console Application")
!MESSAGE "Wrapper - Win32 Debug" ("Win32 (x86) Console Application")
!MESSAGE
!ERROR Ivalid build mode.
!ENDIF
!IF "$(OS)" == "Windows_NT"
NULL=
!ELSE
NULL=nul
!ENDIF
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "Wrapper - Win32 Release"
OUTDIR=.\Release32
INTDIR=.\Release32
ALL : "..\..\bin\wrapper.exe"
CLEAN :
-@erase "$(INTDIR)\logger.obj"
-@erase "$(INTDIR)\property.obj"
-@erase "$(INTDIR)\vc60.idb"
-@erase "$(INTDIR)\wrapper.obj"
-@erase "$(INTDIR)\Wrapper.res"
-@erase "$(INTDIR)\wrapper_unix.obj"
-@erase "$(INTDIR)\wrapper_win.obj"
-@erase "$(INTDIR)\wrappereventloop.obj"
-@erase "$(INTDIR)\wrapperinfo.obj"
-@erase "..\..\bin\wrapper.exe"
"$(OUTDIR)" :
if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
CPP_PROJ=/nologo /ML /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\Wrapper32.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
RSC_PROJ=/l 0x409 /fo"$(INTDIR)\Wrapper.res" /d "NDEBUG"
BSC32=bscmake.exe
BSC32_FLAGS=/nologo /o"$(OUTDIR)\Wrapper32.bsc"
BSC32_SBRS= \
LINK32=link.exe
LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib shlwapi.lib /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\wrapper.pdb" /machine:I386 /out:"../../bin/wrapper.exe"
LINK32_OBJS= \
"$(INTDIR)\logger.obj" \
"$(INTDIR)\property.obj" \
"$(INTDIR)\wrapper.obj" \
"$(INTDIR)\wrapper_unix.obj" \
"$(INTDIR)\wrapper_win.obj" \
"$(INTDIR)\wrappereventloop.obj" \
"$(INTDIR)\wrapperinfo.obj" \
"$(INTDIR)\Wrapper.res"
"..\..\bin\wrapper.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
$(LINK32) @<<
$(LINK32_FLAGS) $(LINK32_OBJS)
<<
!ELSEIF "$(CFG)" == "Wrapper - Win32 Debug"
OUTDIR=.\Debug32
INTDIR=.\Debug32
# Begin Custom Macros
OutDir=.\Debug32
# End Custom Macros
ALL : "..\..\bin\wrapper.exe" "$(OUTDIR)\Wrapper32.bsc"
CLEAN :
-@erase "$(INTDIR)\logger.obj"
-@erase "$(INTDIR)\logger.sbr"
-@erase "$(INTDIR)\property.obj"
-@erase "$(INTDIR)\property.sbr"
-@erase "$(INTDIR)\vc60.idb"
-@erase "$(INTDIR)\vc60.pdb"
-@erase "$(INTDIR)\wrapper.obj"
-@erase "$(INTDIR)\Wrapper.res"
-@erase "$(INTDIR)\wrapper.sbr"
-@erase "$(INTDIR)\wrapper_unix.obj"
-@erase "$(INTDIR)\wrapper_unix.sbr"
-@erase "$(INTDIR)\wrapper_win.obj"
-@erase "$(INTDIR)\wrapper_win.sbr"
-@erase "$(INTDIR)\wrappereventloop.obj"
-@erase "$(INTDIR)\wrappereventloop.sbr"
-@erase "$(INTDIR)\wrapperinfo.obj"
-@erase "$(INTDIR)\wrapperinfo.sbr"
-@erase "$(OUTDIR)\wrapper.pdb"
-@erase "$(OUTDIR)\Wrapper32.bsc"
-@erase "..\..\bin\wrapper.exe"
-@erase "..\..\bin\wrapper.ilk"
"$(OUTDIR)" :
if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
CPP_PROJ=/nologo /MLd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "DEBUG" /FR"$(INTDIR)\\" /Fp"$(INTDIR)\Wrapper32.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
RSC_PROJ=/l 0x409 /fo"$(INTDIR)\Wrapper.res" /d "_DEBUG"
BSC32=bscmake.exe
BSC32_FLAGS=/nologo /o"$(OUTDIR)\Wrapper32.bsc"
BSC32_SBRS= \
"$(INTDIR)\logger.sbr" \
"$(INTDIR)\property.sbr" \
"$(INTDIR)\wrapper.sbr" \
"$(INTDIR)\wrapper_unix.sbr" \
"$(INTDIR)\wrapper_win.sbr" \
"$(INTDIR)\wrappereventloop.sbr" \
"$(INTDIR)\wrapperinfo.sbr"
"$(OUTDIR)\Wrapper32.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
$(BSC32) @<<
$(BSC32_FLAGS) $(BSC32_SBRS)
<<
LINK32=link.exe
LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib shlwapi.lib /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\wrapper.pdb" /debug /machine:I386 /out:"../../bin/wrapper.exe" /pdbtype:sept
LINK32_OBJS= \
"$(INTDIR)\logger.obj" \
"$(INTDIR)\property.obj" \
"$(INTDIR)\wrapper.obj" \
"$(INTDIR)\wrapper_unix.obj" \
"$(INTDIR)\wrapper_win.obj" \
"$(INTDIR)\wrappereventloop.obj" \
"$(INTDIR)\wrapperinfo.obj" \
"$(INTDIR)\Wrapper.res"
"..\..\bin\wrapper.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
$(LINK32) @<<
$(LINK32_FLAGS) $(LINK32_OBJS)
<<
!ENDIF
.c{$(INTDIR)}.obj::
$(CPP) @<<
$(CPP_PROJ) $<
<<
.cpp{$(INTDIR)}.obj::
$(CPP) @<<
$(CPP_PROJ) $<
<<
.cxx{$(INTDIR)}.obj::
$(CPP) @<<
$(CPP_PROJ) $<
<<
.c{$(INTDIR)}.sbr::
$(CPP) @<<
$(CPP_PROJ) $<
<<
.cpp{$(INTDIR)}.sbr::
$(CPP) @<<
$(CPP_PROJ) $<
<<
.cxx{$(INTDIR)}.sbr::
$(CPP) @<<
$(CPP_PROJ) $<
<<
!IF "$(NO_EXTERNAL_DEPS)" != "1"
!IF EXISTS("Wrapper32.dep")
!INCLUDE "Wrapper32.dep"
!ELSE
!MESSAGE Warning: cannot find "Wrapper32.dep"
!ENDIF
!ENDIF
!IF "$(CFG)" == "Wrapper - Win32 Release" || "$(CFG)" == "Wrapper - Win32 Debug"
SOURCE=.\logger.c
!IF "$(CFG)" == "Wrapper - Win32 Release"
"$(INTDIR)\logger.obj" : $(SOURCE) "$(INTDIR)"
!ELSEIF "$(CFG)" == "Wrapper - Win32 Debug"
"$(INTDIR)\logger.obj" "$(INTDIR)\logger.sbr" : $(SOURCE) "$(INTDIR)"
!ENDIF
SOURCE=.\property.c
!IF "$(CFG)" == "Wrapper - Win32 Release"
"$(INTDIR)\property.obj" : $(SOURCE) "$(INTDIR)"
!ELSEIF "$(CFG)" == "Wrapper - Win32 Debug"
"$(INTDIR)\property.obj" "$(INTDIR)\property.sbr" : $(SOURCE) "$(INTDIR)"
!ENDIF
SOURCE=.\wrapper.c
!IF "$(CFG)" == "Wrapper - Win32 Release"
"$(INTDIR)\wrapper.obj" : $(SOURCE) "$(INTDIR)"
!ELSEIF "$(CFG)" == "Wrapper - Win32 Debug"
"$(INTDIR)\wrapper.obj" "$(INTDIR)\wrapper.sbr" : $(SOURCE) "$(INTDIR)"
!ENDIF
SOURCE=.\wrapper_unix.c
!IF "$(CFG)" == "Wrapper - Win32 Release"
"$(INTDIR)\wrapper_unix.obj" : $(SOURCE) "$(INTDIR)"
!ELSEIF "$(CFG)" == "Wrapper - Win32 Debug"
"$(INTDIR)\wrapper_unix.obj" "$(INTDIR)\wrapper_unix.sbr" : $(SOURCE) "$(INTDIR)"
!ENDIF
SOURCE=.\wrapper_win.c
!IF "$(CFG)" == "Wrapper - Win32 Release"
"$(INTDIR)\wrapper_win.obj" : $(SOURCE) "$(INTDIR)"
!ELSEIF "$(CFG)" == "Wrapper - Win32 Debug"
"$(INTDIR)\wrapper_win.obj" "$(INTDIR)\wrapper_win.sbr" : $(SOURCE) "$(INTDIR)"
!ENDIF
SOURCE=.\wrappereventloop.c
!IF "$(CFG)" == "Wrapper - Win32 Release"
"$(INTDIR)\wrappereventloop.obj" : $(SOURCE) "$(INTDIR)"
!ELSEIF "$(CFG)" == "Wrapper - Win32 Debug"
"$(INTDIR)\wrappereventloop.obj" "$(INTDIR)\wrappereventloop.sbr" : $(SOURCE) "$(INTDIR)"
!ENDIF
SOURCE=.\wrapperinfo.c
!IF "$(CFG)" == "Wrapper - Win32 Release"
"$(INTDIR)\wrapperinfo.obj" : $(SOURCE) "$(INTDIR)"
!ELSEIF "$(CFG)" == "Wrapper - Win32 Debug"
"$(INTDIR)\wrapperinfo.obj" "$(INTDIR)\wrapperinfo.sbr" : $(SOURCE) "$(INTDIR)"
!ENDIF
SOURCE=.\Wrapper.rc
!IF "$(CFG)" == "Wrapper - Win32 Release"
"$(INTDIR)\Wrapper.res" : $(SOURCE) "$(INTDIR)"
$(RSC) /l 0x409 /fo"$(INTDIR)\Wrapper.res" /d "NDEBUG" $(SOURCE)
!ELSEIF "$(CFG)" == "Wrapper - Win32 Debug"
"$(INTDIR)\Wrapper.res" : $(SOURCE) "$(INTDIR)"
$(RSC) /l 0x411 /fo"$(INTDIR)\Wrapper.res" /d "_DEBUG" $(SOURCE)
!ENDIF
!ENDIF
wrapper_3.5.22_src/src/c/Wrapper32.plg 100644 0 0 2671 12224722007 14651 0 ustar 0 0
ނ۸
--------------------\: Wrapper - Win32 Debug--------------------
ײ
ꎞ̧ "C:\DOCUME~1\leif\LOCALS~1\Temp\RSP3E.tmp" 쐬A̓eL^܂
[
/nologo /MLd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "DEBUG" /FR"Debug32/" /Fp"Debug32/Wrapper32.pch" /YX /Fo"Debug32/" /Fd"Debug32/" /FD /GZ /c
"C:\SourceForge\wrapper\src\c\wrapper.c"
"C:\SourceForge\wrapper\src\c\wrapper_unix.c"
"C:\SourceForge\wrapper\src\c\wrapper_win.c"
"C:\SourceForge\wrapper\src\c\wrappereventloop.c"
]
Creating command line "cl.exe @C:\DOCUME~1\leif\LOCALS~1\Temp\RSP3E.tmp"
ꎞ̧ "C:\DOCUME~1\leif\LOCALS~1\Temp\RSP3F.tmp" 쐬A̓eL^܂
[
kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib shlwapi.lib /nologo /subsystem:console /incremental:yes /pdb:"Debug32/wrapper.pdb" /debug /machine:I386 /out:"../../bin/wrapper.exe" /pdbtype:sept
.\Debug32\logger.obj
.\Debug32\property.obj
.\Debug32\wrapper.obj
.\Debug32\wrapper_unix.obj
.\Debug32\wrapper_win.obj
.\Debug32\wrappereventloop.obj
.\Debug32\wrapperinfo.obj
]
ײ "link.exe @C:\DOCUME~1\leif\LOCALS~1\Temp\RSP3F.tmp" ̍쐬
߯
ْ߲...
wrapper.c
wrapper_unix.c
wrapper_win.c
wrappereventloop.c
ݸ...
wrapper.exe - װ 0Ax 0
wrapper_3.5.22_src/src/c/WrapperJNI32.dep.in 100644 0 0 736 12224722006 15564 0 ustar 0 0 # Microsoft Developer Studio Generated Dependency File, included by WrapperJNI32.mak
.\wrapperinfo.c : \
".\wrapperinfo.h"\
.\wrapperjni.c : \
".\org_tanukisoftware_wrapper_WrapperManager.h"\
".\wrapperinfo.h"\
".\wrapperjni.h"\
"@msvc.home@\vc98\include\basetsd.h"\
"@jni.h@"\
"@jni_md.h@"\
.\wrapperjni_win.c : \
".\org_tanukisoftware_wrapper_WrapperManager.h"\
".\wrapperjni.h"\
"@msvc.home@\vc98\include\basetsd.h"\
"@jni.h@"\
"@jni_md.h@"\
wrapper_3.5.22_src/src/c/WrapperJNI32.dsp 100644 0 0 11324 12224722007 15231 0 ustar 0 0 # Microsoft Developer Studio Project File - Name="WrapperJNI" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** ҏWȂł **
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
CFG=WrapperJNI - Win32 Debug
!MESSAGE ͗LҲ̧قł͂܂B ۼުĂނ邽߂ɂ NMAKE gpĂB
!MESSAGE [Ҳ̧ق̴߰] ނgpĎsĂ
!MESSAGE
!MESSAGE NMAKE /f "WrapperJNI.mak".
!MESSAGE
!MESSAGE NMAKE ̎sɍ\wł܂
!MESSAGE ײݏϸۂ̐ݒ`܂B:
!MESSAGE
!MESSAGE NMAKE /f "WrapperJNI.mak" CFG="WrapperJNI - Win32 Debug"
!MESSAGE
!MESSAGE I\ Ӱ:
!MESSAGE
!MESSAGE "WrapperJNI - Win32 Release" ("Win32 (x86) Dynamic-Link Library" p)
!MESSAGE "WrapperJNI - Win32 Debug" ("Win32 (x86) Dynamic-Link Library" p)
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
MTL=midl.exe
RSC=rc.exe
!IF "$(CFG)" == "WrapperJNI - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "WrapperJNI___Win32_Release"
# PROP BASE Intermediate_Dir "WrapperJNI___Win32_Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "WrapperJNI___Win32_Release32"
# PROP Intermediate_Dir "WrapperJNI___Win32_Release32"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "WRAPPERJNI_EXPORTS" /YX /FD /c
# ADD CPP /nologo /MT /W3 /GX /O2 /I "D:\Sun\j2sdk1.4.0_03\include\\" /I "D:\Sun\j2sdk1.4.0_03\include\win32\\" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "WRAPPERJNI_EXPORTS" /YX /FD /c
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x411 /d "NDEBUG"
# ADD RSC /l 0x411 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"../../lib/wrapper.dll"
!ELSEIF "$(CFG)" == "WrapperJNI - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "WrapperJNI___Win32_Debug"
# PROP BASE Intermediate_Dir "WrapperJNI___Win32_Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "WrapperJNI___Win32_Debug32"
# PROP Intermediate_Dir "WrapperJNI___Win32_Debug32"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "WRAPPERJNI_EXPORTS" /YX /FD /GZ /c
# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "D:\Sun\j2sdk1.4.0_03\include\\" /I "D:\Sun\j2sdk1.4.0_03\include\win32\\" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "WRAPPERJNI_EXPORTS" /FR /YX /FD /GZ /c
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x411 /d "_DEBUG"
# ADD RSC /l 0x411 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /out:"../../lib/wrapper.dll" /pdbtype:sept
!ENDIF
# Begin Target
# Name "WrapperJNI - Win32 Release"
# Name "WrapperJNI - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=.\wrapperinfo.c
# End Source File
# Begin Source File
SOURCE=.\wrapperjni.c
# End Source File
# Begin Source File
SOURCE=.\wrapperjni_unix.c
# End Source File
# Begin Source File
SOURCE=.\wrapperjni_win.c
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# Begin Source File
SOURCE=.\org_tanukisoftware_wrapper_WrapperManager.h
# End Source File
# Begin Source File
SOURCE=.\wrapperinfo.h
# End Source File
# Begin Source File
SOURCE=.\wrapperjni.h
# End Source File
# End Group
# Begin Group "Resource Files"
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
# End Group
# End Target
# End Project
wrapper_3.5.22_src/src/c/WrapperJNI32.mak.in 100644 0 0 13760 12224722007 15626 0 ustar 0 0 # Microsoft Developer Studio Generated NMAKE File, Based on WrapperJNI32.dsp
!IF "$(CFG)" == ""
CFG=WrapperJNI - Win32 Debug
!MESSAGE Build mode not specified. Defaulting to "WrapperJNI - Win32 Debug".
!ENDIF
!IF "$(CFG)" != "WrapperJNI - Win32 Release" && "$(CFG)" != "WrapperJNI - Win32 Debug"
!MESSAGE The build target "$(CFG)" is invalid.
!MESSAGE Usage:
!MESSAGE
!MESSAGE NMAKE /f "WrapperJNI32.mak" CFG="WrapperJNI - Win32 Debug"
!MESSAGE
!MESSAGE Valid build modes:
!MESSAGE
!MESSAGE "WrapperJNI - Win32 Release" ("Win32 (x86) Dynamic-Link Library")
!MESSAGE "WrapperJNI - Win32 Debug" ("Win32 (x86) Dynamic-Link Library")
!MESSAGE
!ERROR Ivalid build mode.
!ENDIF
!IF "$(OS)" == "Windows_NT"
NULL=
!ELSE
NULL=nul
!ENDIF
CPP=cl.exe
MTL=midl.exe
RSC=rc.exe
!IF "$(CFG)" == "WrapperJNI - Win32 Release"
OUTDIR=.\WrapperJNI___Win32_Release32
INTDIR=.\WrapperJNI___Win32_Release32
ALL : "..\..\lib\wrapper.dll"
CLEAN :
-@erase "$(INTDIR)\vc60.idb"
-@erase "$(INTDIR)\wrapperinfo.obj"
-@erase "$(INTDIR)\wrapperjni.obj"
-@erase "$(INTDIR)\wrapperjni_unix.obj"
-@erase "$(INTDIR)\wrapperjni_win.obj"
-@erase "$(OUTDIR)\wrapper.exp"
-@erase "$(OUTDIR)\wrapper.lib"
-@erase "..\..\lib\wrapper.dll"
"$(OUTDIR)" :
if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
CPP_PROJ=/nologo /MT /W3 /GX /O2 /I "@java.home@\include\\" /I "@java.home@\include\win32\\" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "WRAPPERJNI_EXPORTS" /Fp"$(INTDIR)\WrapperJNI32.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32
BSC32=bscmake.exe
BSC32_FLAGS=/nologo /o"$(OUTDIR)\WrapperJNI32.bsc"
BSC32_SBRS= \
LINK32=link.exe
LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /incremental:no /pdb:"$(OUTDIR)\wrapper.pdb" /machine:I386 /out:"../../lib/wrapper.dll" /implib:"$(OUTDIR)\wrapper.lib"
LINK32_OBJS= \
"$(INTDIR)\wrapperinfo.obj" \
"$(INTDIR)\wrapperjni.obj" \
"$(INTDIR)\wrapperjni_unix.obj" \
"$(INTDIR)\wrapperjni_win.obj"
"..\..\lib\wrapper.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
$(LINK32) @<<
$(LINK32_FLAGS) $(LINK32_OBJS)
<<
!ELSEIF "$(CFG)" == "WrapperJNI - Win32 Debug"
OUTDIR=.\WrapperJNI___Win32_Debug32
INTDIR=.\WrapperJNI___Win32_Debug32
# Begin Custom Macros
OutDir=.\WrapperJNI___Win32_Debug32
# End Custom Macros
ALL : "..\..\lib\wrapper.dll" "$(OUTDIR)\WrapperJNI32.bsc"
CLEAN :
-@erase "$(INTDIR)\vc60.idb"
-@erase "$(INTDIR)\vc60.pdb"
-@erase "$(INTDIR)\wrapperinfo.obj"
-@erase "$(INTDIR)\wrapperinfo.sbr"
-@erase "$(INTDIR)\wrapperjni.obj"
-@erase "$(INTDIR)\wrapperjni.sbr"
-@erase "$(INTDIR)\wrapperjni_unix.obj"
-@erase "$(INTDIR)\wrapperjni_unix.sbr"
-@erase "$(INTDIR)\wrapperjni_win.obj"
-@erase "$(INTDIR)\wrapperjni_win.sbr"
-@erase "$(OUTDIR)\wrapper.exp"
-@erase "$(OUTDIR)\wrapper.lib"
-@erase "$(OUTDIR)\wrapper.pdb"
-@erase "$(OUTDIR)\WrapperJNI32.bsc"
-@erase "..\..\lib\wrapper.dll"
-@erase "..\..\lib\wrapper.ilk"
"$(OUTDIR)" :
if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
CPP_PROJ=/nologo /MTd /W3 /Gm /GX /ZI /Od /I "@java.home@\include\\" /I "@java.home@\include\win32\\" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "WRAPPERJNI_EXPORTS" /FR"$(INTDIR)\\" /Fp"$(INTDIR)\WrapperJNI32.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32
BSC32=bscmake.exe
BSC32_FLAGS=/nologo /o"$(OUTDIR)\WrapperJNI32.bsc"
BSC32_SBRS= \
"$(INTDIR)\wrapperinfo.sbr" \
"$(INTDIR)\wrapperjni.sbr" \
"$(INTDIR)\wrapperjni_unix.sbr" \
"$(INTDIR)\wrapperjni_win.sbr"
"$(OUTDIR)\WrapperJNI32.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
$(BSC32) @<<
$(BSC32_FLAGS) $(BSC32_SBRS)
<<
LINK32=link.exe
LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /incremental:yes /pdb:"$(OUTDIR)\wrapper.pdb" /debug /machine:I386 /out:"../../lib/wrapper.dll" /implib:"$(OUTDIR)\wrapper.lib" /pdbtype:sept
LINK32_OBJS= \
"$(INTDIR)\wrapperinfo.obj" \
"$(INTDIR)\wrapperjni.obj" \
"$(INTDIR)\wrapperjni_unix.obj" \
"$(INTDIR)\wrapperjni_win.obj"
"..\..\lib\wrapper.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
$(LINK32) @<<
$(LINK32_FLAGS) $(LINK32_OBJS)
<<
!ENDIF
.c{$(INTDIR)}.obj::
$(CPP) @<<
$(CPP_PROJ) $<
<<
.cpp{$(INTDIR)}.obj::
$(CPP) @<<
$(CPP_PROJ) $<
<<
.cxx{$(INTDIR)}.obj::
$(CPP) @<<
$(CPP_PROJ) $<
<<
.c{$(INTDIR)}.sbr::
$(CPP) @<<
$(CPP_PROJ) $<
<<
.cpp{$(INTDIR)}.sbr::
$(CPP) @<<
$(CPP_PROJ) $<
<<
.cxx{$(INTDIR)}.sbr::
$(CPP) @<<
$(CPP_PROJ) $<
<<
!IF "$(NO_EXTERNAL_DEPS)" != "1"
!IF EXISTS("WrapperJNI32.dep")
!INCLUDE "WrapperJNI32.dep"
!ELSE
!MESSAGE Warning: cannot find "WrapperJNI32.dep"
!ENDIF
!ENDIF
!IF "$(CFG)" == "WrapperJNI - Win32 Release" || "$(CFG)" == "WrapperJNI - Win32 Debug"
SOURCE=.\wrapperinfo.c
!IF "$(CFG)" == "WrapperJNI - Win32 Release"
"$(INTDIR)\wrapperinfo.obj" : $(SOURCE) "$(INTDIR)"
!ELSEIF "$(CFG)" == "WrapperJNI - Win32 Debug"
"$(INTDIR)\wrapperinfo.obj" "$(INTDIR)\wrapperinfo.sbr" : $(SOURCE) "$(INTDIR)"
!ENDIF
SOURCE=.\wrapperjni.c
!IF "$(CFG)" == "WrapperJNI - Win32 Release"
"$(INTDIR)\wrapperjni.obj" : $(SOURCE) "$(INTDIR)"
!ELSEIF "$(CFG)" == "WrapperJNI - Win32 Debug"
"$(INTDIR)\wrapperjni.obj" "$(INTDIR)\wrapperjni.sbr" : $(SOURCE) "$(INTDIR)"
!ENDIF
SOURCE=.\wrapperjni_unix.c
!IF "$(CFG)" == "WrapperJNI - Win32 Release"
"$(INTDIR)\wrapperjni_unix.obj" : $(SOURCE) "$(INTDIR)"
!ELSEIF "$(CFG)" == "WrapperJNI - Win32 Debug"
"$(INTDIR)\wrapperjni_unix.obj" "$(INTDIR)\wrapperjni_unix.sbr" : $(SOURCE) "$(INTDIR)"
!ENDIF
SOURCE=.\wrapperjni_win.c
!IF "$(CFG)" == "WrapperJNI - Win32 Release"
"$(INTDIR)\wrapperjni_win.obj" : $(SOURCE) "$(INTDIR)"
!ELSEIF "$(CFG)" == "WrapperJNI - Win32 Debug"
"$(INTDIR)\wrapperjni_win.obj" "$(INTDIR)\wrapperjni_win.sbr" : $(SOURCE) "$(INTDIR)"
!ENDIF
!ENDIF
wrapper_3.5.22_src/src/c/WrapperJNI32.plg 100644 0 0 3423 12224722006 15205 0 ustar 0 0
ނ۸
--------------------\: WrapperJNI - Win32 Debug--------------------
ײ
ꎞ̧ "C:\DOCUME~1\leif\LOCALS~1\Temp\RSP321.tmp" 쐬A̓eL^܂
[
/nologo /MTd /W3 /Gm /GX /ZI /Od /I "C:\Sun\j2sdk1.4.2_08\include\\" /I "C:\Sun\j2sdk1.4.2_08\include\win32\\" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "WRAPPERJNI_EXPORTS" /FR"WrapperJNI___Win32_Debug32/" /Fp"WrapperJNI___Win32_Debug32/WrapperJNI32.pch" /YX /Fo"WrapperJNI___Win32_Debug32/" /Fd"WrapperJNI___Win32_Debug32/" /FD /GZ /c
"D:\SourceForge\wrapper\src\c\wrapperinfo.c"
"D:\SourceForge\wrapper\src\c\wrapperjni.c"
"D:\SourceForge\wrapper\src\c\wrapperjni_unix.c"
"D:\SourceForge\wrapper\src\c\wrapperjni_win.c"
]
Creating command line "cl.exe @C:\DOCUME~1\leif\LOCALS~1\Temp\RSP321.tmp"
ꎞ̧ "C:\DOCUME~1\leif\LOCALS~1\Temp\RSP322.tmp" 쐬A̓eL^܂
[
kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /incremental:yes /pdb:"WrapperJNI___Win32_Debug32/wrapper.pdb" /debug /machine:I386 /out:"../../lib/wrapper.dll" /implib:"WrapperJNI___Win32_Debug32/wrapper.lib" /pdbtype:sept
.\WrapperJNI___Win32_Debug32\wrapperinfo.obj
.\WrapperJNI___Win32_Debug32\wrapperjni.obj
.\WrapperJNI___Win32_Debug32\wrapperjni_unix.obj
.\WrapperJNI___Win32_Debug32\wrapperjni_win.obj
]
ײ "link.exe @C:\DOCUME~1\leif\LOCALS~1\Temp\RSP322.tmp" ̍쐬
߯
ْ߲...
wrapperinfo.c
wrapperjni.c
wrapperjni_unix.c
wrapperjni_win.c
ݸ...
ײ WrapperJNI___Win32_Debug32/wrapper.lib Ƶު WrapperJNI___Win32_Debug32/wrapper.exp 쐬
wrapper.dll - װ 0Ax 0
wrapper_3.5.22_src/src/c/logger.c 100644 0 0 347534 12224722016 14055 0 ustar 0 0 /*
* Copyright (c) 1999, 2013 Tanuki Software, Ltd.
* http://www.tanukisoftware.com
* All rights reserved.
*
* This software is the proprietary information of Tanuki Software.
* You shall use it only in accordance with the terms of the
* license agreement you entered into with Tanuki Software.
* http://wrapper.tanukisoftware.com/doc/english/licenseOverview.html
*
*
* Portions of the Software have been derived from source code
* developed by Silver Egg Technology under the following license:
*
* Copyright (c) 2001 Silver Egg Technology
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sub-license, and/or
* sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*/
/**
* Author:
* Johan Sorlin
* Leif Mortenson
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include "wrapper_file.h"
#ifdef WIN32
#include
#include
#include
#include
#include
#include
#include "messages.h"
/* MS Visual Studio 8 went and deprecated the POXIX names for functions.
* Fixing them all would be a big headache for UNIX versions. */
#pragma warning(disable : 4996)
/* Defines for MS Visual Studio 6 */
#ifndef _INTPTR_T_DEFINED
typedef long intptr_t;
#define _INTPTR_T_DEFINED
#endif
#else
#include
#include
#include
#include
#include
#if defined(SOLARIS)
#include
#include
#elif defined(AIX) || defined(HPUX) || defined(MACOSX) || defined(OSF1)
#elif defined(IRIX)
#define PATH_MAX FILENAME_MAX
#elif defined(FREEBSD)
#include
#include
#else /* LINUX */
#include
#endif
#endif
#include "wrapper_i18n.h"
#include "logger.h"
#ifndef TRUE
#define TRUE -1
#endif
#ifndef FALSE
#define FALSE 0
#endif
const TCHAR* defaultLogFile = TEXT("wrapper.log");
/* Global data for logger */
/* Maximum number of milliseconds that a log write can take before we show a warning. */
int logPrintfWarnThreshold = 0;
/* Number of millisecoonds which the previous log message took to process. */
time_t previousLogLag;
/* Keep track of when the last log entry was made so we can show the information in the log. */
time_t previousNow;
int previousNowMillis;
/* Initialize all log levels to unknown until they are set */
int currentConsoleLevel = LEVEL_UNKNOWN;
int currentLogfileLevel = LEVEL_UNKNOWN;
int currentLoginfoLevel = LEVEL_UNKNOWN;
/* Default syslog facility is LOG_USER */
int currentLogfacilityLevel = LOG_USER;
/* Callback notified whenever the active logfile changes. */
void (*logFileChangedCallback)(const TCHAR *logFile);
/* Stores a carefully malloced filename of the most recent log file change. This value is only set in log_printf(), and only cleared in maintainLogger(). */
TCHAR *pendingLogFileChange = NULL;
int logPauseTime = -1;
int logBufferGrowth = FALSE;
TCHAR *logFilePath;
TCHAR *currentLogFileName;
TCHAR *workLogFileName;
size_t logFileNameSize;
int logFileRollMode = ROLL_MODE_SIZE;
int logFileUmask = 0022;
TCHAR *logLevelNames[] = { TEXT("NONE "), TEXT("DEBUG "), TEXT("INFO "), TEXT("STATUS"), TEXT("WARN "), TEXT("ERROR "), TEXT("FATAL "), TEXT("ADVICE"), TEXT("NOTICE") };
#ifdef WIN32
TCHAR *defaultLoginfoSourceName = TEXT("wrapper");
TCHAR *loginfoSourceName = NULL;
#else
char *defaultLoginfoSourceName = "wrapper";
char *loginfoSourceName = NULL;
#endif
int logFileMaxSize = -1;
int logFileMaxLogFiles = -1;
TCHAR *logFilePurgePattern = NULL;
int logFilePurgeSortMode = WRAPPER_FILE_SORT_MODE_TIMES;
TCHAR logFileLastNowDate[9];
/* Defualt formats (Must be 4 chars) */
TCHAR consoleFormat[32];
TCHAR logfileFormat[32];
/* Flag to keep track of whether the console output should be flushed or not. */
int consoleFlush = FALSE;
#ifdef WIN32
/* Flag to keep track of whether we should write directly to the console or not. */
int consoleDirect = TRUE;
#endif
/* Flags to contol where error log level output goes to the console. */
int consoleFatalToStdErr = TRUE;
int consoleErrorToStdErr = TRUE;
int consoleWarnToStdErr = FALSE;
/* Number of seconds since the Wrapper was launched. */
int uptimeSeconds = 0;
/* TRUE once the uptime is so large that it is meaningless. */
int uptimeFlipped = FALSE;
/* Internal function declaration */
#ifdef WIN32
void sendEventlogMessage( int source_id, int level, const TCHAR *szBuff );
#else
void sendLoginfoMessage( int source_id, int level, const TCHAR *szBuff );
#endif
#ifdef WIN32
int writeToConsole( HANDLE hdl, TCHAR *lpszFmt, ...);
#endif
void checkAndRollLogs(const TCHAR *nowDate);
int lockLoggingMutex();
int releaseLoggingMutex();
/* Any log messages generated within signal handlers must be stored until we
* have left the signal handler to avoid deadlocks in the logging code.
* Messages are stored in a round robin buffer of log messages until
* maintainLogger is next called.
* When we are inside of a signal, and thus when calling log_printf_queue,
* we know that it is safe to modify the queue as needed. But it is possible
* that a signal could be fired while we are in maintainLogger, so case is
* taken to make sure that volatile changes are only made in log_printf_queue.
*/
#define QUEUE_SIZE 20
/* The size of QUEUED_BUFFER_SIZE_USABLE is arbitrary as the largest size which can be logged in full,
* but to avoid crashes due to a bug in the HPUX libc (version < 1403), the length of the buffer passed to _vsntprintf must have a length of 1 + N, where N is a multiple of 8. */
#define QUEUED_BUFFER_SIZE_USABLE (512 + 1)
#define QUEUED_BUFFER_SIZE (QUEUED_BUFFER_SIZE_USABLE + 4)
#if defined(UNICODE) && !defined(WIN32)
TCHAR formatMessages[WRAPPER_THREAD_COUNT][QUEUED_BUFFER_SIZE];
#endif
int queueWrapped[WRAPPER_THREAD_COUNT];
int queueWriteIndex[WRAPPER_THREAD_COUNT];
int queueReadIndex[WRAPPER_THREAD_COUNT];
TCHAR queueMessages[WRAPPER_THREAD_COUNT][QUEUE_SIZE][QUEUED_BUFFER_SIZE];
int queueSourceIds[WRAPPER_THREAD_COUNT][QUEUE_SIZE];
int queueLevels[WRAPPER_THREAD_COUNT][QUEUE_SIZE];
/* Thread specific work buffers. */
int threadSets[WRAPPER_THREAD_COUNT];
#ifdef WIN32
DWORD threadIds[WRAPPER_THREAD_COUNT];
#else
pthread_t threadIds[WRAPPER_THREAD_COUNT];
#endif
TCHAR *threadMessageBuffer = NULL;
size_t threadMessageBufferSize = 0;
TCHAR *threadPrintBuffer = NULL;
size_t threadPrintBufferSize = 0;
#ifdef WIN32
int launcherSource = FALSE;
#endif
/* Flag which gets set when a log entry is written to the log file. */
int logFileAccessed = FALSE;
/* Logger file pointer. It is kept open under high log loads but closed whenever it has been idle. */
FILE *logfileFP = NULL;
/** Flag which controls whether or not the logfile is auto flushed after each line. */
int autoFlushLogfile = 0;
/** Flag which controls whether or not the logfile is auto closed after each line. */
int autoCloseLogfile = 0;
/* The number of lines sent to the log file since the getLogfileActivity method was last called. */
DWORD logfileActivityCount = 0;
/* Mutex for syncronization of the log_printf function. */
#ifdef WIN32
HANDLE log_printfMutexHandle = NULL;
#else
pthread_mutex_t log_printfMutex = PTHREAD_MUTEX_INITIALIZER;
#endif
void outOfMemory(const TCHAR *context, int id) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_FATAL, TEXT("Out of memory (%s%02d). %s"),
context, id, getLastErrorText());
}
/* This can be called from within logging code that would otherwise get stuck in recursion.
* Log to the console exactly when it happens and then also try to get it into the log
* file at the next oportunity. */
void outOfMemoryQueued(const TCHAR *context, int id) {
_tprintf(TEXT("Out of memory (%s%02d). %s\n"), context, id, getLastErrorText());
log_printf_queue(TRUE, WRAPPER_SOURCE_WRAPPER, LEVEL_FATAL, TEXT("Out of memory (%s%02d). %s"),
context, id, getLastErrorText());
}
#ifdef _DEBUG
/**
* Used to dump memory directly to the log file in both HEX and readable format.
* Useful in debugging applications to track down memory overflows etc.
*
* @param label A label that will be prepended on all lines of output.
* @param memory The memory to be dumped.
* @param len The length of the memory to be dumped.
*/
void log_dumpHex(TCHAR *label, TCHAR *memory, size_t len) {
TCHAR *buffer;
TCHAR *pos;
size_t i;
int c;
buffer = malloc(sizeof(TCHAR) * (len * 3 + 1));
if (!buffer) {
outOfMemory(TEXT("DH"), 1);
}
pos = buffer;
for (i = 0; i < len; i++) {
c = memory[i] & 0xff;
_sntprintf(pos, 4, TEXT("%02x "), c);
pos += 3;
}
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_INFO, TEXT("%s (HEX) = %s"), label, buffer);
pos = buffer;
for (i = 0; i < len; i++) {
c = memory[i] & 0xff;
if (c == 0) {
_sntprintf(pos, 4, TEXT("\\0 "));
} else if (c <= 26) {
_sntprintf(pos, 4, TEXT("\\%c "), TEXT('a') + c - 1);
} else if (c < 127) {
_sntprintf(pos, 4, TEXT("%c "), c);
} else {
_sntprintf(pos, 4, TEXT(". "));
}
pos += 3;
}
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_INFO, TEXT("%s (CHAR) = %s"), label, buffer);
free(buffer);
}
#endif
void invalidMultiByteSequence(const TCHAR *context, int id) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_FATAL, TEXT("Invalid multibyte Sequence found in (%s%02d). %s"),
context, id, getLastErrorText());
}
/**
* Replaces one token with another. The length of the new token must be equal
* to or less than that of the old token.
*
* newToken may be null, implying "".
*/
TCHAR *replaceStringLongWithShort(TCHAR *string, const TCHAR *oldToken, const TCHAR *newToken) {
size_t oldLen = _tcslen(oldToken);
size_t newLen;
TCHAR *in = string;
TCHAR *out = string;
if (newToken) {
newLen = _tcslen(newToken);
} else {
newLen = 0;
}
/* Assertion check. */
if (newLen > oldLen) {
return string;
}
while (in[0] != L'\0') {
if (_tcsncmp(in, oldToken, oldLen) == 0) {
/* Found the oldToken. Replace it with the new. */
if (newLen > 0) {
_tcsncpy(out, newToken, newLen);
}
in += oldLen;
out += newLen;
}
else
{
out[0] = in[0];
in++;
out++;
}
}
out[0] = L'\0';
return string;
}
/**
* Initializes the logger. Returns 0 if the operation was successful.
*/
int initLogging(void (*logFileChanged)(const TCHAR *logFile)) {
int threadId, i;
logFileChangedCallback = logFileChanged;
#ifdef WIN32
if (!(log_printfMutexHandle = CreateMutex(NULL, FALSE, NULL))) {
_tprintf(TEXT("Failed to create logging mutex. %s\n"), getLastErrorText());
return 1;
}
#endif
logPauseTime = -1;
loginfoSourceName = defaultLoginfoSourceName;
logFileAccessed = FALSE;
logFileLastNowDate[0] = L'\0';
for ( threadId = 0; threadId < WRAPPER_THREAD_COUNT; threadId++ ) {
threadSets[threadId] = FALSE;
/* threadIds[threadId] = 0; */
#if defined(UNICODE) && !defined(WIN32)
formatMessages[threadId][0] = TEXT('\0');
#endif
for ( i = 0; i < QUEUE_SIZE; i++ )
{
queueWrapped[threadId] = 0;
queueWriteIndex[threadId] = 0;
queueReadIndex[threadId] = 0;
queueMessages[threadId][i][0] = TEXT('\0');
queueSourceIds[threadId][i] = 0;
queueLevels[threadId][i] = 0;
}
}
return 0;
}
/**
* Disposes of any logging resouces prior to shutdown.
*/
int disposeLogging() {
#ifdef WIN32
#ifdef WRAPPERW
int i;
#endif
/* Always call maintain logger once to make sure that all queued messages are logged before we exit. */
maintainLogger();
if (log_printfMutexHandle) {
if (!CloseHandle(log_printfMutexHandle)) {
_tprintf(TEXT("Unable to close Logging Mutex handle. %s\n"), getLastErrorText());
return 1;
}
}
#ifdef WRAPPERW
for (i = 0; i < dialogLogEntries; i++) {
free(dialogLogs[i]);
dialogLogs[i] = NULL;
}
free(dialogLogs);
dialogLogs = NULL;
#endif
#endif
if (threadPrintBuffer && threadPrintBufferSize > 0) {
free(threadPrintBuffer);
threadPrintBuffer = NULL;
threadPrintBufferSize = 0;
}
if (threadMessageBuffer && threadMessageBufferSize > 0) {
free(threadMessageBuffer);
threadMessageBuffer = NULL;
threadMessageBufferSize = 0;
}
if (logFilePath) {
free(logFilePath);
logFilePath = NULL;
}
if (currentLogFileName) {
free(currentLogFileName);
currentLogFileName = NULL;
}
if (workLogFileName) {
free(workLogFileName);
workLogFileName = NULL;
}
if ((loginfoSourceName != defaultLoginfoSourceName) && (loginfoSourceName != NULL)) {
free(loginfoSourceName);
loginfoSourceName = NULL;
}
if (logfileFP) {
fclose(logfileFP);
logfileFP = NULL;
}
return 0;
}
/** Registers the calling thread so it can be recognized when it calls
* again later. */
void logRegisterThread( int thread_id ) {
#ifdef WIN32
DWORD threadId;
threadId = GetCurrentThreadId();
#else
pthread_t threadId;
threadId = pthread_self();
#endif
#ifdef _DEBUG
_tprintf(TEXT("logRegisterThread(%d)\n"), thread_id);
#endif
if ( thread_id >= 0 && thread_id < WRAPPER_THREAD_COUNT )
{
threadSets[thread_id] = TRUE;
threadIds[thread_id] = threadId;
#ifdef _DEBUG
_tprintf(TEXT("logRegisterThread(%d) found\n"), thread_id);
#endif
}
}
int getThreadId() {
int i;
#ifdef WIN32
DWORD threadId;
threadId = GetCurrentThreadId();
#else
pthread_t threadId;
threadId = pthread_self();
#endif
/*_tprintf(TEXT("threadId=%lu\n"), threadId );*/
for ( i = 0; i < WRAPPER_THREAD_COUNT; i++ ) {
#ifdef WIN32
if (threadSets[i] && (threadIds[i] == threadId)) {
#else
if (threadSets[i] && pthread_equal(threadIds[i], threadId)) {
#endif
return i;
}
}
_tprintf( TEXT("WARNING - Encountered an unknown thread %ld in getThreadId().\n"),
(long int)threadId
);
return 0; /* WRAPPER_THREAD_SIGNAL */
}
int getLogfileRollModeForName( const TCHAR *logfileRollName ) {
if (strcmpIgnoreCase(logfileRollName, TEXT("NONE")) == 0) {
return ROLL_MODE_NONE;
} else if (strcmpIgnoreCase(logfileRollName, TEXT("SIZE")) == 0) {
return ROLL_MODE_SIZE;
} else if (strcmpIgnoreCase(logfileRollName, TEXT("WRAPPER")) == 0) {
return ROLL_MODE_WRAPPER;
} else if (strcmpIgnoreCase(logfileRollName, TEXT("JVM")) == 0) {
return ROLL_MODE_JVM;
} else if (strcmpIgnoreCase(logfileRollName, TEXT("SIZE_OR_WRAPPER")) == 0) {
return ROLL_MODE_SIZE_OR_WRAPPER;
} else if (strcmpIgnoreCase(logfileRollName, TEXT("SIZE_OR_JVM")) == 0) {
return ROLL_MODE_SIZE_OR_JVM;
} else if (strcmpIgnoreCase(logfileRollName, TEXT("DATE")) == 0) {
return ROLL_MODE_DATE;
} else {
return ROLL_MODE_UNKNOWN;
}
}
int getLogLevelForName( const TCHAR *logLevelName ) {
if (strcmpIgnoreCase(logLevelName, TEXT("NONE")) == 0) {
return LEVEL_NONE;
} else if (strcmpIgnoreCase(logLevelName, TEXT("NOTICE")) == 0) {
return LEVEL_NOTICE;
} else if (strcmpIgnoreCase(logLevelName, TEXT("ADVICE")) == 0) {
return LEVEL_ADVICE;
} else if (strcmpIgnoreCase(logLevelName, TEXT("FATAL")) == 0) {
return LEVEL_FATAL;
} else if (strcmpIgnoreCase(logLevelName, TEXT("ERROR")) == 0) {
return LEVEL_ERROR;
} else if (strcmpIgnoreCase(logLevelName, TEXT("WARN")) == 0) {
return LEVEL_WARN;
} else if (strcmpIgnoreCase(logLevelName, TEXT("STATUS")) == 0) {
return LEVEL_STATUS;
} else if (strcmpIgnoreCase(logLevelName, TEXT("INFO")) == 0) {
return LEVEL_INFO;
} else if (strcmpIgnoreCase(logLevelName, TEXT("DEBUG")) == 0) {
return LEVEL_DEBUG;
} else {
return LEVEL_UNKNOWN;
}
}
#ifndef WIN32
int getLogFacilityForName( const TCHAR *logFacilityName ) {
if (strcmpIgnoreCase(logFacilityName, TEXT("USER")) == 0) {
return LOG_USER;
} else if (strcmpIgnoreCase(logFacilityName, TEXT("LOCAL0")) == 0) {
return LOG_LOCAL0;
} else if (strcmpIgnoreCase(logFacilityName, TEXT("LOCAL1")) == 0) {
return LOG_LOCAL1;
} else if (strcmpIgnoreCase(logFacilityName, TEXT("LOCAL2")) == 0) {
return LOG_LOCAL2;
} else if (strcmpIgnoreCase(logFacilityName, TEXT("LOCAL3")) == 0) {
return LOG_LOCAL3;
} else if (strcmpIgnoreCase(logFacilityName, TEXT("LOCAL4")) == 0) {
return LOG_LOCAL4;
} else if (strcmpIgnoreCase(logFacilityName, TEXT("LOCAL5")) == 0) {
return LOG_LOCAL5;
} else if (strcmpIgnoreCase(logFacilityName, TEXT("LOCAL6")) == 0) {
return LOG_LOCAL6;
} else if (strcmpIgnoreCase(logFacilityName, TEXT("LOCAL7")) == 0) {
return LOG_LOCAL7;
} else {
return LOG_USER;
}
}
#endif
/**
* Sets the number of milliseconds to allow logging to take before a warning is logged.
* Defaults to 0 for no limit. Possible values 0 to 3600000.
*
* @param threshold Warning threashold.
*/
void setLogWarningThreshold(int threshold) {
logPrintfWarnThreshold = __max(__min(threshold, 3600000), 0);
}
/**
* Sets the log levels to a silence so we never output anything.
*/
void setSilentLogLevels() {
setConsoleLogLevelInt(LEVEL_NONE);
#ifdef WRAPPERW
setDialogLogLevelInt(LEVEL_NONE);
#endif
setLogfileLevelInt(LEVEL_NONE);
setSyslogLevelInt(LEVEL_NONE);
}
/**
* Sets the console log levels to a simple format for help and usage messages.
*/
void setSimpleLogLevels() {
/* Force the log levels to control output. */
setConsoleLogFormat(TEXT("M"));
setConsoleLogLevelInt(LEVEL_INFO);
setLogfileLevelInt(LEVEL_NONE);
setSyslogLevelInt(LEVEL_NONE);
}
#ifdef WIN32
/**
* This sets a flag which tells the logger that alternate source labels should be used to indicate that the current process is a launcher.
*/
void setLauncherSource() {
launcherSource = TRUE;
}
#endif
/* Logfile functions */
int isLogfileAccessed() {
return logFileAccessed;
}
/**
* Sets the log file to be used. If the specified file is not absolute then
* it will be resolved into an absolute path. If there are any problems with
* the path, like a directory not existing then the call will fail and the
* cause will be written to the existing log.
*
* @param log_file_path Log file to start using.
* @param workingDir The current working directory, used for relative paths.
* This will be NULL if this is part of the bootstrap process,
* in which case we should not attempt to resolve the absolute
* path.
* @param preload TRUE if called as part of the preload process. We use this to
* suppress double warnings.
*
* @return TRUE if there were any problems.
*/
extern int setLogfilePath(const TCHAR *log_file_path, const TCHAR *workingDir, int preload) {
size_t len = _tcslen(log_file_path);
#ifdef WIN32
TCHAR *c;
#endif
logFileNameSize = len + 10 + 1;
if (logFilePath) {
free(logFilePath);
free(currentLogFileName);
free(workLogFileName);
}
logFilePath = NULL;
currentLogFileName = NULL;
workLogFileName = NULL;
logFilePath = malloc(sizeof(TCHAR) * (len + 1));
if (!logFilePath) {
outOfMemoryQueued(TEXT("SLP"), 1);
return TRUE;
}
_tcsncpy(logFilePath, log_file_path, len + 1);
currentLogFileName = malloc(sizeof(TCHAR) * (len + 10 + 1));
if (!currentLogFileName) {
outOfMemoryQueued(TEXT("SLP"), 2);
free(logFilePath);
logFilePath = NULL;
return TRUE;
}
currentLogFileName[0] = TEXT('\0');
workLogFileName = malloc(sizeof(TCHAR) * (len + 10 + 1));
if (!workLogFileName) {
outOfMemoryQueued(TEXT("SLP"), 3);
free(logFilePath);
logFilePath = NULL;
free(currentLogFileName);
logFileNameSize = 0;
currentLogFileName = NULL;
return TRUE;
}
workLogFileName[0] = TEXT('\0');
#ifdef WIN32
/* To avoid problems on some windows systems, the '/' characters must
* be replaced by '\' characters in the specified path. */
c = (TCHAR *)logFilePath;
while((c = _tcschr(c, TEXT('/'))) != NULL) {
c[0] = TEXT('\\');
}
#endif
return FALSE;
}
/**
* Returns the default logfile.
*/
const TCHAR *getDefaultLogfilePath() {
return defaultLogFile;
}
/**
* Returns a reference to the currect log file path.
* This return value may be changed at any time if the log file is rolled.
*/
const TCHAR *getLogfilePath()
{
return logFilePath;
}
/**
* Returns a snapshot of the current log file path. This call safely gets the current path
* and returns a copy. It is the responsibility of the caller to free up the memory on
* return. Could return null if there was an error.
*/
TCHAR *getCurrentLogfilePath() {
TCHAR *logFileCopy;
/* Lock the logging mutex. */
if (lockLoggingMutex()) {
return NULL;
}
/* We should always have a current log file name here because there will be at least one line of log output before this is called.
* If that is false then we will return an empty length, but valid, string. */
logFileCopy = malloc(sizeof(TCHAR) * (_tcslen(currentLogFileName) + 1));
if (!logFileCopy) {
_tprintf(TEXT("Out of memory in logging code (%s)\n"), TEXT("P3"));
} else {
_tcsncpy(logFileCopy, currentLogFileName, _tcslen(currentLogFileName) + 1);
}
/* Release the lock we have on the logging mutex so that other threads can get in. */
if (releaseLoggingMutex()) {
if (logFileCopy) {
free(logFileCopy);
}
return NULL;
}
return logFileCopy;
}
/**
* Check the directory of the current logfile path to make sure it is writable.
* If there are any problems, log a warning.
*
* @return TRUE if there were any problems.
*/
int checkLogfileDir() {
size_t len;
TCHAR *c;
TCHAR *logFileDir;
TCHAR *testfile;
int fd;
len = _tcslen(logFilePath) + 1;
logFileDir = malloc(len * sizeof(TCHAR));
if (!logFileDir) {
outOfMemory(TEXT("CLD"), 1);
return TRUE;
}
_tcsncpy(logFileDir, logFilePath, len);
#ifdef WIN32
c = _tcsrchr(logFileDir, TEXT('\\'));
#else
c = _tcsrchr(logFileDir, TEXT('/'));
#endif
if (c) {
c[0] = TEXT('\0');
/* We want to try writing a test file to the configured log directory to make sure it is writable. */
len = _tcslen(logFileDir) + 23 + 1 + 1000;
testfile = malloc(len * sizeof(TCHAR));
if (!testfile) {
outOfMemory(TEXT("CLD"), 1);
free(logFileDir);
return TRUE;
}
_sntprintf(testfile, len, TEXT("%s%c.wrapper_test-%.4d%.4d"),
logFileDir,
#ifdef WIN32
TEXT('\\'),
#else
TEXT('/'),
#endif
rand() % 9999, rand() % 9999);
if ((fd = _topen(testfile, O_WRONLY | O_CREAT | O_EXCL
#ifdef WIN32
, _S_IWRITE
#else
, S_IRUSR | S_IWUSR
#endif
)) == -1) {
if (errno == EACCES) {
log_printf_queue(TRUE, WRAPPER_SOURCE_WRAPPER, LEVEL_WARN,
TEXT("Unable to write to the configured log directory: %s (%s)\n The Wrapper may also have problems writing or rolling the log file.\n Please make sure that the current user has read/write access."),
logFileDir, getLastErrorText());
} else if (errno == ENOENT) {
log_printf_queue(TRUE, WRAPPER_SOURCE_WRAPPER, LEVEL_WARN,
TEXT("Unable to write to the configured log directory: %s (%s)\n The directory does not exist."),
logFileDir, getLastErrorText());
}
} else {
/* Successfully wrote the temp file. */
#ifdef WIN32
_close(fd);
#else
close(fd);
#endif
if (_tremove(testfile)) {
log_printf_queue(TRUE, WRAPPER_SOURCE_WRAPPER, LEVEL_WARN,
TEXT("Unable to remove temporary file: %s (%s)\n The Wrapper may also have problems writing or rolling the log file.\n Please make sure that the current user has read/write access."),
testfile, getLastErrorText());
}
}
free(testfile);
}
free(logFileDir);
return FALSE;
}
/**
* This method will wiat for the specified number of seconds. It is only meant for special
* uses within the logging code as it does not itself log any output in a correct way.
*/
void logSleep(int ms) {
#ifdef WIN32
Sleep(ms);
#else
/* We want to use nanosleep if it is available, but make it possible for the
user to build a version that uses usleep if they want.
usleep does not behave nicely with signals thrown while sleeping. This
was the believed cause of a hang experienced on one Solaris system. */
#ifdef USE_USLEEP
usleep(ms * 1000); /* microseconds */
#else
struct timespec ts;
if (ms >= 1000) {
ts.tv_sec = (ms * 1000000) / 1000000000;
ts.tv_nsec = (ms * 1000000) % 1000000000; /* nanoseconds */
} else {
ts.tv_sec = 0;
ts.tv_nsec = ms * 1000000; /* nanoseconds */
}
if (nanosleep(&ts, NULL)) {
if (errno == EINTR) {
return;
} else if (errno == EAGAIN) {
/* On 64-bit AIX this happens once on shutdown. */
return;
} else {
_tprintf(TEXT("nanosleep(%dms) failed. \n"), ms, getLastErrorText());
}
}
#endif
#endif
}
/**
* Used for testing to set a pause into the next log entry made.
*
* @param pauseTime Number of seconds to pause, 0 pauses indefinitely.
*/
void setPauseTime(int pauseTime)
{
logPauseTime = pauseTime;
}
/**
* Set to true to cause changes in internal buffer sizes to be logged. Useful for debugging.
*
* @param log TRUE if changes should be logged.
*/
void setLogBufferGrowth(int log) {
logBufferGrowth = log;
}
void setLogfileRollMode( int log_file_roll_mode ) {
logFileRollMode = log_file_roll_mode;
}
int getLogfileRollMode() {
return logFileRollMode;
}
void setLogfileUmask( int log_file_umask ) {
logFileUmask = log_file_umask;
}
void setLogfileFormat( const TCHAR *log_file_format ) {
if ( log_file_format != NULL ) {
_tcsncpy( logfileFormat, log_file_format, 32 );
/* We only want to time logging if it is needed. */
if ((logPrintfWarnThreshold <= 0) && (_tcschr(log_file_format, TEXT('G')))) {
logPrintfWarnThreshold = 99999999;
}
}
}
void setLogfileLevelInt( int log_file_level ) {
currentLogfileLevel = log_file_level;
}
int getLogfileLevelInt() {
return currentLogfileLevel;
}
void setLogfileLevel( const TCHAR *log_file_level ) {
setLogfileLevelInt(getLogLevelForName(log_file_level));
}
void setLogfileMaxFileSize( const TCHAR *max_file_size ) {
int multiple, i, newLength;
TCHAR *tmpFileSizeBuff;
TCHAR chr;
if ( max_file_size != NULL ) {
/* Allocate buffer */
tmpFileSizeBuff = malloc(sizeof(TCHAR) * (_tcslen( max_file_size ) + 1));
if (!tmpFileSizeBuff) {
outOfMemoryQueued(TEXT("SLMFS"), 1);
return;
}
/* Generate multiple and remove unwanted chars */
multiple = 1;
newLength = 0;
for( i = 0; i < (int)_tcslen(max_file_size); i++ ) {
chr = max_file_size[i];
switch( chr ) {
case TEXT('k'): /* Kilobytes */
case TEXT('K'):
multiple = 1024;
break;
case TEXT('M'): /* Megabytes */
case TEXT('m'):
multiple = 1048576;
break;
}
if( (chr >= TEXT('0') && chr <= TEXT('9')) || (chr == TEXT('-')) )
tmpFileSizeBuff[newLength++] = max_file_size[i];
}
tmpFileSizeBuff[newLength] = TEXT('\0');/* Crop string */
logFileMaxSize = _ttoi( tmpFileSizeBuff );
if( logFileMaxSize > 0 )
logFileMaxSize *= multiple;
/* Free memory */
free( tmpFileSizeBuff );
tmpFileSizeBuff = NULL;
if ((logFileMaxSize > 0) && (logFileMaxSize < 1024)) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_WARN, TEXT(
"wrapper.logfile.maxsize must be 0 or at least 1024. Changing to %d."), logFileMaxSize);
logFileMaxSize = 1024;
}
}
}
void setLogfileMaxFileSizeInt( int max_file_size ) {
logFileMaxSize = max_file_size;
}
void setLogfileMaxLogFiles( int max_log_files ) {
logFileMaxLogFiles = max_log_files;
}
void setLogfilePurgePattern(const TCHAR *pattern) {
size_t len;
if (logFilePurgePattern) {
free(logFilePurgePattern);
logFilePurgePattern = NULL;
}
len = _tcslen(pattern);
if (len > 0) {
logFilePurgePattern = malloc(sizeof(TCHAR) * (len + 1));
if (!logFilePurgePattern) {
outOfMemoryQueued(TEXT("SLPP"), 1);
return;
}
_tcsncpy(logFilePurgePattern, pattern, len + 1);
}
}
void setLogfilePurgeSortMode(int sortMode) {
logFilePurgeSortMode = sortMode;
}
/** Returns the number of lines of log file activity since the last call. */
DWORD getLogfileActivity() {
DWORD logfileLines;
/* Don't worry about synchronization here. Any errors are not critical the way this is used. */
logfileLines = logfileActivityCount;
logfileActivityCount = 0;
return logfileLines;
}
/** Obtains a lock on the logging mutex. */
int lockLoggingMutex() {
#ifdef WIN32
switch (WaitForSingleObject(log_printfMutexHandle, INFINITE)) {
case WAIT_ABANDONED:
_tprintf(TEXT("Logging mutex was abandoned.\n"));
return -1;
case WAIT_FAILED:
_tprintf(TEXT("Logging mutex wait failed.\n"));
return -1;
case WAIT_TIMEOUT:
_tprintf(TEXT("Logging mutex wait timed out.\n"));
return -1;
default:
/* Ok */
break;
}
#else
if (pthread_mutex_lock(&log_printfMutex)) {
_tprintf(TEXT("Failed to lock the Logging mutex. %s\n"), getLastErrorText());
return -1;
}
#endif
return 0;
}
/** Releases a lock on the logging mutex. */
int releaseLoggingMutex() {
#ifdef WIN32
if (!ReleaseMutex(log_printfMutexHandle)) {
_tprintf( TEXT("Failed to release logging mutex. %s\n"), getLastErrorText());
return -1;
}
#else
if (pthread_mutex_unlock(&log_printfMutex)) {
_tprintf(TEXT("Failed to unlock the Logging mutex. %s\n"), getLastErrorText());
return -1;
}
#endif
return 0;
}
/** Sets the auto flush log file flag. */
void setLogfileAutoFlush(int autoFlush) {
autoFlushLogfile = autoFlush;
}
/** Sets the auto close log file flag. */
void setLogfileAutoClose(int autoClose) {
autoCloseLogfile = autoClose;
}
/** Closes the logfile if it is open. */
void closeLogfile() {
/* We need to be very careful that only one thread is allowed in here
* at a time. On Windows this is done using a Mutex object that is
* initialized in the initLogging function. */
if (lockLoggingMutex()) {
return;
}
if (logfileFP != NULL) {
#ifdef _DEBUG
_tprintf(TEXT("Closing logfile by request...\n"));
#endif
fclose(logfileFP);
logfileFP = NULL;
/* Do not clean the currentLogFileName here as the name is not actually changing. */
}
/* Release the lock we have on this function so that other threads can get in. */
if (releaseLoggingMutex()) {
return;
}
}
/** Flushes any buffered logfile output to the disk. */
void flushLogfile() {
/* We need to be very careful that only one thread is allowed in here
* at a time. On Windows this is done using a Mutex object that is
* initialized in the initLogging function. */
if (lockLoggingMutex()) {
return;
}
if (logfileFP != NULL) {
#ifdef _DEBUG
_tprintf(TEXT("Flushing logfile by request...\n"));
#endif
fflush(logfileFP);
}
/* Release the lock we have on this function so that other threads can get in. */
if (releaseLoggingMutex()) {
return;
}
}
/* Console functions */
void setConsoleLogFormat( const TCHAR *console_log_format ) {
if ( console_log_format != NULL ) {
_tcsncpy( consoleFormat, console_log_format, 32 );
/* We only want to time logging if it is needed. */
if ((logPrintfWarnThreshold <= 0) && (_tcschr(console_log_format, TEXT('G')))) {
logPrintfWarnThreshold = 99999999;
}
}
}
void setConsoleLogLevelInt( int console_log_level ) {
currentConsoleLevel = console_log_level;
}
int getConsoleLogLevelInt() {
return currentConsoleLevel;
}
void setConsoleLogLevel( const TCHAR *console_log_level ) {
setConsoleLogLevelInt(getLogLevelForName(console_log_level));
}
void setConsoleFlush( int flush ) {
consoleFlush = flush;
}
#ifdef WIN32
void setConsoleDirect( int direct ) {
consoleDirect = direct;
}
#endif
void setConsoleFatalToStdErr(int toStdErr) {
consoleFatalToStdErr = toStdErr;
}
void setConsoleErrorToStdErr(int toStdErr) {
consoleErrorToStdErr = toStdErr;
}
void setConsoleWarnToStdErr(int toStdErr) {
consoleWarnToStdErr = toStdErr;
}
/* Syslog/eventlog functions */
void setSyslogLevelInt( int loginfo_level ) {
currentLoginfoLevel = loginfo_level;
}
int getSyslogLevelInt() {
return currentLoginfoLevel;
}
void setSyslogLevel( const TCHAR *loginfo_level ) {
setSyslogLevelInt(getLogLevelForName(loginfo_level));
}
#ifndef WIN32
void setSyslogFacilityInt( int logfacility_level ) {
currentLogfacilityLevel = logfacility_level;
}
void setSyslogFacility( const TCHAR *loginfo_level ) {
setSyslogFacilityInt(getLogFacilityForName(loginfo_level));
}
#endif
void setSyslogEventSourceName( const TCHAR *event_source_name ) {
size_t size;
if (event_source_name != NULL) {
if (loginfoSourceName != defaultLoginfoSourceName) {
if (loginfoSourceName != NULL) {
free(loginfoSourceName);
}
}
#ifdef WIN32
size = sizeof(TCHAR) * (_tcslen(event_source_name) + 1);
#else
size = wcstombs(NULL, event_source_name, 0) + 1;
#endif
loginfoSourceName = malloc(size);
if (!loginfoSourceName) {
_tprintf(TEXT("Out of memory in logging code (%s)\n"), TEXT("SSESN"));
loginfoSourceName = defaultLoginfoSourceName;
return;
}
#ifdef WIN32
_tcsncpy(loginfoSourceName, event_source_name, _tcslen(event_source_name) + 1);
if (_tcslen(loginfoSourceName) > 32) {
loginfoSourceName[32] = TEXT('\0');
}
#else
wcstombs(loginfoSourceName, event_source_name, size);
if (strlen(loginfoSourceName) > 32) {
loginfoSourceName[32] = '\0';
}
#endif
}
}
void resetDuration() {
#ifdef WIN32
struct _timeb timebNow;
#else
struct timeval timevalNow;
#endif
time_t now;
int nowMillis;
#ifdef WIN32
_ftime(&timebNow);
now = (time_t)timebNow.time;
nowMillis = timebNow.millitm;
#else
gettimeofday(&timevalNow, NULL);
now = (time_t)timevalNow.tv_sec;
nowMillis = timevalNow.tv_usec / 1000;
#endif
previousNow = now;
previousNowMillis = nowMillis;
}
int getLowLogLevel() {
int lowLogLevel = (currentLogfileLevel < currentConsoleLevel ? currentLogfileLevel : currentConsoleLevel);
lowLogLevel = (currentLoginfoLevel < lowLogLevel ? currentLoginfoLevel : lowLogLevel);
return lowLogLevel;
}
TCHAR* preparePrintBuffer(size_t reqSize) {
if (threadPrintBuffer == NULL) {
threadPrintBuffer = malloc(sizeof(TCHAR) * reqSize);
if (!threadPrintBuffer) {
_tprintf(TEXT("Out of memory in logging code (%s)\n"), TEXT("PPB1"));
threadPrintBufferSize = 0;
return NULL;
}
threadPrintBufferSize = reqSize;
} else if (threadPrintBufferSize < reqSize) {
free(threadPrintBuffer);
threadPrintBuffer = malloc(sizeof(TCHAR) * reqSize);
if (!threadPrintBuffer) {
_tprintf(TEXT("Out of memory in logging code (%s)\n"), TEXT("PPB2"));
threadPrintBufferSize = 0;
return NULL;
}
threadPrintBufferSize = reqSize;
}
return threadPrintBuffer;
}
/* Writes to and then returns a buffer that is reused by the current thread.
* It should not be released. */
TCHAR* buildPrintBuffer( int source_id, int level, int threadId, int queued, struct tm *nowTM, int nowMillis, time_t durationMillis, const TCHAR *format, const TCHAR *defaultFormat, const TCHAR *message) {
int i;
size_t reqSize;
int numColumns;
TCHAR *pos;
int currentColumn;
int handledFormat;
int temp;
int len;
/* Decide the number of columns and come up with a required length for the printBuffer. */
reqSize = 0;
for( i = 0, numColumns = 0; i < (int)_tcslen( format ); i++ ) {
switch( format[i] ) {
case TEXT('P'):
case TEXT('p'):
reqSize += 8 + 3;
numColumns++;
break;
case TEXT('L'):
case TEXT('l'):
reqSize += 6 + 3;
numColumns++;
break;
case TEXT('D'):
case TEXT('d'):
reqSize += 7 + 3;
numColumns++;
break;
case TEXT('Q'):
case TEXT('q'):
reqSize += 1 + 3;
numColumns++;
break;
case TEXT('T'):
case TEXT('t'):
reqSize += 19 + 3;
numColumns++;
break;
case TEXT('Z'):
case TEXT('z'):
reqSize += 23 + 3;
numColumns++;
break;
case TEXT('U'):
case TEXT('u'):
reqSize += 8 + 3;
numColumns++;
break;
case TEXT('R'):
case TEXT('r'):
reqSize += 8 + 3;
numColumns++;
break;
case TEXT('G'):
case TEXT('g'):
reqSize += 10 + 3;
numColumns++;
break;
case TEXT('M'):
case TEXT('m'):
reqSize += _tcslen( message ) + 3;
numColumns++;
break;
}
}
if ((reqSize == 0) && (defaultFormat != NULL)) {
/* This means that the specified format was completely invalid.
* Recurse using the defaultFormat instead.
* The alternative would be to log an empty line, which is useless to everyone. */
return buildPrintBuffer( source_id, level, threadId, queued, nowTM, nowMillis, durationMillis, defaultFormat, NULL /* No default. Prevent further recursion. */, message );
}
/* Always add room for the null. */
reqSize += 1;
if ( !preparePrintBuffer(reqSize)) {
return NULL;
}
/* Always start with a null terminated string in case there are no formats specified. */
threadPrintBuffer[0] = TEXT('\0');
/* Create a pointer to the beginning of the print buffer, it will be advanced
* as the formatted message is build up. */
pos = threadPrintBuffer;
/* We now have a buffer large enough to store the entire formatted message. */
for( i = 0, currentColumn = 0, len = 0, temp = 0; i < (int)_tcslen( format ); i++ ) {
handledFormat = TRUE;
switch( format[i] ) {
case TEXT('P'):
case TEXT('p'):
switch ( source_id ) {
case WRAPPER_SOURCE_WRAPPER:
#ifdef WIN32
if (launcherSource) {
temp = _sntprintf( pos, reqSize - len, TEXT("wrapperm") );
} else {
temp = _sntprintf( pos, reqSize - len, TEXT("wrapper ") );
}
#else
temp = _sntprintf( pos, reqSize - len, TEXT("wrapper ") );
#endif
break;
case WRAPPER_SOURCE_PROTOCOL:
temp = _sntprintf( pos, reqSize - len, TEXT("wrapperp") );
break;
default:
temp = _sntprintf( pos, reqSize - len, TEXT("jvm %-4d"), source_id );
break;
}
currentColumn++;
break;
case TEXT('L'):
case TEXT('l'):
temp = _sntprintf( pos, reqSize - len, TEXT("%s"), logLevelNames[ level ] );
currentColumn++;
break;
case TEXT('D'):
case TEXT('d'):
switch ( threadId )
{
case WRAPPER_THREAD_SIGNAL:
temp = _sntprintf( pos, reqSize - len, TEXT("signal ") );
break;
case WRAPPER_THREAD_MAIN:
temp = _sntprintf( pos, reqSize - len, TEXT("main ") );
break;
case WRAPPER_THREAD_SRVMAIN:
temp = _sntprintf( pos, reqSize - len, TEXT("srvmain") );
break;
case WRAPPER_THREAD_TIMER:
temp = _sntprintf( pos, reqSize - len, TEXT("timer ") );
break;
case WRAPPER_THREAD_JAVAIO:
temp = _sntprintf( pos, reqSize - len, TEXT("javaio ") );
break;
case WRAPPER_THREAD_STARTUP:
temp = _sntprintf( pos, reqSize - len, TEXT("startup") );
break;
default:
temp = _sntprintf( pos, reqSize - len, TEXT("unknown") );
break;
}
currentColumn++;
break;
case TEXT('Q'):
case TEXT('q'):
temp = _sntprintf( pos, reqSize - len, TEXT("%c"), ( queued ? TEXT('Q') : TEXT(' ')));
currentColumn++;
break;
case TEXT('T'):
case TEXT('t'):
temp = _sntprintf( pos, reqSize - len, TEXT("%04d/%02d/%02d %02d:%02d:%02d"),
nowTM->tm_year + 1900, nowTM->tm_mon + 1, nowTM->tm_mday,
nowTM->tm_hour, nowTM->tm_min, nowTM->tm_sec );
currentColumn++;
break;
case TEXT('Z'):
case TEXT('z'):
temp = _sntprintf( pos, reqSize - len, TEXT("%04d/%02d/%02d %02d:%02d:%02d.%03d"),
nowTM->tm_year + 1900, nowTM->tm_mon + 1, nowTM->tm_mday,
nowTM->tm_hour, nowTM->tm_min, nowTM->tm_sec, nowMillis );
currentColumn++;
break;
case TEXT('U'):
case TEXT('u'):
if (uptimeFlipped) {
temp = _sntprintf( pos, reqSize - len, TEXT("--------") );
} else {
temp = _sntprintf( pos, reqSize - len, TEXT("%8d"), uptimeSeconds);
}
currentColumn++;
break;
case TEXT('R'):
case TEXT('r'):
if (durationMillis == (time_t)-1) {
temp = _sntprintf( pos, reqSize - len, TEXT(" ") );
} else if (durationMillis > 99999999) {
temp = _sntprintf( pos, reqSize - len, TEXT("99999999") );
} else {
temp = _sntprintf( pos, reqSize - len, TEXT("%8d"), durationMillis);
}
currentColumn++;
break;
case TEXT('G'):
case TEXT('g'):
temp = _sntprintf( pos, reqSize - len, TEXT("%8d"), __min(previousLogLag, 99999999));
currentColumn++;
break;
case TEXT('M'):
case TEXT('m'):
temp = _sntprintf( pos, reqSize - len, TEXT("%s"), message );
currentColumn++;
break;
default:
handledFormat = FALSE;
}
if (handledFormat) {
pos += temp;
len += temp;
/* Add separator chars */
if (currentColumn != numColumns) {
temp = _sntprintf(pos, reqSize - len, TEXT(" | "));
pos += temp;
len += temp;
}
}
}
/* Return the print buffer to the caller. */
return threadPrintBuffer;
}
/**
* Generates a log file name given.
*
* buffer - Buffer into which to _sntprintf the generated name.
* template - Template from which the name is generated.
* nowDate - Optional date used to replace any YYYYMMDD tokens.
* rollNum - Optional roll number used to replace any ROLLNUM tokens.
*/
void generateLogFileName(TCHAR *buffer, const TCHAR *template, const TCHAR *nowDate, const TCHAR *rollNum ) {
/* Copy the template to the buffer to get started. */
_tcsncpy(buffer, template, _tcslen(logFilePath) + 11);
/* Handle the date token. */
if (_tcsstr(buffer, TEXT("YYYYMMDD"))) {
if (nowDate == NULL) {
/* The token needs to be removed. */
replaceStringLongWithShort(buffer, TEXT("-YYYYMMDD"), NULL);
replaceStringLongWithShort(buffer, TEXT("_YYYYMMDD"), NULL);
replaceStringLongWithShort(buffer, TEXT(".YYYYMMDD"), NULL);
replaceStringLongWithShort(buffer, TEXT("YYYYMMDD"), NULL);
} else {
/* The token needs to be replaced. */
replaceStringLongWithShort(buffer, TEXT("YYYYMMDD"), nowDate);
}
}
/* Handle the roll number token. */
if (_tcsstr(buffer, TEXT("ROLLNUM"))) {
if (rollNum == NULL ) {
/* The token needs to be removed. */
replaceStringLongWithShort(buffer, TEXT("-ROLLNUM"), NULL);
replaceStringLongWithShort(buffer, TEXT("_ROLLNUM"), NULL);
replaceStringLongWithShort(buffer, TEXT(".ROLLNUM"), NULL);
replaceStringLongWithShort(buffer, TEXT("ROLLNUM"), NULL);
} else {
/* The token needs to be replaced. */
replaceStringLongWithShort(buffer, TEXT("ROLLNUM"), rollNum);
}
} else {
/* The name did not contain a ROLLNUM token. */
if (rollNum != NULL ) {
/* Generate the name as if ".ROLLNUM" was appended to the template. */
_sntprintf(buffer + _tcslen(buffer), logFileNameSize, TEXT(".%s"), rollNum);
}
}
}
/**
* Prints the contents of a buffer to the sysLog target. The log level is
* tested prior to this function being called.
*
* Must be called while locked.
*/
void log_printf_message_sysLogInner(int source_id, int level, TCHAR *message, struct tm *nowTM) {
#ifdef WIN32
sendEventlogMessage(source_id, level, message);
#else
sendLoginfoMessage(source_id, level, message);
#endif
}
/**
* @param invertLogLevelCheck There is a special case where we want to log to
* the syslog IF and only if the normal log output
* would not go to the syslog. This flag makes it
* possible to log if it we normally would not.
*/
void log_printf_message_sysLog(int source_id, int level, TCHAR *message, struct tm *nowTM, int invertLogLevelCheck) {
switch (level) {
case LEVEL_NOTICE:
case LEVEL_ADVICE:
/* Advice and Notice level messages are special in that they never get logged to the
* EventLog / SysLog. */
break;
default:
if (invertLogLevelCheck) {
/* Log if we normally should not log. */
if (level < currentLoginfoLevel) {
log_printf_message_sysLogInner(source_id, level, message, nowTM);
}
} else {
if (level >= currentLoginfoLevel) {
log_printf_message_sysLogInner(source_id, level, message, nowTM);
}
}
}
}
/**
* Prints the contents of a buffer to the logfile target. The log level is
* tested prior to this function being called.
*
* Must be called while locked.
*
* @return True if the logfile name changed.
*/
int log_printf_message_logFileInner(int source_id, int level, int threadId, int queued, TCHAR *message, struct tm *nowTM, int nowMillis, time_t durationMillis) {
int logFileChanged = FALSE;
TCHAR nowDate[9];
TCHAR *printBuffer;
int old_umask;
const TCHAR *tempBufferFormat;
const TCHAR *tempBufferLastErrorText;
size_t tempBufferLen;
TCHAR *tempBuffer;
/* If the log file was set to a blank value then it will not be used. */
if (logFilePath && (_tcslen(logFilePath) > 0)) {
/* If this the roll mode is date then we need a nowDate for this log entry. */
if (logFileRollMode & ROLL_MODE_DATE) {
_sntprintf(nowDate, 9, TEXT("%04d%02d%02d"), nowTM->tm_year + 1900, nowTM->tm_mon + 1, nowTM->tm_mday );
} else {
nowDate[0] = TEXT('\0');
}
/* Make sure that the log file does not need to be rolled. */
checkAndRollLogs(nowDate);
/* If the file needs to be opened then do so. */
if (logfileFP == NULL) {
/* Generate the log file name if it is not already set. */
if (currentLogFileName[0] == TEXT('\0')) {
if (logFileRollMode & ROLL_MODE_DATE) {
generateLogFileName(currentLogFileName, logFilePath, nowDate, NULL);
} else {
generateLogFileName(currentLogFileName, logFilePath, NULL, NULL);
}
logFileChanged = TRUE;
}
old_umask = umask( logFileUmask );
logfileFP = _tfopen(currentLogFileName, TEXT("a"));
if (logfileFP == NULL) {
/* The log file could not be opened. */
/* We need to write our error message into a buffer manually so we can use it
* both for the log_printf_queue and log_printf_message_sysLog calls below. */
tempBufferFormat = TEXT("Unable to write to the configured log file: %s (%s)\n Falling back to the default file in the current working directory: %s");
tempBufferLastErrorText = getLastErrorText();
tempBufferLen = _tcslen(tempBufferFormat) - 2 - 2 - 2 + _tcslen(currentLogFileName) + _tcslen(tempBufferLastErrorText) + _tcslen(defaultLogFile) + 1;
tempBuffer = malloc(sizeof(TCHAR) * tempBufferLen);
if (!tempBuffer) {
outOfMemoryQueued(TEXT("LPML"), 1 );
} else {
_sntprintf(tempBuffer, tempBufferLen, tempBufferFormat, currentLogFileName, getLastErrorText(), defaultLogFile);
log_printf_queue(TRUE, WRAPPER_SOURCE_WRAPPER, LEVEL_WARN, TEXT("%s"), tempBuffer);
/* This is critical for debugging problems. If the above message would not have shown
* up in the syslog then send it there manually. We are already locked here so this
* can be done safely. */
log_printf_message_sysLog(WRAPPER_SOURCE_WRAPPER, LEVEL_WARN, tempBuffer, nowTM, TRUE);
free(tempBuffer);
}
/* Try the default file location. */
setLogfilePath(defaultLogFile, NULL, TRUE);
_sntprintf(currentLogFileName, logFileNameSize, defaultLogFile);
logFileChanged = TRUE;
logfileFP = _tfopen(currentLogFileName, TEXT("a"));
if (logfileFP == NULL) {
/* Still unable to write. */
/* We need to write our error message into a buffer manually so we can use it
* both for the log_printf_queue and log_printf_message_sysLog calls below. */
tempBufferFormat = TEXT("Unable to write to the default log file: %s (%s)\n Disabling log file.");
tempBufferLastErrorText = getLastErrorText();
tempBufferLen = _tcslen(tempBufferFormat) - 2 - 2 + _tcslen(currentLogFileName) + _tcslen(tempBufferLastErrorText) + 1;
tempBuffer = malloc(sizeof(TCHAR) * tempBufferLen);
if (!tempBuffer) {
outOfMemoryQueued(TEXT("LPML"), 1 );
} else {
_sntprintf(tempBuffer, tempBufferLen, tempBufferFormat, currentLogFileName, getLastErrorText());
log_printf_queue(TRUE, WRAPPER_SOURCE_WRAPPER, LEVEL_WARN, TEXT("%s"), tempBuffer);
/* This is critical for debugging problems. If the above message would not have shown
* up in the syslog then send it there manually. We are already locked here so this
* can be done safely. */
log_printf_message_sysLog(WRAPPER_SOURCE_WRAPPER, LEVEL_WARN, tempBuffer, nowTM, TRUE);
free(tempBuffer);
}
setLogfileLevelInt(LEVEL_NONE);
logFileChanged = FALSE;
}
}
umask(old_umask);
#ifdef _DEBUG
if (logfileFP != NULL) {
_tprintf(TEXT("Opened logfile\n"));
}
#endif
}
if (logfileFP == NULL) {
currentLogFileName[0] = TEXT('\0');
/* Failure to write to logfile already reported. */
} else {
/* We need to store the date the file was opened for. */
_tcsncpy(logFileLastNowDate, nowDate, 9);
/* Build up the printBuffer. */
printBuffer = buildPrintBuffer(source_id, level, threadId, queued, nowTM, nowMillis, durationMillis, logfileFormat, LOG_FORMAT_LOGFILE_DEFAULT, message);
if (printBuffer) {
_ftprintf(logfileFP, TEXT("%s\n"), printBuffer);
logFileAccessed = TRUE;
/* Increment the activity counter. */
logfileActivityCount++;
/* Decide whether we want to close or flush the log file immediately after each line.
* If not then flushing and closing will be handled externally by calling flushLogfile() or closeLogfile(). */
if (autoCloseLogfile) {
/* Close the log file immediately. */
#ifdef _DEBUG
_tprintf(TEXT("Closing logfile immediately...\n"));
#endif
fclose(logfileFP);
logfileFP = NULL;
/* Do not clear the currentLogFileName here as we are not changing its name. */
} else if (autoFlushLogfile) {
/* Flush the log file immediately. */
#ifdef _DEBUG
_tprintf(TEXT("Flushing logfile immediately...\n"));
#endif
fflush(logfileFP);
}
/* Leave the file open. It will be closed later after a period of inactivity. */
}
}
}
return logFileChanged;
}
int log_printf_message_logFile(int source_id, int level, int threadId, int queued, TCHAR *message, struct tm *nowTM, int nowMillis, time_t durationMillis) {
int logFileChanged = FALSE;
if (level >= currentLogfileLevel) {
logFileChanged = log_printf_message_logFileInner(source_id, level, threadId, queued, message, nowTM, nowMillis, durationMillis);
}
return logFileChanged;
}
/**
* Prints the contents of a buffer to the console target. The log level is
* tested prior to this function being called.
*
* Must be called while locked.
*/
void log_printf_message_consoleInner(int source_id, int level, int threadId, int queued, TCHAR *message, struct tm *nowTM, int nowMillis, time_t durationMillis) {
TCHAR *printBuffer;
FILE *target;
#ifdef WIN32
HANDLE targetH;
int complete = FALSE;
#endif
/* Build up the printBuffer. */
printBuffer = buildPrintBuffer(source_id, level, threadId, queued, nowTM, nowMillis, durationMillis, consoleFormat, LOG_FORMAT_CONSOLE_DEFAULT, message);
if (printBuffer) {
/* Decide where to send the output. */
switch (level) {
case LEVEL_FATAL:
if (consoleFatalToStdErr) {
target = stderr;
} else {
target = stdout;
}
break;
case LEVEL_ERROR:
if (consoleErrorToStdErr) {
target = stderr;
} else {
target = stdout;
}
break;
case LEVEL_WARN:
if (consoleWarnToStdErr) {
target = stderr;
} else {
target = stdout;
}
break;
default:
target = stdout;
break;
}
/* Write the print buffer to the console. */
#ifdef WIN32
/* Using the WinAPI function WriteConsole would make it impossible to pipe the console output.
* We never want to allow direct console writing if this is a launcher instance.*/
if (consoleDirect) {
if (target == stderr) {
targetH = GetStdHandle(STD_ERROR_HANDLE);
} else {
targetH = GetStdHandle(STD_OUTPUT_HANDLE);
}
if (targetH != NULL) {
complete = writeToConsole(targetH, TEXT("%s\n"), printBuffer);
} else {
/* Should not happen. But just in case. */
_tprintf(TEXT("Failed to find standard handle. Disabled direct console output.\n"));
consoleDirect = FALSE;
}
}
if (!complete) {
#endif
_ftprintf(target, TEXT("%s\n"), printBuffer);
if (consoleFlush) {
fflush(target);
}
#ifdef WIN32
}
#endif
}
}
void log_printf_message_console(int source_id, int level, int threadId, int queued, TCHAR *message, struct tm *nowTM, int nowMillis, time_t durationMillis) {
if (level >= currentConsoleLevel) {
log_printf_message_consoleInner(source_id, level, threadId, queued, message, nowTM, nowMillis, durationMillis);
}
}
/**
* Prints the contents of a buffer to all configured targets.
*
* Must be called while locked.
*
* @param sysLogEnabled A flag that is used to help with recursion to control
* whether or not the syslog should be considered as a log
* target for this call. It is always disabled when we
* recurse.
*
* @return True if the logfile name changed.
*/
int log_printf_message(int source_id, int level, int threadId, int queued, TCHAR *message, int sysLogEnabled) {
#ifndef WIN32
TCHAR *printBuffer;
FILE *target;
#endif
int logFileChanged = FALSE;
TCHAR *subMessage;
TCHAR *nextLF;
#ifdef WIN32
struct _timeb timebNow;
#else
size_t reqSize;
struct timeval timevalNow;
TCHAR intBuffer[3];
TCHAR* pos;
#endif
time_t now;
int nowMillis;
struct tm *nowTM;
time_t durationMillis;
#ifndef WIN32
if ((_tcsstr(message, LOG_SPECIAL_MARKER) == message) && (_tcslen(message) >= _tcslen(LOG_SPECIAL_MARKER) + 10)) {
/* Got a special encoded log message from the child Wrapper process.
* Parse it and continue as if the log message came from this process.
* These should never be multi-line messages as the forked child
* process will have already broken them up. */
pos = (TCHAR *)(message + _tcslen(LOG_SPECIAL_MARKER) + 1);
/* source_id */
_tcsncpy(intBuffer, pos, 2);
intBuffer[2] = TEXT('\0');
source_id = _ttoi(intBuffer);
pos += 3;
/* level */
_tcsncpy(intBuffer, pos, 2);
intBuffer[2] = TEXT('\0');
level = _ttoi(intBuffer);
pos += 3;
/* threadId */
_tcsncpy(intBuffer, pos, 2);
intBuffer[2] = TEXT('\0');
threadId = _ttoi(intBuffer);
pos += 3;
/* message */
message = pos;
}
#endif
/* Build a timestamp */
#ifdef WIN32
_ftime( &timebNow );
now = (time_t)timebNow.time;
nowMillis = timebNow.millitm;
#else
gettimeofday( &timevalNow, NULL );
now = (time_t)timevalNow.tv_sec;
nowMillis = timevalNow.tv_usec / 1000;
#endif
nowTM = localtime( &now );
/* Calculate the number of milliseconds which have passed since the previous log entry.
* We only need to display up to 8 digits, so if the result is going to be larger than
* that, set it to 100000000.
* We only want to do this for output coming from the JVM. Any other log output should
* be set to (time_t)-1. */
switch(source_id) {
case WRAPPER_SOURCE_WRAPPER:
case WRAPPER_SOURCE_PROTOCOL:
durationMillis = (time_t)-1;
break;
default:
if (now - previousNow > 100000) {
/* Without looking at the millis, we know it is already too long. */
durationMillis = 100000000;
} else {
durationMillis = (now - previousNow) * 1000 + nowMillis - previousNowMillis;
}
previousNow = now;
previousNowMillis = nowMillis;
break;
}
/* Syslog messages are printed first so we can print them including line feeds as is.
* This must be done before we break up multi-line messages into individual lines. */
#ifdef WIN32
if (sysLogEnabled) {
#else
/* On UNIX we never want to log to the syslog here if this is in a forked thread.
* In this case, any lines will be broken up into individual lines and then logged
* as usual by the main process. But this can't be helped and is very rare anyway. */
if (sysLogEnabled && (_tcsstr(message, LOG_FORK_MARKER) != message)) {
#endif
/* syslog/Eventlog. */
log_printf_message_sysLog(source_id, level, message, nowTM, FALSE);
}
/* If the message contains line feeds then break up the line into substrings and recurse. */
subMessage = message;
nextLF = _tcschr(subMessage, TEXT('\n'));
if (nextLF) {
/* This string contains more than one line. Loop over the strings. It is Ok to corrupt this string because it is only used once. */
while (nextLF) {
nextLF[0] = TEXT('\0');
logFileChanged |= log_printf_message(source_id, level, threadId, queued, subMessage, FALSE);
/* Locate the next one. */
subMessage = &(nextLF[1]);
nextLF = _tcschr(subMessage, TEXT('\n'));
}
/* The rest of the buffer will be the final line. */
logFileChanged |= log_printf_message(source_id, level, threadId, queued, subMessage, FALSE);
return logFileChanged;
}
#ifndef WIN32
/* See if this is a special case log entry from the forked child. */
if (_tcsstr(message, LOG_FORK_MARKER) == message) {
/* Found the marker. We only want to log the message as is to the console with a special prefix.
* This is used to pass the log output through the pipe to the parent Wrapper process where it
* will be decoded below and displayed appropriately. */
reqSize = _tcslen(LOG_SPECIAL_MARKER) + 1 + 2 + 1 + 2 + 1 + 2 + 1 + _tcslen(message) - _tcslen(LOG_FORK_MARKER) + 1;
if (!(printBuffer = preparePrintBuffer(reqSize))) {
return FALSE;
}
_sntprintf(printBuffer, reqSize, TEXT("%s|%02d|%02d|%02d|%s"), LOG_SPECIAL_MARKER, source_id, level, threadId, message + _tcslen(LOG_FORK_MARKER));
/* Decide where to send the output. */
switch (level) {
case LEVEL_FATAL:
if (consoleFatalToStdErr) {
target = stderr;
} else {
target = stdout;
}
break;
case LEVEL_ERROR:
if (consoleErrorToStdErr) {
target = stderr;
} else {
target = stdout;
}
break;
case LEVEL_WARN:
if (consoleWarnToStdErr) {
target = stderr;
} else {
target = stdout;
}
break;
default:
target = stdout;
break;
}
_ftprintf(target, TEXT("%s\n"), printBuffer);
if (consoleFlush) {
fflush(target);
}
return FALSE;
}
#endif
/* Get the current threadId. */
if ( threadId < 0 )
{
/* The current thread was specified. Resolve what thread this actually is. */
threadId = getThreadId();
}
/* Console output by format */
log_printf_message_console(source_id, level, threadId, queued, message, nowTM, nowMillis, durationMillis);
/* Logfile output by format */
logFileChanged = log_printf_message_logFile(source_id, level, threadId, queued, message, nowTM, nowMillis, durationMillis);
return logFileChanged;
}
/**
* Used for testing to pause the current thread for the specified number of seconds.
* This can only be called when logging is locked.
*
* @param pauseTime Number of seconds to pause, 0 pauses indefinitely.
*/
void pauseThread(int pauseTime) {
int i;
if (pauseTime > 0) {
for (i = 0; i < pauseTime; i++) {
logSleep(1000);
}
} else {
while (TRUE) {
logSleep(1000);
}
}
}
/* General log functions */
void log_printf( int source_id, int level, const TCHAR *lpszFmt, ... ) {
va_list vargs;
int count;
int threadId;
int logFileChanged;
TCHAR *logFileCopy;
#if defined(UNICODE) && !defined(WIN32)
TCHAR *msg = NULL;
int i;
int flag;
#endif
#ifdef WIN32
struct _timeb timebNow;
#else
struct timeval timevalNow;
#endif
time_t startNow;
int startNowMillis;
time_t endNow;
int endNowMillis;
if (level == LEVEL_NONE) {
/* Some APIs allow the user to potentially configure the NONE log level. Skip it as it means no logging in this case. */
return;
}
/* If we are checking on the log time then store the start time. */
if (logPrintfWarnThreshold > 0) {
#ifdef WIN32
_ftime(&timebNow);
startNow = (time_t)timebNow.time;
startNowMillis = timebNow.millitm;
#else
gettimeofday(&timevalNow, NULL);
startNow = (time_t)timevalNow.tv_sec;
startNowMillis = timevalNow.tv_usec / 1000;
#endif
} else {
startNow = 0;
startNowMillis = 0;
}
/* We need to be very careful that only one thread is allowed in here
* at a time. On Windows this is done using a Mutex object that is
* initialized in the initLogging function. */
if (lockLoggingMutex()) {
return;
}
/* If there is a queued pause then do so. */
if ((logPauseTime >= 0) && (level > LEVEL_DEBUG) && (source_id < 0)) {
pauseThread(logPauseTime);
logPauseTime = -1;
}
#if defined(UNICODE) && !defined(WIN32)
if (source_id < 1 && wcsstr(lpszFmt, TEXT("%s")) != NULL) {
msg = malloc(sizeof(wchar_t) * (wcslen(lpszFmt) + 1));
if (msg) {
/* Loop over the format and convert all '%s' patterns to %S' so the UNICODE displays correctly. */
if (wcslen(lpszFmt) > 0) {
for (i = 0; i < _tcslen(lpszFmt); i++){
msg[i] = lpszFmt[i];
if ((lpszFmt[i] == TEXT('%')) && (i < _tcslen(lpszFmt)) && (lpszFmt[i + 1] == TEXT('s')) && ((i == 0) || (lpszFmt[i - 1] != TEXT('%')))){
msg[i+1] = TEXT('S'); i++;
}
}
}
msg[wcslen(lpszFmt)] = TEXT('\0');
} else {
_tprintf(TEXT("Out of memory in logging code (%s)\n"), TEXT("P0"));
return;
}
flag = TRUE;
} else {
msg = (TCHAR*) lpszFmt;
flag = FALSE;
}
#endif
threadId = getThreadId();
if (source_id <= 0) {
/* Loop until the buffer is large enough that we are able to successfully
* print into it. Once the buffer has grown to the largest message size,
* smaller messages will pass through this code without looping. */
do {
if ( threadMessageBufferSize == 0 )
{
/* No buffer yet. Allocate one to get started. */
threadMessageBufferSize = 100;
#if defined(HPUX)
/* Due to a bug in the HPUX libc (version < 1403), the length of the buffer passed to _vsntprintf must have a length of 1 + N, where N is a multiple of 8. Adjust it as necessary. */
threadMessageBufferSize = threadMessageBufferSize + (((threadMessageBufferSize - 1) % 8) == 0 ? 0 : 8 - ((threadMessageBufferSize - 1) % 8));
#endif
threadMessageBuffer = malloc(sizeof(TCHAR) * threadMessageBufferSize);
if (!threadMessageBuffer) {
_tprintf(TEXT("Out of memory in logging code (%s)\n"), TEXT("P1"));
threadMessageBufferSize = 0;
#if defined(UNICODE) && !defined(WIN32)
if (flag == TRUE) {
free(msg);
}
#endif
return;
}
}
/* Try writing to the buffer. */
va_start( vargs, lpszFmt );
#if defined(UNICODE) && !defined(WIN32)
count = _vsntprintf( threadMessageBuffer, threadMessageBufferSize, msg, vargs );
#else
count = _vsntprintf( threadMessageBuffer, threadMessageBufferSize, lpszFmt, vargs );
#endif
va_end( vargs );
/*
_tprintf(TEXT(" vsnprintf->%d, size=%d\n"), count, threadMessageBufferSize );
*/
if ( ( count < 0 ) || ( count >= (int)threadMessageBufferSize ) ) {
/* If the count is exactly equal to the buffer size then a null TCHAR was not written.
* It must be larger.
* Windows will return -1 if the buffer is too small. If the number is
* exact however, we still need to expand it to have room for the null.
* UNIX will return the required size. */
/* Free the old buffer for starters. */
free( threadMessageBuffer );
/* Decide on a new buffer size.
* We can't tell how long the resulting string will be without expanding because the
* results are stored in the vargs.
* Most messages will be short, but there is a possibility that some will be very
* long. To minimize the number of times that we need to loop, while at the same
* time trying to avoid using too much memory, increase the size by the maximum of
* 1024 or 10% of the current length.
* Some platforms will return the required size as count. Use that if available. */
threadMessageBufferSize = __max(threadMessageBufferSize + 1024, __max(threadMessageBufferSize + threadMessageBufferSize / 10, (size_t)count + 1));
#if defined(HPUX)
/* Due to a bug in the HPUX libc (version < 1403), the length of the buffer passed to _vsntprintf must have a length of 1 + N, where N is a multiple of 8. Adjust it as necessary. */
threadMessageBufferSize = threadMessageBufferSize + (((threadMessageBufferSize - 1) % 8) == 0 ? 0 : 8 - ((threadMessageBufferSize - 1) % 8));
#endif
threadMessageBuffer = malloc(sizeof(TCHAR) * threadMessageBufferSize);
if (!threadMessageBuffer) {
_tprintf(TEXT("Out of memory in logging code (%s)\n"), TEXT("P3"));
threadMessageBufferSize = 0;
#if defined(UNICODE) && !defined(WIN32)
if (flag == TRUE) {
free(msg);
}
#endif
return;
}
/* Always set the count to -1 so we will loop again. */
count = -1;
}
} while ( count < 0 );
}
#if defined(UNICODE) && !defined(WIN32)
if (flag == TRUE) {
free(msg);
}
#endif
logFileCopy = NULL;
if (source_id > 0) {
#if defined(UNICODE) && !defined(WIN32)
logFileChanged = log_printf_message(source_id, level, threadId, FALSE, msg, TRUE);
#else
logFileChanged = log_printf_message(source_id, level, threadId, FALSE, (TCHAR*) lpszFmt, TRUE);
#endif
} else {
logFileChanged = log_printf_message(source_id, level, threadId, FALSE, threadMessageBuffer, TRUE);
}
if (logFileChanged) {
/* We need to enqueue a notification that the log file name was changed.
* We can NOT directly send the notification here as that could cause a deadlock,
* depending on where exactly this function was called from. (See Wrapper protocol mutex.) */
logFileCopy = malloc(sizeof(TCHAR) * (_tcslen(currentLogFileName) + 1));
if (!logFileCopy) {
_tprintf(TEXT("Out of memory in logging code (%s)\n"), TEXT("P3"));
} else {
_tcsncpy(logFileCopy, currentLogFileName, _tcslen(currentLogFileName) + 1);
/* Now after we have 100% prepared the log file name. Put into the queue variable
* so the maintainLogging() function can safely grab it at any time.
* The reading code is also in a semaphore so we can do a quick test here safely as well. */
if (pendingLogFileChange) {
/* The previous file was still in the queue. Free it up to avoid a memory leak.
* This can happen if the log file size is 1k or something like that. We will always
* keep the most recent file however, so this should not be that big a problem. */
#ifdef _DEBUG
_tprintf(TEXT("Log file name change was overwritten in queue: %s\n"), pendingLogFileChange);
#endif
free(pendingLogFileChange);
}
pendingLogFileChange = logFileCopy;
}
}
/* Release the lock we have on this function so that other threads can get in. */
if (releaseLoggingMutex()) {
return;
}
/* If we are checking on the log time then store the stop time.
* It is Ok that some of the error paths don't make it this far. */
if (logPrintfWarnThreshold > 0) {
#ifdef WIN32
_ftime(&timebNow);
endNow = (time_t)timebNow.time;
endNowMillis = timebNow.millitm;
#else
gettimeofday(&timevalNow, NULL);
endNow = (time_t)timevalNow.tv_sec;
endNowMillis = timevalNow.tv_usec / 1000;
#endif
previousLogLag = __min(endNow - startNow, 3600) * 1000 + endNowMillis - startNowMillis;
if (previousLogLag >= logPrintfWarnThreshold) {
log_printf_queue(TRUE, WRAPPER_SOURCE_WRAPPER, LEVEL_WARN, TEXT("Write to log took %d milliseconds."), previousLogLag);
}
}
}
/* Internal functions */
/**
* Create an error message from GetLastError() using the
* FormatMessage API Call...
*/
#ifdef WIN32
TCHAR lastErrBuf[1024];
TCHAR* getLastErrorText() {
DWORD dwRet;
TCHAR* lpszTemp = NULL;
dwRet = FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |FORMAT_MESSAGE_ARGUMENT_ARRAY,
NULL,
GetLastError(),
LANG_NEUTRAL,
(TCHAR*)&lpszTemp,
0,
NULL);
/* supplied buffer is not long enough */
if (!dwRet || ((long)1023 < (long)dwRet+14)) {
lastErrBuf[0] = TEXT('\0');
} else {
lpszTemp[lstrlen(lpszTemp)-2] = TEXT('\0'); /*remove cr and newline character */
_sntprintf( lastErrBuf, 1024, TEXT("%s (0x%x)"), lpszTemp, GetLastError());
}
/* following the documentation of FormatMessage, LocalFree should be called to free the output buffer. */
if (lpszTemp) {
LocalFree(lpszTemp);
}
return lastErrBuf;
}
int getLastError() {
return GetLastError();
}
#else
TCHAR* getLastErrorText() {
#ifdef UNICODE
char* c;
TCHAR* t;
size_t req;
c = strerror(errno);
req = mbstowcs(NULL, c, 0);
if (req == (size_t)-1) {
invalidMultiByteSequence(TEXT("GLET"), 1);
return NULL;
}
t = malloc(sizeof(TCHAR) * (req + 1));
if (!t) {
_tprintf(TEXT("Out of memory in logging code (%s)\n"), TEXT("GLET1"));
return NULL;
}
mbstowcs(t, c, req + 1);
return t;
#else
return strerror(errno);
#endif
}
int getLastError() {
return errno;
}
#endif
int registerSyslogMessageFile( ) {
#ifdef WIN32
TCHAR buffer[_MAX_PATH];
DWORD usedLen;
TCHAR regPath[1024];
HKEY hKey;
DWORD categoryCount, typesSupported;
/* Get absolute path to service manager */
usedLen = GetModuleFileName(NULL, buffer, _MAX_PATH);
if (usedLen == 0) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_FATAL, TEXT("Unable to obtain the full path to the Wrapper. %s"), getLastErrorText());
return -1;
} else if ((usedLen == _MAX_PATH) || (getLastError() == ERROR_INSUFFICIENT_BUFFER)) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_FATAL, TEXT("Unable to obtain the full path to the Wrapper. %s"), TEXT("Path to Wrapper binary too long."));
return -1;
} else {
_sntprintf( regPath, 1024, TEXT("SYSTEM\\CurrentControlSet\\Services\\Eventlog\\Application\\%s"), loginfoSourceName );
if( RegCreateKey( HKEY_LOCAL_MACHINE, regPath, (PHKEY) &hKey ) == ERROR_SUCCESS ) {
RegCloseKey( hKey );
if( RegOpenKeyEx( HKEY_LOCAL_MACHINE, regPath, 0, KEY_WRITE, (PHKEY) &hKey ) == ERROR_SUCCESS ) {
/* Set EventMessageFile */
if( RegSetValueEx( hKey, TEXT("EventMessageFile"), (DWORD) 0, (DWORD) REG_SZ, (LPBYTE) buffer, (DWORD)(sizeof(TCHAR) * (_tcslen(buffer) + 1))) != ERROR_SUCCESS ) {
RegCloseKey( hKey );
return -1;
}
/* Set CategoryMessageFile */
if( RegSetValueEx( hKey, TEXT("CategoryMessageFile"), (DWORD) 0, (DWORD) REG_SZ, (LPBYTE) buffer, (DWORD)(sizeof(TCHAR) * (_tcslen(buffer) + 1))) != ERROR_SUCCESS ) {
RegCloseKey( hKey );
return -1;
}
/* Set CategoryCount */
categoryCount = 12;
if( RegSetValueEx( hKey, TEXT("CategoryCount"), (DWORD) 0, (DWORD) REG_DWORD, (LPBYTE) &categoryCount, sizeof(DWORD) ) != ERROR_SUCCESS ) {
RegCloseKey( hKey );
return -1;
}
/* Set TypesSupported */
typesSupported = 7;
if( RegSetValueEx( hKey, TEXT("TypesSupported"), (DWORD) 0, (DWORD) REG_DWORD, (LPBYTE) &typesSupported, sizeof(DWORD) ) != ERROR_SUCCESS ) {
RegCloseKey( hKey );
return -1;
}
RegCloseKey( hKey );
return 0;
}
}
}
return -1; /* Failure */
#else
return 0;
#endif
}
int unregisterSyslogMessageFile( ) {
#ifdef WIN32
/* If we deregister this application, then the event viewer will not work when the program is not running. */
/* Don't want to clutter up the Registry, but is there another way? */
TCHAR regPath[ 1024 ];
/* Get absolute path to service manager */
_sntprintf( regPath, 1024, TEXT("SYSTEM\\CurrentControlSet\\Services\\Eventlog\\Application\\%s"), loginfoSourceName );
if( RegDeleteKey( HKEY_LOCAL_MACHINE, regPath ) == ERROR_SUCCESS )
return 0;
return -1; /* Failure */
#else
return 0;
#endif
}
#ifdef WIN32
void sendEventlogMessage( int source_id, int level, const TCHAR *szBuff ) {
TCHAR header[16];
const TCHAR **strings;
WORD eventType;
HANDLE handle;
WORD eventID, categoryID;
int result;
strings = malloc(sizeof(TCHAR *) * 3);
if (!strings) {
_tprintf(TEXT("Out of memory in logging code (%s)\n"), TEXT("SEM1"));
return;
}
/* Build the source header */
switch(source_id) {
case WRAPPER_SOURCE_WRAPPER:
#ifdef WIN32
if (launcherSource) {
_sntprintf( header, 16, TEXT("wrapperm") );
} else {
_sntprintf( header, 16, TEXT("wrapper") );
}
#else
_sntprintf( header, 16, TEXT("wrapper") );
#endif
break;
case WRAPPER_SOURCE_PROTOCOL:
_sntprintf( header, 16, TEXT("wrapperp") );
break;
default:
_sntprintf( header, 16, TEXT("jvm %d"), source_id );
break;
}
/* Build event type by level */
switch(level) {
case LEVEL_NOTICE: /* Will not get in here. */
case LEVEL_ADVICE: /* Will not get in here. */
case LEVEL_FATAL:
eventType = EVENTLOG_ERROR_TYPE;
break;
case LEVEL_ERROR:
case LEVEL_WARN:
eventType = EVENTLOG_WARNING_TYPE;
break;
case LEVEL_STATUS:
case LEVEL_INFO:
case LEVEL_DEBUG:
eventType = EVENTLOG_INFORMATION_TYPE;
break;
}
/* Set the category id to the appropriate resource id. */
if ( source_id == WRAPPER_SOURCE_WRAPPER ) {
categoryID = MSG_EVENT_LOG_CATEGORY_WRAPPER;
} else if ( source_id == WRAPPER_SOURCE_PROTOCOL ) {
categoryID = MSG_EVENT_LOG_CATEGORY_PROTOCOL;
} else {
/* Source is a JVM. */
switch ( source_id ) {
case 1:
categoryID = MSG_EVENT_LOG_CATEGORY_JVM1;
break;
case 2:
categoryID = MSG_EVENT_LOG_CATEGORY_JVM2;
break;
case 3:
categoryID = MSG_EVENT_LOG_CATEGORY_JVM3;
break;
case 4:
categoryID = MSG_EVENT_LOG_CATEGORY_JVM4;
break;
case 5:
categoryID = MSG_EVENT_LOG_CATEGORY_JVM5;
break;
case 6:
categoryID = MSG_EVENT_LOG_CATEGORY_JVM6;
break;
case 7:
categoryID = MSG_EVENT_LOG_CATEGORY_JVM7;
break;
case 8:
categoryID = MSG_EVENT_LOG_CATEGORY_JVM8;
break;
case 9:
categoryID = MSG_EVENT_LOG_CATEGORY_JVM9;
break;
default:
categoryID = MSG_EVENT_LOG_CATEGORY_JVMXX;
break;
}
}
/* Place event in eventlog */
strings[0] = header;
strings[1] = szBuff;
strings[2] = 0;
eventID = level;
handle = RegisterEventSource( NULL, loginfoSourceName );
if( !handle )
return;
result = ReportEvent(
handle, /* handle to event log */
eventType, /* event type */
categoryID, /* event category */
MSG_EVENT_LOG_MESSAGE, /* event identifier */
NULL, /* user security identifier */
2, /* number of strings to merge */
0, /* size of binary data */
(const TCHAR**) strings, /* array of strings to merge */
NULL /* binary data buffer */
);
if (result == 0) {
/* If there are any errors accessing the event log, like it is full, then disable its output. */
setSyslogLevelInt(LEVEL_NONE);
/* Recurse so this error gets set in the log file and console. The syslog
* output has been disabled so we will not get back here. */
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_ERROR, TEXT("Unable to write to the EventLog due to: %s"), getLastErrorText());
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_ERROR, TEXT("Internally setting wrapper.syslog.loglevel=NONE to prevent further messages."));
}
DeregisterEventSource( handle );
free( (void *) strings );
strings = NULL;
}
#else
void sendLoginfoMessage( int source_id, int level, const TCHAR *szBuff ) {
int eventType;
/* Build event type by level */
switch( level ) {
case LEVEL_FATAL:
eventType = LOG_CRIT;
break;
case LEVEL_ERROR:
eventType = LOG_ERR;
break;
case LEVEL_WARN:
case LEVEL_STATUS:
eventType = LOG_NOTICE;
break;
case LEVEL_INFO:
eventType = LOG_INFO;
break;
case LEVEL_DEBUG:
eventType = LOG_DEBUG;
break;
default:
eventType = LOG_DEBUG;
}
openlog( loginfoSourceName, LOG_PID | LOG_NDELAY, currentLogfacilityLevel );
_tsyslog( eventType, szBuff );
closelog( );
}
#endif
#ifdef WIN32
#define CONSOLE_BLOCK_SIZE 1024
/* The following is an initial (max) size in characters to try and write at once to the console.
* The buffer is less than 64KB, so 32K chars is a good max. The actual buffer size will be
* smaller than this so this massages the size reduction code whenever strings around this size
* are encountered. */
size_t vWriteToConsoleMaxHeapBufferSize = 32000;
size_t vWriteToConsoleBufferSize = 0;
TCHAR *vWriteToConsoleBuffer = NULL;
/**
* Write a line of output to the console.
*
* @param hdl The handle to write to. Must be a valid handle.
*
* @return TRUE if successful, FALSE if the line was not written.
*/
int writeToConsole(HANDLE hdl, TCHAR *lpszFmt, ...) {
va_list vargs;
int cnt;
size_t fullLen;
size_t remainLen;
size_t offset;
size_t thisLen;
DWORD wrote;
#ifdef DEBUG_CONSOLE_OUTPUT
_tprintf(TEXT("writeToConsole BEGIN\n"));
#endif
if (vWriteToConsoleBuffer == NULL) {
vWriteToConsoleBufferSize = CONSOLE_BLOCK_SIZE * 2;
vWriteToConsoleBuffer = malloc(sizeof(TCHAR) * vWriteToConsoleBufferSize);
if (!vWriteToConsoleBuffer) {
_tprintf(TEXT("Out of memory in logging code (%s)\n"), TEXT("WTC1"));
return FALSE;
}
#ifdef DEBUG_CONSOLE_OUTPUT
_tprintf(TEXT("Console Buffer Size = %d (Initial Size)\n"), vWriteToConsoleBufferSize);
#endif
if (logBufferGrowth) {
/* This is queued as we can't use direct logging here. */
log_printf_queue(TRUE, WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT("Console Buffer Size initially set to %d characters."), vWriteToConsoleBufferSize);
}
}
va_start(vargs, lpszFmt);
/* The only way I could figure out how to write to the console
* returned by AllocConsole when running as a service was to
* do all of this special casing and use the handle to the new
* console's stdout and the WriteConsole function. If anyone
* puzzling over this code knows a better way of doing this
* let me know.
* WriteConsole takes a fixed buffer and does not do any expansions
* We need to prepare the string to be displayed ahead of time.
* This means storing the message into a temporary buffer. The
* following loop will expand the global buffer to hold the current
* message. It will grow as needed to handle any arbitrarily large
* user message. The buffer needs to be able to hold all available
* characters + a null TCHAR.
* The _vsntprintf function will fill all available space and only
* terminate the string if there is room. Because of this we need
* to make sure and reserve room for the null terminator and add it
* if needed below. */
while ((cnt = _vsntprintf(vWriteToConsoleBuffer, vWriteToConsoleBufferSize - 1, lpszFmt, vargs)) < 0) {
#ifdef DEBUG_CONSOLE_OUTPUT
_tprintf(TEXT("writeToConsole ProcessCount=%d\n"), cnt);
#endif
/* Expand the size of the buffer */
free(vWriteToConsoleBuffer);
/* Increase the buffer by the CONSOLE_BLOCK_SIZE or an additional 10%, which ever is larger.
* The goal here is to grow the buffer size quickly, but not waste too much memory. */
vWriteToConsoleBufferSize = __max(vWriteToConsoleBufferSize + CONSOLE_BLOCK_SIZE, vWriteToConsoleBufferSize + vWriteToConsoleBufferSize / 10);
vWriteToConsoleBuffer = malloc(sizeof(TCHAR) * vWriteToConsoleBufferSize);
if (!vWriteToConsoleBuffer) {
_tprintf(TEXT("Out of memory in logging code (%s)\n"), TEXT("WTC2"));
va_end( vargs );
return FALSE;
}
#ifdef DEBUG_CONSOLE_OUTPUT
_tprintf(TEXT("Console Buffer Size = %d (Increased Size) ****************************************\n"), vWriteToConsoleBufferSize);
#endif
if (logBufferGrowth) {
/* This is queued as we can't use direct logging here. */
log_printf_queue(TRUE, WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT("Console Buffer Size increased from to %d characters."), vWriteToConsoleBufferSize);
}
}
#ifdef DEBUG_CONSOLE_OUTPUT
_tprintf(TEXT("writeToConsole ProcessCount=%d\n"), cnt);
#endif
if (cnt == (vWriteToConsoleBufferSize - 1)) {
/* The maximum number of characters were read. All of the characters fit in the available space, but because of the way the API works, the string was not null terminated. */
vWriteToConsoleBuffer[vWriteToConsoleBufferSize - 1] = '\0';
}
va_end(vargs);
#ifdef DEBUG_CONSOLE_OUTPUT
_tprintf(TEXT("writeToConsole BufferSize=%d, MessageLen=%d, Message=[%s]\n"), vWriteToConsoleBufferSize, _tcslen(vWriteToConsoleBuffer), vWriteToConsoleBuffer);
#endif
/* The WriteConsole API is a nasty little beast.
* It can accept a buffer that is up to 64KB in size, but they can't tell us exactly how much before hand.
* The size on tests on a 64-bit XP system appear to be around 25000 characters.
* The problem is that this is highly dependent on the current system state.
* Start with a large size for efficiency, but then reduce it automatically in a sticky way in 5% increments to get to a size that works. */
fullLen = _tcslen(vWriteToConsoleBuffer);
remainLen = fullLen;
offset = 0;
while (remainLen > 0) {
thisLen = __min(remainLen, vWriteToConsoleMaxHeapBufferSize);
#ifdef DEBUG_CONSOLE_OUTPUT
_tprintf(TEXT("writeToConsole write %d of %d characters\n"), thisLen, fullLen);
#endif
if (WriteConsole(hdl, &(vWriteToConsoleBuffer[offset]), (DWORD)thisLen, &wrote, NULL)) {
/* Success. */
offset += thisLen;
remainLen -= thisLen;
#ifdef DEBUG_CONSOLE_OUTPUT
if (remainLen > 0) {
/* We have not written out the whole line which means there was no line feed. Add one or the debug output will be hard to read. */
_tprintf(TEXT("\nwriteToConsole (Previous line was incomplete)\n"));
}
#endif
} else {
/* Failed. */
switch (getLastError()) {
case ERROR_NOT_ENOUGH_MEMORY:
/* This means that the max heap buffer size is too large and needs to be reduced. */
if (vWriteToConsoleMaxHeapBufferSize < 100) {
_tprintf(TEXT("Not enough available HEAP to write to console.\n"));
return FALSE;
}
vWriteToConsoleMaxHeapBufferSize = vWriteToConsoleMaxHeapBufferSize - vWriteToConsoleMaxHeapBufferSize / 20;
#ifdef DEBUG_CONSOLE_OUTPUT
_tprintf(TEXT("Usable Console HEAP Buffer Size reduced to = %d ****************************************\n"), vWriteToConsoleMaxHeapBufferSize);
#endif
if (logBufferGrowth) {
/* This is queued as we can't use direct logging here. */
log_printf_queue(TRUE, WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT("Usable Console HEAP Buffer Size decreased to %d characters."), vWriteToConsoleMaxHeapBufferSize);
}
break;
case ERROR_INVALID_FUNCTION:
case ERROR_INVALID_HANDLE:
/* This is a fairly normal thing to happen if the Wrapper is run without an actual console.
* ERROR_INVALID_FUNCTION happens when we launch a forked elevated Wrapper.
* ERROR_INVALID_HANDLE happens when the Wrapper is launched without its own console.
* Log to debug so there is a note, but it is fine if this does not show up in commands where debug output can't be enabled. */
if (currentConsoleLevel <= LEVEL_DEBUG) {
_tprintf(TEXT("A console does not exist. Disabling direct console output and falling back to using pipes.\n"));
}
consoleDirect = FALSE;
return FALSE;
default:
_tprintf(TEXT("Failed to write to console: %s\n"), getLastErrorText());
return FALSE;
}
}
}
#ifdef DEBUG_CONSOLE_OUTPUT
_tprintf(TEXT("writeToConsole END\n"));
#endif
return TRUE;
}
#endif
/**
* Does a search for all files matching the specified pattern and deletes all
* but the most recent 'count' files. The files are sorted by their names.
*/
void limitLogFileCount(const TCHAR *current, const TCHAR *pattern, int sortMode, int count) {
TCHAR **files;
int index;
int foundCurrent;
#ifdef _DEBUG
_tprintf(TEXT("limitLogFileCount(%s, %s, %d, %d)\n"), current, pattern, sortMode, count);
#endif
files = wrapperFileGetFiles(pattern, sortMode);
if (!files) {
/* Failed */
return;
}
/* When this loop runs we keep the first COUNT files in the list and everything thereafter is deleted. */
foundCurrent = FALSE;
index = 0;
while (files[index]) {
if (index < count) {
#ifdef _DEBUG
_tprintf(TEXT("Keep files[%d] %s\n"), index, files[index]);
#endif
if (_tcscmp(current, files[index]) == 0) {
/* This is the current file, as expected. */
#ifdef _DEBUG
_tprintf(TEXT(" Current\n"));
#endif
foundCurrent = TRUE;
}
} else {
#ifdef _DEBUG
_tprintf(TEXT("Delete files[%d] %s\n"), index, files[index]);
#endif
if (_tcscmp(current, files[index]) == 0) {
/* This is the current file, we don't want to delete it. */
_tprintf(TEXT("Log file sort order would result in current log file being deleted: %s\n"), current);
foundCurrent = TRUE;
} else if (_tremove(files[index])) {
_tprintf(TEXT("Unable to delete old log file: %s (%s)\n"), files[index], getLastErrorText());
}
}
index++;
}
/* Now if we did not find the current file, and there are files
still in the directory, then we want to also delete the oldest one.
Otherwise, the addition of the current file would result in too many
files. */
if (!foundCurrent) {
if (index >= count) {
#ifdef _DEBUG
_tprintf(TEXT("Delete files[%d] %s\n"), count - 1, files[count - 1]);
#endif
if (_tremove(files[count - 1])) {
_tprintf(TEXT("Unable to delete old log file: %s (%s)\n"), files[count - 1], getLastErrorText());
}
}
}
wrapperFileFreeFiles(files);
}
/**
* Sets the current uptime in seconds.
*
* @param uptime Uptime in seconds.
* @param flipped TRUE when the uptime is no longer meaningful.
*/
void setUptime(int uptime, int flipped) {
uptimeSeconds = uptime;
uptimeFlipped = flipped;
}
int rollFailure = FALSE;
/**
* Rolls log files using the ROLLNUM system.
*/
void rollLogs() {
int i;
TCHAR rollNum[11];
#if defined(WIN32) && !defined(WIN64)
struct _stat64i32 fileStat;
#else
struct stat fileStat;
#endif
int result;
#ifdef _DEBUG
_tprintf(TEXT("rollLogs()\n"));
#endif
if (!logFilePath) {
return;
}
/* If the log file is currently open, it needs to be closed. */
if (logfileFP != NULL) {
#ifdef _DEBUG
_tprintf(TEXT("Closing logfile so it can be rolled...\n"));
#endif
fclose(logfileFP);
logfileFP = NULL;
currentLogFileName[0] = TEXT('\0');
}
#ifdef _DEBUG
_tprintf(TEXT("Rolling log files... (rollFailure=%d)\n"), rollFailure);
#endif
/* We don't know how many log files need to be rotated yet, so look. */
i = 0;
do {
i++;
_sntprintf(rollNum, 11, TEXT("%d"), i);
generateLogFileName(workLogFileName, logFilePath, NULL, rollNum);
result = _tstat(workLogFileName, &fileStat);
#ifdef _DEBUG
if (result == 0) {
_tprintf(TEXT("Rolled log file %s exists.\n"), workLogFileName);
}
#endif
} while (result == 0);
/* Now, starting at the highest file rename them up by one index. */
for (; i > 1; i--) {
_tcsncpy(currentLogFileName, workLogFileName, _tcslen(logFilePath) + 11);
_sntprintf(rollNum, 11, TEXT("%d"), i - 1);
generateLogFileName(workLogFileName, logFilePath, NULL, rollNum);
if ((logFileMaxLogFiles > 0) && (i > logFileMaxLogFiles) && (!logFilePurgePattern)) {
/* The file needs to be deleted rather than rolled. If a purge pattern was not specified,
* then the files will be deleted here. Otherwise they will be deleted below. */
#ifdef _DEBUG
_tprintf(TEXT("Remove old log file %s\n"), workLogFileName);
#endif
if (_tremove(workLogFileName)) {
#ifdef _DEBUG
_tprintf(TEXT("Failed to remove old log file %s. err=%d\n"), workLogFileName, getLastError());
#endif
if (getLastError() == 2) {
/* The file did not exist. */
} else if (getLastError() == 3) {
/* The path did not exist. */
} else {
if (rollFailure == FALSE) {
log_printf_queue(TRUE, WRAPPER_SOURCE_WRAPPER, LEVEL_WARN, TEXT("Unable to delete old log file: %s (%s)"), workLogFileName, getLastErrorText());
}
rollFailure = TRUE;
generateLogFileName(currentLogFileName, logFilePath, NULL, NULL); /* Set the name back so we don't cause a logfile name changed event. */
return;
}
} else {
/* On Windows, in some cases if the file can't be deleted, we still get here without an error. Double check. */
if (_tstat(workLogFileName, &fileStat) == 0) {
/* The file still existed. */
#ifdef _DEBUG
_tprintf(TEXT("Failed to remove old log file %s\n"), workLogFileName);
#endif
if (rollFailure == FALSE) {
log_printf_queue(TRUE, WRAPPER_SOURCE_WRAPPER, LEVEL_WARN, TEXT("Unable to delete old log file: %s"), workLogFileName);
}
rollFailure = TRUE;
generateLogFileName(currentLogFileName, logFilePath, NULL, NULL); /* Set the name back so we don't cause a logfile name changed event. */
return;
}
#ifdef _DEBUG
else {
_tprintf(TEXT("Deleted %s\n"), workLogFileName);
}
#endif
}
} else {
if (_trename(workLogFileName, currentLogFileName) != 0) {
if (rollFailure == FALSE) {
#ifdef WIN32
if (errno == EACCES) {
/* This access denied message is treated as a special case, but the use by other applications issue only happens on Windows. */
/* Don't log this as with other errors as that would cause recursion. */
log_printf_queue(TRUE, WRAPPER_SOURCE_WRAPPER, LEVEL_WARN, TEXT("Unable to rename log file %s to %s. File is in use by another application."),
workLogFileName, currentLogFileName);
} else {
#endif
/* Don't log this as with other errors as that would cause recursion. */
log_printf_queue(TRUE, WRAPPER_SOURCE_WRAPPER, LEVEL_WARN, TEXT("Unable to rename log file %s to %s. (%s)"),
workLogFileName, currentLogFileName, getLastErrorText());
#ifdef WIN32
}
#endif
}
rollFailure = TRUE;
generateLogFileName(currentLogFileName, logFilePath, NULL, NULL); /* Set the name back so we don't cause a logfile name changed event. */
return;
}
#ifdef _DEBUG
else {
_tprintf(TEXT("Renamed %s to %s\n"), workLogFileName, currentLogFileName);
}
#endif
}
}
/* Rename the current file to the #1 index position */
generateLogFileName(currentLogFileName, logFilePath, NULL, NULL);
if (_trename(currentLogFileName, workLogFileName) != 0) {
if (rollFailure == FALSE) {
if (getLastError() == 2) {
/* File does not yet exist. */
} else if (getLastError() == 3) {
/* Path does not yet exist. */
} else if (errno == 13) {
/* Don't log this as with other errors as that would cause recursion. */
log_printf_queue(TRUE, WRAPPER_SOURCE_WRAPPER, LEVEL_WARN,
TEXT("Unable to rename log file %s to %s. File is in use by another application."),
currentLogFileName, workLogFileName);
} else {
/* Don't log this as with other errors as that would cause recursion. */
log_printf_queue(TRUE, WRAPPER_SOURCE_WRAPPER, LEVEL_WARN, TEXT("Unable to rename log file %s to %s. (%s)"),
currentLogFileName, workLogFileName, getLastErrorText());
}
}
rollFailure = TRUE;
generateLogFileName(currentLogFileName, logFilePath, NULL, NULL); /* Set the name back so we don't cause a logfile name changed event. */
return;
}
#ifdef _DEBUG
else {
_tprintf(TEXT("Renamed %s to %s\n"), currentLogFileName, workLogFileName);
}
#endif
/* Now limit the number of files using the standard method. */
if (logFileMaxLogFiles > 0) {
if (logFilePurgePattern) {
limitLogFileCount(currentLogFileName, logFilePurgePattern, logFilePurgeSortMode, logFileMaxLogFiles + 1);
}
}
if (rollFailure == TRUE) {
/* We made it here, but the rollFailure flag had been previously set. Make a note that we are back and then continue. */
log_printf_queue(TRUE, WRAPPER_SOURCE_WRAPPER, LEVEL_DEBUG,
TEXT("Logfile rolling is working again."));
}
rollFailure = FALSE;
/* Reset the current log file name as it is not being used yet. */
currentLogFileName[0] = TEXT('\0'); /* Log file was rolled, so we want to cause a logfile change event. */
}
/**
* Check to see whether or not the log file needs to be rolled.
* This is only called when synchronized.
*/
void checkAndRollLogs(const TCHAR *nowDate) {
long position;
#if defined(WIN32) && !defined(WIN64)
struct _stat64i32 fileStat;
#else
struct stat fileStat;
#endif
/* Depending on the roll mode, decide how to roll the log file. */
if (logFileRollMode & ROLL_MODE_SIZE) {
/* Roll based on the size of the file. */
if (logFileMaxSize <= 0) {
return;
}
/* Find out the current size of the file. If the file is currently open then we need to
* use ftell to make sure that the buffered data is also included. */
if (logfileFP != NULL) {
/* File is open */
if ((position = ftell(logfileFP)) < 0) {
_tprintf(TEXT("Unable to get the current logfile size with ftell: %s\n"), getLastErrorText());
return;
}
} else {
/* File is not open */
if (_tstat(logFilePath, &fileStat) != 0) {
if (getLastError() == 2) {
/* File does not yet exist. */
position = 0;
} else if (getLastError() == 3) {
/* Path does not exist. */
position = 0;
} else {
_tprintf(TEXT("Unable to get the current logfile size with stat: %s\n"), getLastErrorText());
return;
}
} else {
position = fileStat.st_size;
}
}
/* Does the log file need to rotated? */
if (position >= logFileMaxSize) {
rollLogs();
}
} else if (logFileRollMode & ROLL_MODE_DATE) {
/* Roll based on the date of the log entry. */
if (_tcscmp(nowDate, logFileLastNowDate) != 0) {
/* The date has changed. Close the file. */
if (logfileFP != NULL) {
#ifdef _DEBUG
_tprintf(TEXT("Closing logfile because the date changed...\n"));
#endif
fclose(logfileFP);
logfileFP = NULL;
}
/* Always reset the name so the the log file name will be regenerated correctly. */
currentLogFileName[0] = TEXT('\0');
/* This will happen just before a new log file is created.
* Check the maximum file count. */
if (logFileMaxLogFiles > 0) {
/* We will check for too many files here and then clear the current log file name so it will be set later. */
generateLogFileName(currentLogFileName, logFilePath, nowDate, NULL);
if (logFilePurgePattern) {
limitLogFileCount(currentLogFileName, logFilePurgePattern, logFilePurgeSortMode, logFileMaxLogFiles + 1);
} else {
generateLogFileName(workLogFileName, logFilePath, TEXT("????????"), NULL);
limitLogFileCount(currentLogFileName, workLogFileName, WRAPPER_FILE_SORT_MODE_NAMES_DEC, logFileMaxLogFiles + 1);
}
currentLogFileName[0] = TEXT('\0');
workLogFileName[0] = TEXT('\0');
}
}
}
}
void log_printf_queue( int useQueue, int source_id, int level, const TCHAR *lpszFmt, ... ) {
int threadId;
int localWriteIndex;
int localReadIndex;
va_list vargs;
int count;
#if defined(UNICODE) && !defined(WIN32)
TCHAR *format;
size_t i;
size_t len;
#endif
TCHAR *buffer;
/* Start by processing any arguments so that we can store a simple string. */
#ifdef _DEBUG_QUEUE
_tprintf(TEXT("log_printf_queue(%d, %d, %d, %S)\n"), useQueue, source_id, level, lpszFmt);
#endif
#if defined(UNICODE) && !defined(WIN32)
if (wcsstr(lpszFmt, TEXT("%s")) != NULL) {
/* On UNIX platforms string tokens must always use "%S" variables and not "%s". We can
* not safely use malloc here as the call may have originated from a signal handler.
* Copy the template into the formatMessages string reserved for this thread, replace
* the tokens and then continue using that. This is a bit of overhead, but these async
* messages are fairly rare and this greatly simplifies the code throughout the rest of
* the application by making it possible to always use the "%s" syntax. */
threadId = getThreadId();
_tcsncpy(formatMessages[threadId], lpszFmt, QUEUED_BUFFER_SIZE);
/* Terminate just in case the format was too long. */
formatMessages[threadId][QUEUED_BUFFER_SIZE - 1] = TEXT('\0');
format = formatMessages[threadId];
/* Replace the tokens. */
#ifdef _DEBUG_QUEUE
_tprintf(TEXT("Replacing string tokens.\n"));
_tprintf(TEXT(" From: %S\n"), format);
#endif
len = wcslen(format);
if (len > 0) {
for (i = 0; i < len; i++) {
if ((i > 0) && (format[i - 1] == TEXT('%')) && (format[i] == TEXT('s'))) {
/* Make sure the '%' was not escaped. */
if ((i > 1) && (format[i - 2] == TEXT('%'))) {
/* Escaped. Do nothing. */
} else {
/* 's' needs to be changed to 'S' */
format[i] = TEXT('S');
}
}
}
}
#ifdef _DEBUG_QUEUE
_tprintf(TEXT(" To: %S\n"), format);
#endif
lpszFmt = format;
}
#endif
/** For queued logging, we have a fixed length buffer to work with. Just to make it easy to catch
* problems, always use the same sized fixed buffer even if we will be using the non-queued logging. */
if (useQueue) {
/* Care needs to be taken both with this code and the code below to get done as quick as possible.
* It is generally safe because each thread has its own queue. The only danger is if a message is
* being queued while that thread is interupted by a signal. If things are setup correctly however
* then non-signal threads should not be here in the first place. */
threadId = getThreadId();
localWriteIndex = queueWriteIndex[threadId];
localReadIndex = queueReadIndex[threadId];
if ((localWriteIndex == localReadIndex - 1) || ((localWriteIndex == QUEUE_SIZE - 1) && (localReadIndex == 0))) {
_tprintf(TEXT("WARNING log queue overflow for thread[%d]:%d:%d dropping entry: %s\n"), threadId, localWriteIndex, localReadIndex, lpszFmt);
return;
}
/* Get a reference to the message buffer we will use. */
buffer = queueMessages[threadId][queueWriteIndex[threadId]];
} else {
/* This will not be queued so we can use malloc to create a new buffer. */
buffer = malloc(sizeof(TCHAR) * QUEUED_BUFFER_SIZE);
if (!buffer) {
_tprintf(TEXT("Out of memory in logging code (%s)\n"), TEXT("PQ1"));
return;
}
/* For compiler */
threadId = -1;
localWriteIndex = -1;
}
/* Now actually generate our buffer. */
va_start(vargs, lpszFmt);
count = _vsntprintf(buffer, QUEUED_BUFFER_SIZE_USABLE, lpszFmt, vargs);
va_end(vargs);
/* vswprintf returns -1 on overflow. */
if ((count < 0) || (count >= QUEUED_BUFFER_SIZE_USABLE - 1)) {
/* The expanded message was too big to fit into the buffer.
* On Windows, it writes as much as it can so we can make it look pretty.
* But on other platforms, nothing is written so we need a message.
* It is illegal to do any mallocs in here, so there is notheing we can really do on UNIX. */
#if defined(WIN32)
/* To be safe, make sure we are null terminated. */
buffer[QUEUED_BUFFER_SIZE_USABLE - 1] = 0;
_tcsncat(buffer, TEXT("..."), QUEUED_BUFFER_SIZE);
#else
/* Write an error string that we know will fit. This doesn't need to be localized as it should be caught in testing. */
_sntprintf(buffer, QUEUED_BUFFER_SIZE, TEXT("(Message too long to be logged as a queued message. Please report this.)"));
#endif
}
if (useQueue) {
#ifdef _DEBUG_QUEUE
_tprintf(TEXT("LOG ENQUEUE[%d] Thread[%d]: %s\n"), localWriteIndex, threadId, buffer);
#endif
/* Store additional information about the call. */
queueSourceIds[threadId][localWriteIndex] = source_id;
queueLevels[threadId][localWriteIndex] = level;
/* Lastly increment and wrap the write index. */
queueWriteIndex[threadId]++;
if (queueWriteIndex[threadId] >= QUEUE_SIZE) {
queueWriteIndex[threadId] = 0;
queueWrapped[threadId] = 1;
}
} else {
/* Make a normal logging call with our new buffer. Parameters are already expanded. */
log_printf(source_id, level,
#if defined(UNICODE) && !defined(WIN32)
TEXT("%S"),
#else
TEXT("%s"),
#endif
buffer);
free(buffer);
}
}
/**
* Perform any required logger maintenance at regular intervals.
*
* One operation is to log any queued messages. This must be done very
* carefully as it is possible that a signal handler could be thrown at
* any time as this function is being executed.
*/
void maintainLogger() {
int localWriteIndex;
int source_id;
int level;
int threadId;
TCHAR *buffer;
int logFileChanged;
TCHAR *logFileCopy;
/* Check to see if there is a pending log file change notification. Do this first as we could
* generate our own here as well. It is important that we do our best to keep them in order.
* Grab it and clear the reference quick in case another is set. This order is thread safe. */
if (pendingLogFileChange) {
/* Lock the logging mutex. */
if (lockLoggingMutex()) {
return;
}
logFileCopy = pendingLogFileChange;
pendingLogFileChange = NULL;
/* Release the lock we have on the logging mutex so that other threads can get in. */
if (releaseLoggingMutex()) {
return;
}
/* Now see if a log file name was queued, using our local copy. */
if (logFileCopy) {
#ifdef _DEBUG
_tprintf(TEXT("Sending notification of queued log file name change: %s"), logFileCopy);
#endif
logFileChangedCallback(logFileCopy);
free(logFileCopy);
logFileCopy = NULL;
}
}
for (threadId = 0; threadId < WRAPPER_THREAD_COUNT; threadId++) {
/* NOTE - The queue variables are not synchronized so we need to access them
* carefully and assume that data could possibly be corrupted. */
localWriteIndex = queueWriteIndex[threadId]; /* Snapshot the value to maintain a constant reference. */
if ( queueReadIndex[threadId] != localWriteIndex ) {
logFileChanged = FALSE;
logFileCopy = NULL;
/* Lock the logging mutex. */
if (lockLoggingMutex()) {
return;
}
/* Empty the queue of any logged messages. */
localWriteIndex = queueWriteIndex[threadId]; /* Snapshot the value to maintain a constant reference. */
while (queueReadIndex[threadId] != localWriteIndex) {
/* Snapshot the values in the queue at that index. */
source_id = queueSourceIds[threadId][queueReadIndex[threadId]];
level = queueLevels[threadId][queueReadIndex[threadId]];
buffer = queueMessages[threadId][queueReadIndex[threadId]];
/* The buffer is static in the queue and will be reused. */
#ifdef _DEBUG_QUEUE
_tprintf(TEXT("LOG QUEUED[%d]: %s\n"), queueReadIndex[threadId], buffer );
#endif
logFileChanged = log_printf_message(source_id, level, threadId, TRUE, buffer, TRUE);
if (logFileChanged) {
logFileCopy = malloc(sizeof(TCHAR) * (_tcslen(currentLogFileName) + 1));
if (!logFileCopy) {
_tprintf(TEXT("Out of memory in logging code (%s)\n"), TEXT("ML1"));
} else {
_tcsncpy(logFileCopy, currentLogFileName, _tcslen(currentLogFileName) + 1);
}
}
#ifdef _DEBUG_QUEUE
_tprintf(TEXT(" Queue lw=%d, qw=%d, qr=%d\n"), localWriteIndex, queueWriteIndex[threadId], queueReadIndex[threadId]);
#endif
/* Clear the string we just wrote. */
buffer[0] = TEXT('\0');
queueReadIndex[threadId]++;
if ( queueReadIndex[threadId] >= QUEUE_SIZE ) {
queueReadIndex[threadId] = 0;
}
}
/* Release the lock we have on the logging mutex so that other threads can get in. */
if (releaseLoggingMutex()) {
if (logFileChanged && logFileCopy) {
free(logFileCopy);
}
return;
}
/* Now that we are no longer in the semaphore, register the change of the logfile. */
if (logFileChanged && logFileCopy) {
logFileChangedCallback(logFileCopy);
free(logFileCopy);
}
}
}
}
wrapper_3.5.22_src/src/c/logger.h 100644 0 0 25515 12224722016 14032 0 ustar 0 0 /*
* Copyright (c) 1999, 2013 Tanuki Software, Ltd.
* http://www.tanukisoftware.com
* All rights reserved.
*
* This software is the proprietary information of Tanuki Software.
* You shall use it only in accordance with the terms of the
* license agreement you entered into with Tanuki Software.
* http://wrapper.tanukisoftware.com/doc/english/licenseOverview.html
*
*
* Portions of the Software have been derived from source code
* developed by Silver Egg Technology under the following license:
*
* Copyright (c) 2001 Silver Egg Technology
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sub-license, and/or
* sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*/
/**
* Author:
* Johan Sorlin
* Leif Mortenson
*/
#ifndef _LOGGER_H
#define _LOGGER_H
/* If defined, output debug information about console output. */
/*#define DEBUG_CONSOLE_OUTPUT*/
#ifdef MACOSX
#ifndef wcscasecmp
extern inline int wcscasecmp(const wchar_t* s1, const wchar_t* s2);
#define MACOSX_ECSCASECMP
#endif
#endif
#ifdef _DEBUG
#define _DEBUG_QUEUE
#endif
#ifdef WIN32
#include
#define LOG_USER (1<<3)
#endif
#include "wrapper_i18n.h"
#ifndef DWORD
#define DWORD unsigned long
#endif
/* * * Log source constants * * */
#define WRAPPER_SOURCE_WRAPPER -1
#define WRAPPER_SOURCE_PROTOCOL -2
/* * * Log thread constants * * */
/* These are indexes in an array so they must be sequential, start
* with zero and be one less than the final WRAPPER_THREAD_COUNT */
#define WRAPPER_THREAD_CURRENT -1
#define WRAPPER_THREAD_SIGNAL 0
#define WRAPPER_THREAD_MAIN 1
#define WRAPPER_THREAD_SRVMAIN 2
#define WRAPPER_THREAD_TIMER 3
#define WRAPPER_THREAD_JAVAIO 4
#define WRAPPER_THREAD_STARTUP 5
#define WRAPPER_THREAD_COUNT 6
#define MAX_LOG_SIZE 4096
#ifdef WIN32
#else
/* A special prefix on log messages that can be bassed through from a forked process
so the parent will handle the log message correctly. */
#define LOG_FORK_MARKER TEXT("#!#WrApPeR#!#")
#define LOG_SPECIAL_MARKER TEXT("#!#WrApPeRsPeCiAl#!#")
#endif
/* Default log formats */
#define LOG_FORMAT_LOGFILE_DEFAULT TEXT("LPTM")
#define LOG_FORMAT_CONSOLE_DEFAULT TEXT("PM")
/* * * Log level constants * * */
/* No logging at all. */
#define LEVEL_NONE 9
/* Notice messages which should always be displayed. These never go to the syslog. */
#define LEVEL_NOTICE 8
/* Advisor messages which should always be displayed. These never go to the syslog. */
#define LEVEL_ADVICE 7
/* Too many restarts, unable to start etc. Case when the Wrapper is forced to exit. */
#define LEVEL_FATAL 6
/* JVM died, hung messages */
#define LEVEL_ERROR 5
/* Warning messages. */
#define LEVEL_WARN 4
/* Started, Stopped, Restarted messages. */
#define LEVEL_STATUS 3
/* Copyright message. and logged console output. */
#define LEVEL_INFO 2
/* Current debug messages */
#define LEVEL_DEBUG 1
/* Unknown level */
#define LEVEL_UNKNOWN 0
/* * * Log file roll mode constants * * */
#define ROLL_MODE_UNKNOWN 0
#define ROLL_MODE_NONE 1
#define ROLL_MODE_SIZE 2
#define ROLL_MODE_WRAPPER 4
#define ROLL_MODE_JVM 8
#define ROLL_MODE_SIZE_OR_WRAPPER ROLL_MODE_SIZE + ROLL_MODE_WRAPPER
#define ROLL_MODE_SIZE_OR_JVM ROLL_MODE_SIZE + ROLL_MODE_JVM
#define ROLL_MODE_DATE 16
#define ROLL_MODE_DATE_TOKEN TEXT("YYYYMMDD")
/* * * Function predeclaration * * */
#define strcmpIgnoreCase(str1, str2) _tcsicmp(str1, str2)
/* This can be called from within logging code that would otherwise get stuck in recursion.
* Log to the console exactly when it happens and then also try to get it into the log
* file at the next oportunity. */
extern void outOfMemoryQueued(const TCHAR *context, int id);
extern void outOfMemory(const TCHAR *context, int id);
#ifdef _DEBUG
/**
* Used to dump memory directly to the log file in both HEX and readable format.
* Useful in debugging applications to track down memory overflows etc.
*
* @param label A label that will be prepended on all lines of output.
* @param memory The memory to be dumped.
* @param len The length of the memory to be dumped.
*/
extern void log_dumpHex(TCHAR *label, TCHAR *memory, size_t len);
#endif
/**
* Sets the number of milliseconds to allow logging to take before a warning is logged.
* Defaults to 0 for no limit. Possible values 0 to 3600000.
*
* @param threshold Warning threashold.
*/
extern void setLogWarningThreshold(int threshold);
/**
* Sets the log levels to a silence so we never output anything.
*/
extern void setSilentLogLevels();
/**
* Sets the console log levels to a simple format for help and usage messages.
*/
extern void setSimpleLogLevels();
#ifdef WIN32
/**
* This sets a flag which tells the logger that alternate source labels should be used to indicate that the current process is a launcher.
*/
extern void setLauncherSource();
#endif
/**
* Used for testing to set a pause into the next log entry made.
*
* @param pauseTime Number of seconds to pause, 0 pauses indefinitely.
*/
extern void setPauseTime(int pauseTime);
/**
* Set to true to cause changes in internal buffer sizes to be logged. Useful for debugging.
*
* @param log TRUE if changes should be logged.
*/
void setLogBufferGrowth(int log);
/* * Logfile functions * */
extern int isLogfileAccessed();
/**
* Sets the log file to be used. If the specified file is not absolute then
* it will be resolved into an absolute path. If there are any problems with
* the path, like a directory not existing then the call will fail and the
* cause will be written to the existing log.
*
* @param log_file_path Log file to start using.
* @param workingDir The current working directory, used for relative paths.
* This will be NULL if this is part of the bootstrap process,
* in which case we should not attempt to resolve the absolute
* path.
* @param preload TRUE if called as part of the preload process. We use this to
* suppress double warnings.
*
* @return TRUE if there were any problems.
*/
extern int setLogfilePath( const TCHAR *log_file_path, const TCHAR *workingDir, int preload);
/**
* Returns the default logfile.
*/
extern const TCHAR *getDefaultLogfilePath();
/**
* Returns a reference to the currect log file path.
* This return value may be changed at any time if the log file is rolled.
*/
extern const TCHAR *getLogfilePath();
/**
* Returns a snapshot of the current log file path. This call safely gets the current path
* and returns a copy. It is the responsibility of the caller to free up the memory on
* return. Could return null if there was an error.
*/
extern TCHAR *getCurrentLogfilePath();
/**
* Check the directory of the current logfile path to make sure it is writable.
* If there are any problems, log a warning.
*
* @return TRUE if there were any problems.
*/
extern int checkLogfileDir();
extern int getLogfileRollModeForName( const TCHAR *logfileRollName );
extern void setLogfileRollMode(int log_file_roll_mode);
extern int getLogfileRollMode();
extern void setLogfileUmask(int log_file_umask);
extern void setLogfileFormat( const TCHAR *log_file_format );
extern void setLogfileLevelInt(int log_file_level);
extern int getLogfileLevelInt();
extern void setLogfileLevel( const TCHAR *log_file_level );
extern void setLogfileMaxFileSize( const TCHAR *max_file_size );
extern void setLogfileMaxFileSizeInt(int max_file_size);
extern void setLogfileMaxLogFiles(int max_log_files);
extern void setLogfilePurgePattern(const TCHAR *pattern);
extern void setLogfilePurgeSortMode(int sortMode);
extern DWORD getLogfileActivity();
/** Sets the auto flush log file flag. */
extern void setLogfileAutoFlush(int autoFlush);
/** Sets the auto close log file flag. */
extern void setLogfileAutoClose(int autoClose);
/** Closes the logfile if it is open. */
extern void closeLogfile();
/** Flushes any buffered logfile output to the disk. */
extern void flushLogfile();
/* * Console functions * */
extern void setConsoleLogFormat( const TCHAR *console_log_format );
extern void setConsoleLogLevelInt(int console_log_level);
extern int getConsoleLogLevelInt();
extern void setConsoleLogLevel( const TCHAR *console_log_level );
extern void setConsoleFlush(int flush);
#ifdef WIN32
extern void setConsoleDirect(int direct);
#endif
extern void setConsoleFatalToStdErr(int toStdErr);
extern void setConsoleErrorToStdErr(int toStdErr);
extern void setConsoleWarnToStdErr(int toStdErr);
/* * Syslog/eventlog functions * */
extern void setSyslogLevelInt(int loginfo_level);
extern int getSyslogLevelInt();
extern void setSyslogLevel( const TCHAR *loginfo_level );
#ifndef WIN32
extern void setSyslogFacility( const TCHAR *loginfo_level );
#endif
extern void setSyslogEventSourceName( const TCHAR *event_source_name );
extern int registerSyslogMessageFile();
extern int unregisterSyslogMessageFile();
extern void resetDuration();
extern int getLowLogLevel();
/* * General log functions * */
extern int initLogging(void (*logFileChanged)(const TCHAR *logFile));
extern int disposeLogging();
extern void setUptime(int uptime, int flipped);
extern void rollLogs();
extern int getLogLevelForName( const TCHAR *logLevelName );
#ifndef WIN32
extern int getLogFacilityForName( const TCHAR *logFacilityName );
#endif
extern void logRegisterThread(int thread_id);
/**
* The log_printf function logs a message to the configured log targets.
*
* This method can be used safely in most cases. See the log_printf_queue
* funtion for the exceptions.
*/
extern void log_printf( int source_id, int level, const TCHAR *lpszFmt, ... );
/**
* The log_printf_queue function is less efficient than the log_printf
* function and will cause logged messages to be logged out of order from
* those logged with log_printf because the messages are queued and then
* logged from another thread.
*
* Use of this function is required in cases where the thread may possibly
* be a signal callback. In these cases, it is possible for the original
* thread to have been suspended within a log_printf call. If the signal
* thread then attempted to call log_printf, it would result in a deadlock.
*/
extern void log_printf_queue( int useQueue, int source_id, int level, const TCHAR *lpszFmt, ... );
extern TCHAR* getLastErrorText();
extern int getLastError();
extern void maintainLogger();
extern void invalidMultiByteSequence(const TCHAR *context, int id);
#endif
wrapper_3.5.22_src/src/c/messages.h 100644 0 0 4732 12224722016 14340 0 ustar 0 0 //
// Values are 32 bit values layed out as follows:
//
// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
// +---+-+-+-----------------------+-------------------------------+
// |Sev|C|R| Facility | Code |
// +---+-+-+-----------------------+-------------------------------+
//
// where
//
// Sev - is the severity code
//
// 00 - Success
// 01 - Informational
// 10 - Warning
// 11 - Error
//
// C - is the Customer code flag
//
// R - is a reserved bit
//
// Facility - is the facility code
//
// Code - is the facility's status code
//
//
// Define the facility codes
//
//
// Define the severity codes
//
//
// MessageId: MSG_EVENT_LOG_MESSAGE
//
// MessageText:
//
// %2
//
#define MSG_EVENT_LOG_MESSAGE 0x00000064L
//
// MessageId: MSG_EVENT_LOG_CATEGORY_JVM1
//
// MessageText:
//
// jvm1
//
#define MSG_EVENT_LOG_CATEGORY_JVM1 0x00000001L
//
// MessageId: MSG_EVENT_LOG_CATEGORY_JVM2
//
// MessageText:
//
// jvm2
//
#define MSG_EVENT_LOG_CATEGORY_JVM2 0x00000002L
//
// MessageId: MSG_EVENT_LOG_CATEGORY_JVM3
//
// MessageText:
//
// jvm3
//
#define MSG_EVENT_LOG_CATEGORY_JVM3 0x00000003L
//
// MessageId: MSG_EVENT_LOG_CATEGORY_JVM4
//
// MessageText:
//
// jvm4
//
#define MSG_EVENT_LOG_CATEGORY_JVM4 0x00000004L
//
// MessageId: MSG_EVENT_LOG_CATEGORY_JVM5
//
// MessageText:
//
// jvm5
//
#define MSG_EVENT_LOG_CATEGORY_JVM5 0x00000005L
//
// MessageId: MSG_EVENT_LOG_CATEGORY_JVM6
//
// MessageText:
//
// jvm6
//
#define MSG_EVENT_LOG_CATEGORY_JVM6 0x00000006L
//
// MessageId: MSG_EVENT_LOG_CATEGORY_JVM7
//
// MessageText:
//
// jvm7
//
#define MSG_EVENT_LOG_CATEGORY_JVM7 0x00000007L
//
// MessageId: MSG_EVENT_LOG_CATEGORY_JVM8
//
// MessageText:
//
// jvm8
//
#define MSG_EVENT_LOG_CATEGORY_JVM8 0x00000008L
//
// MessageId: MSG_EVENT_LOG_CATEGORY_JVM9
//
// MessageText:
//
// jvm9
//
#define MSG_EVENT_LOG_CATEGORY_JVM9 0x00000009L
//
// MessageId: MSG_EVENT_LOG_CATEGORY_JVMXX
//
// MessageText:
//
// jvmxx
//
#define MSG_EVENT_LOG_CATEGORY_JVMXX 0x0000000AL
//
// MessageId: MSG_EVENT_LOG_CATEGORY_WRAPPER
//
// MessageText:
//
// wrapper
//
#define MSG_EVENT_LOG_CATEGORY_WRAPPER 0x0000000BL
//
// MessageId: MSG_EVENT_LOG_CATEGORY_PROTOCOL
//
// MessageText:
//
// wrapperp
//
#define MSG_EVENT_LOG_CATEGORY_PROTOCOL 0x0000000CL
wrapper_3.5.22_src/src/c/org_tanukisoftware_wrapper_WrapperManager.h 100644 0 0 43760 12224722016 23225 0 ustar 0 0 /* DO NOT EDIT THIS FILE - it is machine generated */
#include
/* Header for class org_tanukisoftware_wrapper_WrapperManager */
#ifndef _Included_org_tanukisoftware_wrapper_WrapperManager
#define _Included_org_tanukisoftware_wrapper_WrapperManager
#ifdef __cplusplus
extern "C" {
#endif
#undef org_tanukisoftware_wrapper_WrapperManager_DEFAULT_PORT
#define org_tanukisoftware_wrapper_WrapperManager_DEFAULT_PORT 15003L
#undef org_tanukisoftware_wrapper_WrapperManager_DEFAULT_CPU_TIMEOUT
#define org_tanukisoftware_wrapper_WrapperManager_DEFAULT_CPU_TIMEOUT 10000L
#undef org_tanukisoftware_wrapper_WrapperManager_TICK_MS
#define org_tanukisoftware_wrapper_WrapperManager_TICK_MS 100L
#undef org_tanukisoftware_wrapper_WrapperManager_TIMER_FAST_THRESHOLD
#define org_tanukisoftware_wrapper_WrapperManager_TIMER_FAST_THRESHOLD 1728000L
#undef org_tanukisoftware_wrapper_WrapperManager_TIMER_SLOW_THRESHOLD
#define org_tanukisoftware_wrapper_WrapperManager_TIMER_SLOW_THRESHOLD 1728000L
#undef org_tanukisoftware_wrapper_WrapperManager_BACKEND_TYPE_UNKNOWN
#define org_tanukisoftware_wrapper_WrapperManager_BACKEND_TYPE_UNKNOWN 0L
#undef org_tanukisoftware_wrapper_WrapperManager_BACKEND_TYPE_SOCKET
#define org_tanukisoftware_wrapper_WrapperManager_BACKEND_TYPE_SOCKET 1L
#undef org_tanukisoftware_wrapper_WrapperManager_BACKEND_TYPE_PIPE
#define org_tanukisoftware_wrapper_WrapperManager_BACKEND_TYPE_PIPE 2L
#undef org_tanukisoftware_wrapper_WrapperManager_WRAPPER_MSG_START
#define org_tanukisoftware_wrapper_WrapperManager_WRAPPER_MSG_START 100L
#undef org_tanukisoftware_wrapper_WrapperManager_WRAPPER_MSG_STOP
#define org_tanukisoftware_wrapper_WrapperManager_WRAPPER_MSG_STOP 101L
#undef org_tanukisoftware_wrapper_WrapperManager_WRAPPER_MSG_RESTART
#define org_tanukisoftware_wrapper_WrapperManager_WRAPPER_MSG_RESTART 102L
#undef org_tanukisoftware_wrapper_WrapperManager_WRAPPER_MSG_PING
#define org_tanukisoftware_wrapper_WrapperManager_WRAPPER_MSG_PING 103L
#undef org_tanukisoftware_wrapper_WrapperManager_WRAPPER_MSG_STOP_PENDING
#define org_tanukisoftware_wrapper_WrapperManager_WRAPPER_MSG_STOP_PENDING 104L
#undef org_tanukisoftware_wrapper_WrapperManager_WRAPPER_MSG_START_PENDING
#define org_tanukisoftware_wrapper_WrapperManager_WRAPPER_MSG_START_PENDING 105L
#undef org_tanukisoftware_wrapper_WrapperManager_WRAPPER_MSG_STARTED
#define org_tanukisoftware_wrapper_WrapperManager_WRAPPER_MSG_STARTED 106L
#undef org_tanukisoftware_wrapper_WrapperManager_WRAPPER_MSG_STOPPED
#define org_tanukisoftware_wrapper_WrapperManager_WRAPPER_MSG_STOPPED 107L
#undef org_tanukisoftware_wrapper_WrapperManager_WRAPPER_MSG_KEY
#define org_tanukisoftware_wrapper_WrapperManager_WRAPPER_MSG_KEY 110L
#undef org_tanukisoftware_wrapper_WrapperManager_WRAPPER_MSG_BADKEY
#define org_tanukisoftware_wrapper_WrapperManager_WRAPPER_MSG_BADKEY 111L
#undef org_tanukisoftware_wrapper_WrapperManager_WRAPPER_MSG_LOW_LOG_LEVEL
#define org_tanukisoftware_wrapper_WrapperManager_WRAPPER_MSG_LOW_LOG_LEVEL 112L
#undef org_tanukisoftware_wrapper_WrapperManager_WRAPPER_MSG_PING_TIMEOUT
#define org_tanukisoftware_wrapper_WrapperManager_WRAPPER_MSG_PING_TIMEOUT 113L
#undef org_tanukisoftware_wrapper_WrapperManager_WRAPPER_MSG_SERVICE_CONTROL_CODE
#define org_tanukisoftware_wrapper_WrapperManager_WRAPPER_MSG_SERVICE_CONTROL_CODE 114L
#undef org_tanukisoftware_wrapper_WrapperManager_WRAPPER_MSG_PROPERTIES
#define org_tanukisoftware_wrapper_WrapperManager_WRAPPER_MSG_PROPERTIES 115L
#undef org_tanukisoftware_wrapper_WrapperManager_WRAPPER_MSG_LOG
#define org_tanukisoftware_wrapper_WrapperManager_WRAPPER_MSG_LOG 116L
#undef org_tanukisoftware_wrapper_WrapperManager_WRAPPER_MSG_CHILD_LAUNCH
#define org_tanukisoftware_wrapper_WrapperManager_WRAPPER_MSG_CHILD_LAUNCH -124L
#undef org_tanukisoftware_wrapper_WrapperManager_WRAPPER_MSG_CHILD_TERM
#define org_tanukisoftware_wrapper_WrapperManager_WRAPPER_MSG_CHILD_TERM -123L
#undef org_tanukisoftware_wrapper_WrapperManager_WRAPPER_MSG_LOGFILE
#define org_tanukisoftware_wrapper_WrapperManager_WRAPPER_MSG_LOGFILE -122L
#undef org_tanukisoftware_wrapper_WrapperManager_WRAPPER_MSG_CHECK_DEADLOCK
#define org_tanukisoftware_wrapper_WrapperManager_WRAPPER_MSG_CHECK_DEADLOCK -121L
#undef org_tanukisoftware_wrapper_WrapperManager_WRAPPER_MSG_DEADLOCK
#define org_tanukisoftware_wrapper_WrapperManager_WRAPPER_MSG_DEADLOCK -120L
#undef org_tanukisoftware_wrapper_WrapperManager_WRAPPER_MSG_APPEAR_ORPHAN
#define org_tanukisoftware_wrapper_WrapperManager_WRAPPER_MSG_APPEAR_ORPHAN -119L
#undef org_tanukisoftware_wrapper_WrapperManager_WRAPPER_MSG_PAUSE
#define org_tanukisoftware_wrapper_WrapperManager_WRAPPER_MSG_PAUSE -118L
#undef org_tanukisoftware_wrapper_WrapperManager_WRAPPER_MSG_RESUME
#define org_tanukisoftware_wrapper_WrapperManager_WRAPPER_MSG_RESUME -117L
#undef org_tanukisoftware_wrapper_WrapperManager_WRAPPER_MSG_GC
#define org_tanukisoftware_wrapper_WrapperManager_WRAPPER_MSG_GC -116L
#undef org_tanukisoftware_wrapper_WrapperManager_WRAPPER_MSG_FIRE_USER_EVENT
#define org_tanukisoftware_wrapper_WrapperManager_WRAPPER_MSG_FIRE_USER_EVENT -115L
#undef org_tanukisoftware_wrapper_WrapperManager_WRAPPER_CTRL_C_EVENT
#define org_tanukisoftware_wrapper_WrapperManager_WRAPPER_CTRL_C_EVENT 200L
#undef org_tanukisoftware_wrapper_WrapperManager_WRAPPER_CTRL_CLOSE_EVENT
#define org_tanukisoftware_wrapper_WrapperManager_WRAPPER_CTRL_CLOSE_EVENT 201L
#undef org_tanukisoftware_wrapper_WrapperManager_WRAPPER_CTRL_LOGOFF_EVENT
#define org_tanukisoftware_wrapper_WrapperManager_WRAPPER_CTRL_LOGOFF_EVENT 202L
#undef org_tanukisoftware_wrapper_WrapperManager_WRAPPER_CTRL_SHUTDOWN_EVENT
#define org_tanukisoftware_wrapper_WrapperManager_WRAPPER_CTRL_SHUTDOWN_EVENT 203L
#undef org_tanukisoftware_wrapper_WrapperManager_WRAPPER_CTRL_TERM_EVENT
#define org_tanukisoftware_wrapper_WrapperManager_WRAPPER_CTRL_TERM_EVENT 204L
#undef org_tanukisoftware_wrapper_WrapperManager_WRAPPER_CTRL_HUP_EVENT
#define org_tanukisoftware_wrapper_WrapperManager_WRAPPER_CTRL_HUP_EVENT 205L
#undef org_tanukisoftware_wrapper_WrapperManager_WRAPPER_CTRL_USR1_EVENT
#define org_tanukisoftware_wrapper_WrapperManager_WRAPPER_CTRL_USR1_EVENT 206L
#undef org_tanukisoftware_wrapper_WrapperManager_WRAPPER_CTRL_USR2_EVENT
#define org_tanukisoftware_wrapper_WrapperManager_WRAPPER_CTRL_USR2_EVENT 207L
#undef org_tanukisoftware_wrapper_WrapperManager_WRAPPER_LOG_LEVEL_DEBUG
#define org_tanukisoftware_wrapper_WrapperManager_WRAPPER_LOG_LEVEL_DEBUG 1L
#undef org_tanukisoftware_wrapper_WrapperManager_WRAPPER_LOG_LEVEL_INFO
#define org_tanukisoftware_wrapper_WrapperManager_WRAPPER_LOG_LEVEL_INFO 2L
#undef org_tanukisoftware_wrapper_WrapperManager_WRAPPER_LOG_LEVEL_STATUS
#define org_tanukisoftware_wrapper_WrapperManager_WRAPPER_LOG_LEVEL_STATUS 3L
#undef org_tanukisoftware_wrapper_WrapperManager_WRAPPER_LOG_LEVEL_WARN
#define org_tanukisoftware_wrapper_WrapperManager_WRAPPER_LOG_LEVEL_WARN 4L
#undef org_tanukisoftware_wrapper_WrapperManager_WRAPPER_LOG_LEVEL_ERROR
#define org_tanukisoftware_wrapper_WrapperManager_WRAPPER_LOG_LEVEL_ERROR 5L
#undef org_tanukisoftware_wrapper_WrapperManager_WRAPPER_LOG_LEVEL_FATAL
#define org_tanukisoftware_wrapper_WrapperManager_WRAPPER_LOG_LEVEL_FATAL 6L
#undef org_tanukisoftware_wrapper_WrapperManager_WRAPPER_LOG_LEVEL_ADVICE
#define org_tanukisoftware_wrapper_WrapperManager_WRAPPER_LOG_LEVEL_ADVICE 7L
#undef org_tanukisoftware_wrapper_WrapperManager_WRAPPER_LOG_LEVEL_NOTICE
#define org_tanukisoftware_wrapper_WrapperManager_WRAPPER_LOG_LEVEL_NOTICE 8L
#undef org_tanukisoftware_wrapper_WrapperManager_SERVICE_CONTROL_CODE_START
#define org_tanukisoftware_wrapper_WrapperManager_SERVICE_CONTROL_CODE_START 65536L
#undef org_tanukisoftware_wrapper_WrapperManager_SERVICE_CONTROL_CODE_STOP
#define org_tanukisoftware_wrapper_WrapperManager_SERVICE_CONTROL_CODE_STOP 1L
#undef org_tanukisoftware_wrapper_WrapperManager_SERVICE_CONTROL_CODE_PAUSE
#define org_tanukisoftware_wrapper_WrapperManager_SERVICE_CONTROL_CODE_PAUSE 2L
#undef org_tanukisoftware_wrapper_WrapperManager_SERVICE_CONTROL_CODE_CONTINUE
#define org_tanukisoftware_wrapper_WrapperManager_SERVICE_CONTROL_CODE_CONTINUE 3L
#undef org_tanukisoftware_wrapper_WrapperManager_SERVICE_CONTROL_CODE_INTERROGATE
#define org_tanukisoftware_wrapper_WrapperManager_SERVICE_CONTROL_CODE_INTERROGATE 4L
#undef org_tanukisoftware_wrapper_WrapperManager_SERVICE_CONTROL_CODE_SHUTDOWN
#define org_tanukisoftware_wrapper_WrapperManager_SERVICE_CONTROL_CODE_SHUTDOWN 5L
#undef org_tanukisoftware_wrapper_WrapperManager_SERVICE_CONTROL_CODE_POWEREVENT_QUERYSUSPEND
#define org_tanukisoftware_wrapper_WrapperManager_SERVICE_CONTROL_CODE_POWEREVENT_QUERYSUSPEND 3328L
#undef org_tanukisoftware_wrapper_WrapperManager_SERVICE_CONTROL_CODE_POWEREVENT_QUERYSUSPENDFAILED
#define org_tanukisoftware_wrapper_WrapperManager_SERVICE_CONTROL_CODE_POWEREVENT_QUERYSUSPENDFAILED 3330L
#undef org_tanukisoftware_wrapper_WrapperManager_SERVICE_CONTROL_CODE_POWEREVENT_SUSPEND
#define org_tanukisoftware_wrapper_WrapperManager_SERVICE_CONTROL_CODE_POWEREVENT_SUSPEND 3332L
#undef org_tanukisoftware_wrapper_WrapperManager_SERVICE_CONTROL_CODE_POWEREVENT_RESUMECRITICAL
#define org_tanukisoftware_wrapper_WrapperManager_SERVICE_CONTROL_CODE_POWEREVENT_RESUMECRITICAL 3334L
#undef org_tanukisoftware_wrapper_WrapperManager_SERVICE_CONTROL_CODE_POWEREVENT_RESUMESUSPEND
#define org_tanukisoftware_wrapper_WrapperManager_SERVICE_CONTROL_CODE_POWEREVENT_RESUMESUSPEND 3335L
#undef org_tanukisoftware_wrapper_WrapperManager_SERVICE_CONTROL_CODE_POWEREVENT_BATTERYLOW
#define org_tanukisoftware_wrapper_WrapperManager_SERVICE_CONTROL_CODE_POWEREVENT_BATTERYLOW 3337L
#undef org_tanukisoftware_wrapper_WrapperManager_SERVICE_CONTROL_CODE_POWEREVENT_POWERSTATUSCHANGE
#define org_tanukisoftware_wrapper_WrapperManager_SERVICE_CONTROL_CODE_POWEREVENT_POWERSTATUSCHANGE 3338L
#undef org_tanukisoftware_wrapper_WrapperManager_SERVICE_CONTROL_CODE_POWEREVENT_OEMEVENT
#define org_tanukisoftware_wrapper_WrapperManager_SERVICE_CONTROL_CODE_POWEREVENT_OEMEVENT 3339L
#undef org_tanukisoftware_wrapper_WrapperManager_SERVICE_CONTROL_CODE_POWEREVENT_RESUMEAUTOMATIC
#define org_tanukisoftware_wrapper_WrapperManager_SERVICE_CONTROL_CODE_POWEREVENT_RESUMEAUTOMATIC 3346L
/* Inaccessible static: m_out */
/* Inaccessible static: m_err */
/* Inaccessible static: m_outInfo */
/* Inaccessible static: m_outError */
/* Inaccessible static: m_outDebug */
/* Inaccessible static: m_windows */
/* Inaccessible static: m_macosx */
/* Inaccessible static: m_securityManagerChecked */
/* Inaccessible static: m_disposed */
/* Inaccessible static: m_starting */
/* Inaccessible static: m_started */
/* Inaccessible static: m_instance */
/* Inaccessible static: m_hook */
/* Inaccessible static: m_hookTriggered */
/* Inaccessible static: m_hookRemoveFailed */
/* Inaccessible static: m_shutdownJVMComplete */
/* Inaccessible static: m_shutdownLockMap */
/* Inaccessible static: m_shutdownLocks */
/* Inaccessible static: m_args */
/* Inaccessible static: m_backendType */
/* Inaccessible static: m_backendConnected */
/* Inaccessible static: m_backendOS */
/* Inaccessible static: m_backendIS */
/* Inaccessible static: m_port */
/* Inaccessible static: m_jvmPort */
/* Inaccessible static: m_jvmPortMin */
/* Inaccessible static: m_jvmPortMax */
/* Inaccessible static: m_wrapperPortAddress */
/* Inaccessible static: m_key */
/* Inaccessible static: m_soTimeout */
/* Inaccessible static: m_cpuTimeout */
/* Inaccessible static: m_startedTicks */
/* Inaccessible static: m_lowLogLevel */
/* Inaccessible static: m_ignoreSignals */
/* Inaccessible static: m_detachStarted */
/* Inaccessible static: m_commRunner */
/* Inaccessible static: m_commRunnerStarted */
/* Inaccessible static: m_eventRunner */
/* Inaccessible static: m_eventRunnerTicks */
/* Inaccessible static: m_startupRunner */
/* Inaccessible static: m_useSystemTime */
/* Inaccessible static: m_timerFastThreshold */
/* Inaccessible static: m_timerSlowThreshold */
/* Inaccessible static: m_disableTests */
/* Inaccessible static: m_listenerForceStop */
/* Inaccessible static: m_jvmBits */
/* Inaccessible static: m_ticks */
/* Inaccessible static: m_listener */
/* Inaccessible static: m_lastPingTicks */
/* Inaccessible static: m_backendSocket */
/* Inaccessible static: m_appearHung */
/* Inaccessible static: m_slowSeconds */
/* Inaccessible static: m_ignoreUserLogoffs */
/* Inaccessible static: m_service */
/* Inaccessible static: m_debug */
/* Inaccessible static: m_logFinalizer */
/* Inaccessible static: m_jvmId */
/* Inaccessible static: m_stoppingInit */
/* Inaccessible static: m_stopping */
/* Inaccessible static: m_stoppingThread */
/* Inaccessible static: m_stopped */
/* Inaccessible static: m_pendingStopMessage */
/* Inaccessible static: m_exitCode */
/* Inaccessible static: m_libraryOK */
/* Inaccessible static: m_commandBuffer */
/* Inaccessible static: m_logFile */
/* Inaccessible static: m_properties */
/* Inaccessible static: m_wrapperEventListenerMaskList */
/* Inaccessible static: m_wrapperEventListenerMasks */
/* Inaccessible static: m_produceCoreEvents */
/* Inaccessible static: m_res */
/* Inaccessible static: m_professionalEdition */
/* Inaccessible static: m_standardEdition */
/* Inaccessible static: PROPERTY_SEPARATOR */
/* Inaccessible static: m_backendReadBuffer */
/* Inaccessible static: class_00024org_00024tanukisoftware_00024wrapper_00024WrapperManager */
/* Inaccessible static: class_00024java_00024lang_00024String */
/* Inaccessible static: class_00024java_00024lang_00024Object */
/*
* Class: org_tanukisoftware_wrapper_WrapperManager
* Method: nativeInit
* Signature: (Z)V
*/
JNIEXPORT void JNICALL Java_org_tanukisoftware_wrapper_WrapperManager_nativeInit
(JNIEnv *, jclass, jboolean);
/*
* Class: org_tanukisoftware_wrapper_WrapperManager
* Method: nativeGetLibraryVersion
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_org_tanukisoftware_wrapper_WrapperManager_nativeGetLibraryVersion
(JNIEnv *, jclass);
/*
* Class: org_tanukisoftware_wrapper_WrapperManager
* Method: nativeGetJavaPID
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_org_tanukisoftware_wrapper_WrapperManager_nativeGetJavaPID
(JNIEnv *, jclass);
/*
* Class: org_tanukisoftware_wrapper_WrapperManager
* Method: nativeIsProfessionalEdition
* Signature: ()Z
*/
JNIEXPORT jboolean JNICALL Java_org_tanukisoftware_wrapper_WrapperManager_nativeIsProfessionalEdition
(JNIEnv *, jclass);
/*
* Class: org_tanukisoftware_wrapper_WrapperManager
* Method: nativeIsStandardEdition
* Signature: ()Z
*/
JNIEXPORT jboolean JNICALL Java_org_tanukisoftware_wrapper_WrapperManager_nativeIsStandardEdition
(JNIEnv *, jclass);
/*
* Class: org_tanukisoftware_wrapper_WrapperManager
* Method: nativeGetControlEvent
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_org_tanukisoftware_wrapper_WrapperManager_nativeGetControlEvent
(JNIEnv *, jclass);
/*
* Class: org_tanukisoftware_wrapper_WrapperManager
* Method: nativeRedirectPipes
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_org_tanukisoftware_wrapper_WrapperManager_nativeRedirectPipes
(JNIEnv *, jclass);
/*
* Class: org_tanukisoftware_wrapper_WrapperManager
* Method: nativeRequestThreadDump
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_org_tanukisoftware_wrapper_WrapperManager_nativeRequestThreadDump
(JNIEnv *, jclass);
/*
* Class: org_tanukisoftware_wrapper_WrapperManager
* Method: accessViolationInner
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_org_tanukisoftware_wrapper_WrapperManager_accessViolationInner
(JNIEnv *, jclass);
/*
* Class: org_tanukisoftware_wrapper_WrapperManager
* Method: nativeSetConsoleTitle
* Signature: (Ljava/lang/String;)V
*/
JNIEXPORT void JNICALL Java_org_tanukisoftware_wrapper_WrapperManager_nativeSetConsoleTitle
(JNIEnv *, jclass, jstring);
/*
* Class: org_tanukisoftware_wrapper_WrapperManager
* Method: nativeGetUser
* Signature: (Z)Lorg/tanukisoftware/wrapper/WrapperUser;
*/
JNIEXPORT jobject JNICALL Java_org_tanukisoftware_wrapper_WrapperManager_nativeGetUser
(JNIEnv *, jclass, jboolean);
/*
* Class: org_tanukisoftware_wrapper_WrapperManager
* Method: nativeGetInteractiveUser
* Signature: (Z)Lorg/tanukisoftware/wrapper/WrapperUser;
*/
JNIEXPORT jobject JNICALL Java_org_tanukisoftware_wrapper_WrapperManager_nativeGetInteractiveUser
(JNIEnv *, jclass, jboolean);
/*
* Class: org_tanukisoftware_wrapper_WrapperManager
* Method: nativeListServices
* Signature: ()[Lorg/tanukisoftware/wrapper/WrapperWin32Service;
*/
JNIEXPORT jobjectArray JNICALL Java_org_tanukisoftware_wrapper_WrapperManager_nativeListServices
(JNIEnv *, jclass);
/*
* Class: org_tanukisoftware_wrapper_WrapperManager
* Method: nativeSendServiceControlCode
* Signature: (Ljava/lang/String;I)Lorg/tanukisoftware/wrapper/WrapperWin32Service;
*/
JNIEXPORT jobject JNICALL Java_org_tanukisoftware_wrapper_WrapperManager_nativeSendServiceControlCode
(JNIEnv *, jclass, jstring, jint);
/*
* Class: org_tanukisoftware_wrapper_WrapperManager
* Method: nativeExec
* Signature: ([Ljava/lang/String;Ljava/lang/String;Lorg/tanukisoftware/wrapper/WrapperProcessConfig;Z)Lorg/tanukisoftware/wrapper/WrapperProcess;
*/
JNIEXPORT jobject JNICALL Java_org_tanukisoftware_wrapper_WrapperManager_nativeExec
(JNIEnv *, jclass, jobjectArray, jstring, jobject, jboolean);
/*
* Class: org_tanukisoftware_wrapper_WrapperManager
* Method: nativeWrapperGetEnv
* Signature: (Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_org_tanukisoftware_wrapper_WrapperManager_nativeWrapperGetEnv
(JNIEnv *, jclass, jstring);
/*
* Class: org_tanukisoftware_wrapper_WrapperManager
* Method: nativeLoadWrapperResources
* Signature: (Ljava/lang/String;Ljava/lang/String;Z)Lorg/tanukisoftware/wrapper/WrapperResources;
*/
JNIEXPORT jobject JNICALL Java_org_tanukisoftware_wrapper_WrapperManager_nativeLoadWrapperResources
(JNIEnv *, jclass, jstring, jstring, jboolean);
/*
* Class: org_tanukisoftware_wrapper_WrapperManager
* Method: nativeCheckDeadLocks
* Signature: ()Z
*/
JNIEXPORT jboolean JNICALL Java_org_tanukisoftware_wrapper_WrapperManager_nativeCheckDeadLocks
(JNIEnv *, jclass);
#ifdef __cplusplus
}
#endif
#endif
wrapper_3.5.22_src/src/c/org_tanukisoftware_wrapper_WrapperManager_ShutdownLock.h 100644 0 0 562 12224722016 25662 0 ustar 0 0 /* DO NOT EDIT THIS FILE - it is machine generated */
#include
/* Header for class org_tanukisoftware_wrapper_WrapperManager_ShutdownLock */
#ifndef _Included_org_tanukisoftware_wrapper_WrapperManager_ShutdownLock
#define _Included_org_tanukisoftware_wrapper_WrapperManager_ShutdownLock
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif
wrapper_3.5.22_src/src/c/org_tanukisoftware_wrapper_WrapperManager_WrapperEventListenerMask.h 100644 0 0 626 12224722016 30203 0 ustar 0 0 /* DO NOT EDIT THIS FILE - it is machine generated */
#include
/* Header for class org_tanukisoftware_wrapper_WrapperManager_WrapperEventListenerMask */
#ifndef _Included_org_tanukisoftware_wrapper_WrapperManager_WrapperEventListenerMask
#define _Included_org_tanukisoftware_wrapper_WrapperManager_WrapperEventListenerMask
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif
wrapper_3.5.22_src/src/c/org_tanukisoftware_wrapper_WrapperManager_WrapperInputStream.h 100644 0 0 1075 12224722016 27072 0 ustar 0 0 /* DO NOT EDIT THIS FILE - it is machine generated */
#include
/* Header for class org_tanukisoftware_wrapper_WrapperManager_WrapperInputStream */
#ifndef _Included_org_tanukisoftware_wrapper_WrapperManager_WrapperInputStream
#define _Included_org_tanukisoftware_wrapper_WrapperManager_WrapperInputStream
#ifdef __cplusplus
extern "C" {
#endif
#undef org_tanukisoftware_wrapper_WrapperManager_WrapperInputStream_MAX_SKIP_BUFFER_SIZE
#define org_tanukisoftware_wrapper_WrapperManager_WrapperInputStream_MAX_SKIP_BUFFER_SIZE 2048L
#ifdef __cplusplus
}
#endif
#endif
wrapper_3.5.22_src/src/c/org_tanukisoftware_wrapper_WrapperManager_WrapperTickEventImpl.h 100644 0 0 1117 12224722016 27332 0 ustar 0 0 /* DO NOT EDIT THIS FILE - it is machine generated */
#include
/* Header for class org_tanukisoftware_wrapper_WrapperManager_WrapperTickEventImpl */
#ifndef _Included_org_tanukisoftware_wrapper_WrapperManager_WrapperTickEventImpl
#define _Included_org_tanukisoftware_wrapper_WrapperManager_WrapperTickEventImpl
#ifdef __cplusplus
extern "C" {
#endif
#undef org_tanukisoftware_wrapper_WrapperManager_WrapperTickEventImpl_serialVersionUID
#define org_tanukisoftware_wrapper_WrapperManager_WrapperTickEventImpl_serialVersionUID 5516075349620653480LL
#ifdef __cplusplus
}
#endif
#endif
wrapper_3.5.22_src/src/c/org_tanukisoftware_wrapper_WrapperProcessConfig.h 100644 0 0 2553 12224722016 24372 0 ustar 0 0 /* DO NOT EDIT THIS FILE - it is machine generated */
#include
/* Header for class org_tanukisoftware_wrapper_WrapperProcessConfig */
#ifndef _Included_org_tanukisoftware_wrapper_WrapperProcessConfig
#define _Included_org_tanukisoftware_wrapper_WrapperProcessConfig
#ifdef __cplusplus
extern "C" {
#endif
#undef org_tanukisoftware_wrapper_WrapperProcessConfig_POSIX_SPAWN
#define org_tanukisoftware_wrapper_WrapperProcessConfig_POSIX_SPAWN 1L
#undef org_tanukisoftware_wrapper_WrapperProcessConfig_FORK_EXEC
#define org_tanukisoftware_wrapper_WrapperProcessConfig_FORK_EXEC 2L
#undef org_tanukisoftware_wrapper_WrapperProcessConfig_VFORK_EXEC
#define org_tanukisoftware_wrapper_WrapperProcessConfig_VFORK_EXEC 3L
#undef org_tanukisoftware_wrapper_WrapperProcessConfig_DYNAMIC
#define org_tanukisoftware_wrapper_WrapperProcessConfig_DYNAMIC 4L
/*
* Class: org_tanukisoftware_wrapper_WrapperProcessConfig
* Method: nativeGetEnv
* Signature: ()[Ljava/lang/String;
*/
JNIEXPORT jobjectArray JNICALL Java_org_tanukisoftware_wrapper_WrapperProcessConfig_nativeGetEnv
(JNIEnv *, jobject);
/*
* Class: org_tanukisoftware_wrapper_WrapperProcessConfig
* Method: isSupportedNative
* Signature: (I)Z
*/
JNIEXPORT jboolean JNICALL Java_org_tanukisoftware_wrapper_WrapperProcessConfig_isSupportedNative
(JNIEnv *, jclass, jint);
#ifdef __cplusplus
}
#endif
#endif
wrapper_3.5.22_src/src/c/org_tanukisoftware_wrapper_WrapperProcessInputStream.h 100644 0 0 2444 12224722016 25437 0 ustar 0 0 /* DO NOT EDIT THIS FILE - it is machine generated */
#include
/* Header for class org_tanukisoftware_wrapper_WrapperProcessInputStream */
#ifndef _Included_org_tanukisoftware_wrapper_WrapperProcessInputStream
#define _Included_org_tanukisoftware_wrapper_WrapperProcessInputStream
#ifdef __cplusplus
extern "C" {
#endif
#undef org_tanukisoftware_wrapper_WrapperProcessInputStream_SKIP_BUFFER_SIZE
#define org_tanukisoftware_wrapper_WrapperProcessInputStream_SKIP_BUFFER_SIZE 2048L
/* Inaccessible static: skipBuffer */
/*
* Class: org_tanukisoftware_wrapper_WrapperProcessInputStream
* Method: nativeRead
* Signature: (Z)I
*/
JNIEXPORT jint JNICALL Java_org_tanukisoftware_wrapper_WrapperProcessInputStream_nativeRead
(JNIEnv *, jobject, jboolean);
/*
* Class: org_tanukisoftware_wrapper_WrapperProcessInputStream
* Method: nativeClose
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_org_tanukisoftware_wrapper_WrapperProcessInputStream_nativeClose
(JNIEnv *, jobject);
/*
* Class: org_tanukisoftware_wrapper_WrapperProcessInputStream
* Method: nativeRead2
* Signature: ([BIIZ)I
*/
JNIEXPORT jint JNICALL Java_org_tanukisoftware_wrapper_WrapperProcessInputStream_nativeRead2
(JNIEnv *, jobject, jbyteArray, jint, jint, jboolean);
#ifdef __cplusplus
}
#endif
#endif
wrapper_3.5.22_src/src/c/org_tanukisoftware_wrapper_WrapperProcessOutputStream.h 100644 0 0 1520 12224722016 25632 0 ustar 0 0 /* DO NOT EDIT THIS FILE - it is machine generated */
#include
/* Header for class org_tanukisoftware_wrapper_WrapperProcessOutputStream */
#ifndef _Included_org_tanukisoftware_wrapper_WrapperProcessOutputStream
#define _Included_org_tanukisoftware_wrapper_WrapperProcessOutputStream
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: org_tanukisoftware_wrapper_WrapperProcessOutputStream
* Method: nativeWrite
* Signature: (I)V
*/
JNIEXPORT void JNICALL Java_org_tanukisoftware_wrapper_WrapperProcessOutputStream_nativeWrite
(JNIEnv *, jobject, jint);
/*
* Class: org_tanukisoftware_wrapper_WrapperProcessOutputStream
* Method: nativeClose
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_org_tanukisoftware_wrapper_WrapperProcessOutputStream_nativeClose
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
wrapper_3.5.22_src/src/c/org_tanukisoftware_wrapper_WrapperResources.h 100644 0 0 1540 12224722016 23573 0 ustar 0 0 /* DO NOT EDIT THIS FILE - it is machine generated */
#include
/* Header for class org_tanukisoftware_wrapper_WrapperResources */
#ifndef _Included_org_tanukisoftware_wrapper_WrapperResources
#define _Included_org_tanukisoftware_wrapper_WrapperResources
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: org_tanukisoftware_wrapper_WrapperResources
* Method: nativeGetLocalizedString
* Signature: (Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_org_tanukisoftware_wrapper_WrapperResources_nativeGetLocalizedString
(JNIEnv *, jobject, jstring);
/*
* Class: org_tanukisoftware_wrapper_WrapperResources
* Method: nativeDestroyResource
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_org_tanukisoftware_wrapper_WrapperResources_nativeDestroyResource
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
wrapper_3.5.22_src/src/c/property.c 100644 0 0 211661 12224722016 14451 0 ustar 0 0 /*
* Copyright (c) 1999, 2013 Tanuki Software, Ltd.
* http://www.tanukisoftware.comment
* All rights reserved.
*
* This software is the proprietary information of Tanuki Software.
* You shall use it only in accordance with the terms of the
* license agreement you entered into with Tanuki Software.
* http://wrapper.tanukisoftware.com/doc/english/licenseOverview.html
*
*
* Portions of the Software have been derived from source code
* developed by Silver Egg Technology under the following license:
*
* Copyright (c) 2001 Silver Egg Technology
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sub-license, and/or
* sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*/
#if defined(MACOSX) || defined(FREEBSD)
#else
#include
#endif
#include
#include
#include
#include
#ifdef WIN32
#include
/* MS Visual Studio 8 went and deprecated the POXIX names for functions.
* Fixing them all would be a big headache for UNIX versions. */
#pragma warning(disable : 4996)
#else
#include
#include
#include
#include
#if defined(IRIX)
#define PATH_MAX FILENAME_MAX
#endif
#endif
#include "wrapper_i18n.h"
#include "logger.h"
#include "property.h"
#include "wrapper.h"
#include "wrapper_file.h"
#define MAX_INCLUDE_DEPTH 10
EnvSrc *baseEnvSrc = NULL;
/** Stores the time that the property file began to be loaded. */
struct tm loadPropertiesTM;
const TCHAR **escapedPropertyNames = NULL;
void setInnerProperty(Properties *properties, Property *property, const TCHAR *propertyValue, int warnUndefinedVars);
/**
* @param warnUndefinedVars Log warnings about missing environment variables.
*/
void prepareProperty(Properties *properties, Property *property, int warnUndefinedVars) {
TCHAR *oldValue;
if (_tcsstr(property->value, TEXT("%"))) {
/* Reset the property. If the unreplaced environment variables are now available
* setting it again will cause it to be replaced correctly. If not this will
* only waste time. The value will be freed in the process so we need to
* keep it around. */
#ifdef _DEBUG
_tprintf( TEXT("Unreplaced property %s=%s\n"), property->name, property->value );
#endif
oldValue = malloc(sizeof(TCHAR) * (_tcslen(property->value) + 1));
if (!oldValue) {
outOfMemory(TEXT("PP"), 1);
} else {
_tcsncpy(oldValue, property->value, _tcslen(property->value) + 1);
setInnerProperty(properties, property, oldValue, warnUndefinedVars);
free(oldValue);
}
#ifdef _DEBUG
_tprintf( TEXT(" -> property %s=%s\n"), property->name, property->value );
#endif
}
}
/**
* Private function to find a Property structure.
*/
Property* getInnerProperty(Properties *properties, const TCHAR *propertyName, int warnUndefinedVars) {
Property *property;
int cmp;
/* Loop over the properties which are in order and look for the specified property. */
property = properties->first;
while (property != NULL) {
cmp = strcmpIgnoreCase(property->name, propertyName);
if (cmp > 0) {
/* This property would be after the one being looked for, so it does not exist. */
return NULL;
} else if (cmp == 0) {
/* We found it. */
prepareProperty(properties, property, warnUndefinedVars && properties->logWarnings);
return property;
}
/* Keep looking */
property = property->next;
}
/* We did not find the property being looked for. */
return NULL;
}
void insertInnerProperty(Properties *properties, Property *newProperty) {
Property *property;
int cmp;
/* Loop over the properties which are in order and look for the specified property. */
/* This function assumes that Property is not already in properties. */
property = properties->first;
while (property != NULL) {
cmp = strcmpIgnoreCase(property->name, newProperty->name);
if (cmp > 0) {
/* This property would be after the new property, so insert it here. */
newProperty->previous = property->previous;
newProperty->next = property;
if (property->previous == NULL) {
/* This was the first property */
properties->first = newProperty;
} else {
property->previous->next = newProperty;
}
property->previous = newProperty;
/* We are done, so return */
return;
}
property = property->next;
}
/* The new property needs to be added at the end */
newProperty->previous = properties->last;
if (properties->last == NULL) {
/* This will be the first property. */
properties->first = newProperty;
} else {
/* Point the old last property to the new last property. */
properties->last->next = newProperty;
}
properties->last = newProperty;
newProperty->next = NULL;
}
Property* createInnerProperty() {
Property *property;
property = malloc(sizeof(Property));
if (!property) {
outOfMemory(TEXT("CIP"), 1);
return NULL;
}
property->name = NULL;
property->next = NULL;
property->previous = NULL;
property->value = NULL;
return property;
}
/**
* Private function to dispose a Property structure. Assumes that the
* Property is disconnected already.
*/
void disposeInnerProperty(Property *property) {
if (property->name) {
free(property->name);
}
if (property->value) {
free(property->value);
}
free(property);
}
TCHAR generateValueBuffer[256];
/**
* This function returns a reference to a static buffer and is NOT thread safe.
*/
TCHAR* generateTimeValue(const TCHAR* format) {
if (strcmpIgnoreCase(format, TEXT("YYYYMMDDHHIISS")) == 0) {
_sntprintf(generateValueBuffer, 256, TEXT("%04d%02d%02d%02d%02d%02d"),
loadPropertiesTM.tm_year + 1900, loadPropertiesTM.tm_mon + 1, loadPropertiesTM.tm_mday,
loadPropertiesTM.tm_hour, loadPropertiesTM.tm_min, loadPropertiesTM.tm_sec );
} else if (strcmpIgnoreCase(format, TEXT("YYYYMMDD_HHIISS")) == 0) {
_sntprintf(generateValueBuffer, 256, TEXT("%04d%02d%02d_%02d%02d%02d"),
loadPropertiesTM.tm_year + 1900, loadPropertiesTM.tm_mon + 1, loadPropertiesTM.tm_mday,
loadPropertiesTM.tm_hour, loadPropertiesTM.tm_min, loadPropertiesTM.tm_sec );
} else if (strcmpIgnoreCase(format, TEXT("YYYYMMDDHHII")) == 0) {
_sntprintf(generateValueBuffer, 256, TEXT("%04d%02d%02d%02d%02d"),
loadPropertiesTM.tm_year + 1900, loadPropertiesTM.tm_mon + 1, loadPropertiesTM.tm_mday,
loadPropertiesTM.tm_hour, loadPropertiesTM.tm_min );
} else if (strcmpIgnoreCase(format, TEXT("YYYYMMDDHH")) == 0) {
_sntprintf(generateValueBuffer, 256, TEXT("%04d%02d%02d%02d"),
loadPropertiesTM.tm_year + 1900, loadPropertiesTM.tm_mon + 1, loadPropertiesTM.tm_mday,
loadPropertiesTM.tm_hour );
} else if (strcmpIgnoreCase(format, TEXT("YYYYMMDD")) == 0) {
_sntprintf(generateValueBuffer, 256, TEXT("%04d%02d%02d"),
loadPropertiesTM.tm_year + 1900, loadPropertiesTM.tm_mon + 1, loadPropertiesTM.tm_mday);
} else {
_sntprintf(generateValueBuffer, 256, TEXT("{INVALID}"));
}
return generateValueBuffer;
}
/**
* This function returns a reference to a static buffer and is NOT thread safe.
*/
TCHAR* generateRandValue(const TCHAR* format) {
if (strcmpIgnoreCase(format, TEXT("N")) == 0) {
_sntprintf(generateValueBuffer, 256, TEXT("%01d"), rand() % 10);
} else if (strcmpIgnoreCase(format, TEXT("NN")) == 0) {
_sntprintf(generateValueBuffer, 256, TEXT("%02d"), rand() % 100);
} else if (strcmpIgnoreCase(format, TEXT("NNN")) == 0) {
_sntprintf(generateValueBuffer, 256, TEXT("%03d"), rand() % 1000);
} else if (strcmpIgnoreCase(format, TEXT("NNNN")) == 0) {
_sntprintf(generateValueBuffer, 256, TEXT("%04d"), rand() % 10000);
} else if (strcmpIgnoreCase(format, TEXT("NNNNN")) == 0) {
_sntprintf(generateValueBuffer, 256, TEXT("%04d%01d"), rand() % 10000, rand() % 10);
} else if (strcmpIgnoreCase(format, TEXT("NNNNNN")) == 0) {
_sntprintf(generateValueBuffer, 256, TEXT("%04d%02d"), rand() % 10000, rand() % 100);
} else {
_sntprintf(generateValueBuffer, 256, TEXT("{INVALID}"));
}
return generateValueBuffer;
}
/**
* Parses a property value and populates any environment variables. If the expanded
* environment variable would result in a string that is longer than bufferLength
* the value is truncated.
*
* @param warnUndefinedVars Log warnings about missing environment variables.
* @param warnedUndefVarMap Map of variables which have previously been logged, may be NULL if warnUndefinedVars false.
* @param warnLogLevel Log level at which any warnings will be logged.
*/
void evaluateEnvironmentVariables(const TCHAR *propertyValue, TCHAR *buffer, int bufferLength, int warnUndefinedVars, PHashMap warnedUndefVarMap, int warnLogLevel) {
const TCHAR *in;
TCHAR *out;
TCHAR *envName;
TCHAR *envValue;
int envValueNeedFree;
TCHAR *start;
TCHAR *end;
size_t len;
size_t outLen;
size_t bufferAvailable;
#ifdef _DEBUG
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT("evaluateEnvironmentVariables(properties, '%s', buffer, %d, %d)"), propertyValue, bufferLength, warnUndefinedVars);
#endif
buffer[0] = TEXT('\0');
in = propertyValue;
out = buffer;
bufferAvailable = bufferLength - 1; /* Reserver room for the null terminator */
/* Loop until we hit the end of string. */
while (in[0] != TEXT('\0')) {
#ifdef _DEBUG
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT(" initial='%s', buffer='%s'"), propertyValue, buffer);
#endif
start = _tcschr(in, TEXT('%'));
if (start != NULL) {
end = _tcschr(start + 1, TEXT('%'));
if (end != NULL) {
/* A pair of '%' characters was found. An environment */
/* variable name should be between the two. */
len = (int)(end - start - 1);
envName = malloc(sizeof(TCHAR) * (len + 1));
if (envName == NULL) {
outOfMemory(TEXT("EEV"), 1);
return;
}
_tcsncpy(envName, start + 1, len);
envName[len] = TEXT('\0');
/* See if it is a special dynamic environment variable */
envValueNeedFree = FALSE;
if (_tcsstr(envName, TEXT("WRAPPER_TIME_")) == envName) {
/* Found a time value. */
envValue = generateTimeValue(envName + 13);
} else if (_tcsstr(envName, TEXT("WRAPPER_RAND_")) == envName) {
/* Found a time value. */
envValue = generateRandValue(envName + 13);
} else {
/* Try looking up the environment variable. */
envValue = _tgetenv(envName);
#if !defined(WIN32) && defined(UNICODE)
envValueNeedFree = TRUE;
#endif
}
if (envValue != NULL) {
/* An envvar value was found. */
/* Copy over any text before the envvar */
outLen = (int)(start - in);
if (bufferAvailable < outLen) {
outLen = bufferAvailable;
}
if (outLen > 0) {
_tcsncpy(out, in, outLen);
out += outLen;
bufferAvailable -= outLen;
}
/* Copy over the env value */
outLen = _tcslen(envValue);
if (bufferAvailable < outLen) {
outLen = bufferAvailable;
}
if (outLen > 0) {
_tcsncpy(out, envValue, outLen);
out += outLen;
bufferAvailable -= outLen;
}
if (envValueNeedFree) {
free(envValue);
}
/* Terminate the string */
out[0] = TEXT('\0');
/* Set the new in pointer */
in = end + 1;
} else {
/* Not found. So copy over the input up until the */
/* second '%'. Leave it in case it is actually the */
/* start of an environment variable name */
outLen = len = end - in + 1;
if (bufferAvailable < outLen) {
outLen = bufferAvailable;
}
if (outLen > 0) {
_tcsncpy(out, in, outLen);
out += outLen;
bufferAvailable -= outLen;
}
in += len;
/* Terminate the string */
out[0] = TEXT('\0');
if (warnUndefinedVars) {
if (hashMapGetKWVW(warnedUndefVarMap, envName) == NULL) {
/* This is the first time this environment variable was noticed, so report it to the user then remember so we don't report it again. */
log_printf(WRAPPER_SOURCE_WRAPPER, warnLogLevel, TEXT("The '%s' environment variable was referenced but has not been defined."), envName);
hashMapPutKWVW(warnedUndefVarMap, envName, envName);
}
}
}
free(envName);
} else {
/* Only a single '%' TCHAR was found. Leave it as is. */
outLen = len = _tcslen(in);
if (bufferAvailable < outLen) {
outLen = bufferAvailable;
}
if (outLen > 0) {
_tcsncpy(out, in, outLen);
out += outLen;
bufferAvailable -= outLen;
}
in += len;
/* Terminate the string */
out[0] = TEXT('\0');
}
} else {
/* No more '%' chars in the string. Copy over the rest. */
outLen = len = _tcslen(in);
if (bufferAvailable < outLen) {
outLen = bufferAvailable;
}
if (outLen > 0) {
_tcsncpy(out, in, outLen);
out += outLen;
bufferAvailable -= outLen;
}
in += len;
/* Terminate the string */
out[0] = TEXT('\0');
}
}
#ifdef _DEBUG
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT(" final buffer='%s'"), buffer);
#endif
}
/**
*
* @param warnUndefinedVars Log warnings about missing environment variables.
*/
void setInnerProperty(Properties *properties, Property *property, const TCHAR *propertyValue, int warnUndefinedVars) {
int i, count;
/* The property value is expanded into a large buffer once, but that is temporary. The actual
* value is stored in the minimum required size. */
TCHAR *buffer;
/* Free any existing value */
if (property->value != NULL) {
free(property->value);
property->value = NULL;
}
/* Set the new value using a copy of the provided value. */
if (propertyValue == NULL) {
property->value = NULL;
} else {
buffer = malloc(MAX_PROPERTY_VALUE_LENGTH * sizeof(TCHAR));
if (buffer) {
evaluateEnvironmentVariables(propertyValue, buffer, MAX_PROPERTY_VALUE_LENGTH, warnUndefinedVars, properties->warnedVarMap, properties->logWarningLogLevel);
property->value = malloc(sizeof(TCHAR) * (_tcslen(buffer) + 1));
if (!property->value) {
outOfMemoryQueued(TEXT("SIP"), 1);
} else {
/* Strip any non valid characters like control characters. Some valid characters are
* less than 0 when the TCHAR is unsigned. */
for (i = 0, count = 0; i < (int)_tcslen(buffer); i++) {
/* Only add valid characters, skipping any control characters EXCEPT for a line feed. */
if ((buffer[i] == TEXT('\n')) || (!_istcntrl(buffer[i]))) {
property->value[count++] = buffer[i];
}
}
/* Crop string to new size */
property->value[count] = TEXT('\0');
}
free(buffer);
} else {
outOfMemoryQueued(TEXT("SIP"), 2);
}
}
}
/**
* Function to get the system encoding name/number for the encoding
* of the conf file
*
* @para String holding the encoding from the conf file
*
* @return TRUE if not found, FALSE otherwise
*
*/
#ifdef WIN32
#define strIgnoreCaseCmp stricmp
int getEncodingByName(char* encodingMB, int *encoding) {
#else
#define strIgnoreCaseCmp strcasecmp
int getEncodingByName(char* encodingMB, char** encoding) {
#endif
if (strIgnoreCaseCmp(encodingMB, "Shift_JIS") == 0) {
#if defined(FREEBSD) || defined (AIX) || defined(MACOSX)
*encoding = "SJIS";
#elif defined(WIN32)
*encoding = 932;
#else
*encoding = "shiftjis";
#endif
} else if (strIgnoreCaseCmp(encodingMB, "eucJP") == 0) {
#if defined(AIX)
*encoding = "IBM-eucJP";
#elif defined(WIN32)
*encoding = 20932;
#else
*encoding = "eucJP";
#endif
} else if (strIgnoreCaseCmp(encodingMB, "UTF-8") == 0) {
#if defined(HPUX)
*encoding = "utf8";
#elif defined(WIN32)
*encoding = 65001;
#else
*encoding = "UTF-8";
#endif
} else if (strIgnoreCaseCmp(encodingMB, "ISO-8859-1") == 0) {
#if defined(WIN32)
*encoding = 28591;
#elif defined(LINUX)
*encoding = "ISO-8859-1";
#else
*encoding = "ISO8859-1";
#endif
} else if (strIgnoreCaseCmp(encodingMB, "CP1252") == 0) {
#if defined(WIN32)
*encoding = 1252;
#else
*encoding = "CP1252";
#endif
} else if (strIgnoreCaseCmp(encodingMB, "ISO-8859-2") == 0) {
#if defined(WIN32)
*encoding = 28592;
#elif defined(LINUX)
*encoding = "ISO-8859-2";
#else
*encoding = "ISO8859-2";
#endif
} else if (strIgnoreCaseCmp(encodingMB, "ISO-8859-3") == 0) {
#if defined(WIN32)
*encoding = 28593;
#elif defined(LINUX)
*encoding = "ISO-8859-3";
#else
*encoding = "ISO8859-3";
#endif
} else if (strIgnoreCaseCmp(encodingMB, "ISO-8859-4") == 0) {
#if defined(WIN32)
*encoding = 28594;
#elif defined(LINUX)
*encoding = "ISO-8859-4";
#else
*encoding = "ISO8859-4";
#endif
} else if (strIgnoreCaseCmp(encodingMB, "ISO-8859-5") == 0) {
#if defined(WIN32)
*encoding = 28595;
#elif defined(LINUX)
*encoding = "ISO-8859-5";
#else
*encoding = "ISO8859-5";
#endif
} else if (strIgnoreCaseCmp(encodingMB, "ISO-8859-6") == 0) {
#if defined(WIN32)
*encoding = 28596;
#elif defined(LINUX)
*encoding = "ISO-8859-6";
#else
*encoding = "ISO8859-6";
#endif
} else if (strIgnoreCaseCmp(encodingMB, "ISO-8859-7") == 0) {
#if defined(WIN32)
*encoding = 28597;
#elif defined(LINUX)
*encoding = "ISO-8859-7";
#else
*encoding = "ISO8859-7";
#endif
} else if (strIgnoreCaseCmp(encodingMB, "ISO-8859-8") == 0) {
#if defined(WIN32)
*encoding = 28598;
#elif defined(LINUX)
*encoding = "ISO-8859-8";
#else
*encoding = "ISO8859-8";
#endif
} else if (strIgnoreCaseCmp(encodingMB, "ISO-8859-9") == 0) {
#if defined(WIN32)
*encoding = 28599;
#elif defined(LINUX)
*encoding = "ISO-8859-9";
#else
*encoding = "ISO8859-9";
#endif
} else if (strIgnoreCaseCmp(encodingMB, "ISO-8859-10") == 0) {
#if defined(WIN32)
*encoding = 28600;
#elif defined(LINUX)
*encoding = "ISO-8859-10";
#else
*encoding = "ISO8859-10";
#endif
} else if (strIgnoreCaseCmp(encodingMB, "ISO-8859-11") == 0) {
#if defined(WIN32)
*encoding = 28601;
#elif defined(LINUX)
*encoding = "ISO-8859-11";
#else
*encoding = "ISO8859-11";
#endif
} else if (strIgnoreCaseCmp(encodingMB, "ISO-8859-13") == 0) {
#if defined(WIN32)
*encoding = 28603;
#elif defined(LINUX)
*encoding = "ISO-8859-13";
#else
*encoding = "ISO8859-13";
#endif
} else if (strIgnoreCaseCmp(encodingMB, "ISO-8859-14") == 0) {
#if defined(WIN32)
*encoding = 28604;
#elif defined(LINUX)
*encoding = "ISO-8859-14";
#else
*encoding = "ISO8859-14";
#endif
} else if (strIgnoreCaseCmp(encodingMB, "ISO-8859-15") == 0) {
#if defined(WIN32)
*encoding = 28605;
#elif defined(LINUX)
*encoding = "ISO-8859-15";
#else
*encoding = "ISO8859-15";
#endif
} else if (strIgnoreCaseCmp(encodingMB, "ISO-8859-16") == 0) {
#if defined(WIN32)
*encoding = 28606;
#elif defined(LINUX)
*encoding = "ISO-8859-16";
#else
*encoding = "ISO8859-16";
#endif
} else if (strIgnoreCaseCmp(encodingMB, "CP1250") == 0) {
#if defined(WIN32)
*encoding = 1250;
#else
*encoding = "CP1250";
#endif
} else if (strIgnoreCaseCmp(encodingMB, "CP1251") == 0) {
#if defined(WIN32)
*encoding = 1251;
#else
*encoding = "CP1251";
#endif
} else if (strIgnoreCaseCmp(encodingMB, "KOI8-R") == 0) {
#if defined(WIN32)
*encoding = 20866;
#else
*encoding = "KOI8-R";
#endif
} else if (strIgnoreCaseCmp(encodingMB, "KOI8-U") == 0) {
#if defined(WIN32)
*encoding = 21866;
#else
*encoding = "KOI8-U";
#endif
} else if (strIgnoreCaseCmp(encodingMB, "DEFAULT") == 0) {
#ifdef WIN32
*encoding = GetACP();
#else
*encoding = nl_langinfo(CODESET);
#ifdef MACOSX
if (strlen(*encoding) == 0) {
*encoding = "UTF-8";
}
#endif
#endif
} else {
return TRUE;
}
return FALSE;
}
static int loadPropertiesCallback(void *callbackParam, const TCHAR *fileName, int lineNumber, TCHAR *config, int debugProperties)
{
Properties *properties = (Properties *)callbackParam;
TCHAR *d;
properties->debugProperties = debugProperties;
if (_tcsstr(config, TEXT("include")) == config) {
/* Users sometimes remove the '#' from include statements.
Add a warning to help them notice the problem. */
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_ADVICE,
TEXT("Include file reference missing leading '#': %s"), config);
} else if ((d = _tcschr(config, TEXT('='))) != NULL) {
/* Locate the first '=' in the line, ignore lines that do not contain a '=' */
/* Null terminate the first half of the line. */
*d = TEXT('\0');
d++;
addProperty(properties, fileName, lineNumber, config, d, FALSE, FALSE, TRUE, FALSE);
}
return TRUE;
}
/**
* Create a Properties structure loaded in from the specified file.
* Must call disposeProperties to free up allocated memory.
*
* @param properties Properties structure to load into.
* @param filename File to load the properties from.
* @param preload TRUE if this is a preload call that should have supressed error output.
*
* @return TRUE if there were any problems, FALSE if successful.
*/
int loadProperties(Properties *properties, const TCHAR* filename, int preload) {
/* Store the time that the property file began to be loaded. */
#ifdef WIN32
struct _timeb timebNow;
#else
struct timeval timevalNow;
#endif
time_t now;
struct tm *nowTM;
ConfigFileReader reader;
int loadResult;
#ifdef WIN32
_ftime( &timebNow );
now = (time_t)timebNow.time;
#else
gettimeofday(&timevalNow, NULL);
now = (time_t)timevalNow.tv_sec;
#endif
nowTM = localtime(&now);
memcpy(&loadPropertiesTM, nowTM, sizeof(struct tm));
configFileReader_Initialize(&reader, loadPropertiesCallback, properties, TRUE);
/* Store the preload flag for this loading of properties. */
reader.preload = preload;
loadResult = configFileReader_Read(&reader, filename, 0, 0, NULL, 0);
/* Any failure is a failure in the root. */
switch (loadResult) {
case CONFIG_FILE_READER_SUCCESS:
return FALSE;
case CONFIG_FILE_READER_FAIL:
case CONFIG_FILE_READER_HARD_FAIL:
return TRUE;
default:
_tprintf(TEXT("Unexpected load error %d\n"), loadResult);
return TRUE;
}
}
Properties* createProperties() {
Properties *properties = malloc(sizeof(Properties));
if (!properties) {
outOfMemory(TEXT("CP"), 1);
return NULL;
}
properties->debugProperties = FALSE;
properties->logWarnings = TRUE;
properties->logWarningLogLevel = LEVEL_WARN;
properties->first = NULL;
properties->last = NULL;
properties->warnedVarMap = newHashMap(8);
if (!properties->warnedVarMap) {
return NULL;
}
return properties;
}
void disposeProperties(Properties *properties) {
/* Loop and dispose any Property structures */
Property *tempProperty;
Property *property;
if (properties) {
property = properties->first;
properties->first = NULL;
properties->last = NULL;
while (property != NULL) {
/* Save the next property */
tempProperty = property->next;
/* Clean up the current property */
disposeInnerProperty(property);
property = NULL;
/* set the current property to the next. */
property = tempProperty;
}
if (properties->warnedVarMap) {
freeHashMap(properties->warnedVarMap);
}
/* Dispose the Properties structure */
free(properties);
properties = NULL;
}
}
/**
* This method cleans the environment at shutdown.
*/
void disposeEnvironment() {
EnvSrc *current, *previous;
if (baseEnvSrc) {
current = baseEnvSrc;
while (current != NULL) {
free(current->name);
previous = current;
current = current->next;
free(previous);
}
baseEnvSrc = NULL;
}
}
void removeProperty(Properties *properties, const TCHAR *propertyName) {
Property *property;
Property *next;
Property *previous;
/* Look up the property */
property = getInnerProperty(properties, propertyName, FALSE);
if (property == NULL) {
/* The property did not exist, so nothing to do. */
} else {
next = property->next;
previous = property->previous;
/* Disconnect the property */
if (next == NULL) {
/* This was the last property */
properties->last = previous;
} else {
next->previous = property->previous;
}
if (previous == NULL) {
/* This was the first property */
properties->first = next;
} else {
previous->next = property->next;
}
/* Now that property is disconnected, if can be disposed. */
disposeInnerProperty(property);
}
}
/**
* Sets an environment variable with the specified value.
* The function will only set the variable if its value is changed, but if
* it does, the call will result in a memory leak the size of the string:
* "name=value".
*
* For Windows, the putenv_s funcion looks better, but it is not available
* on some older SDKs and non-pro versions of XP.
*
* @param name Name of the variable being set.
* @param value Value to be set, NULL to clear it.
*
* Return TRUE if there were any problems, FALSE otherwise.
*/
int setEnvInner(const TCHAR *name, const TCHAR *value) {
int result = FALSE;
TCHAR *oldVal;
#ifdef WIN32
#if !defined(WRAPPER_USE_PUTENV_S)
size_t len;
TCHAR *envBuf;
#endif
#endif
#if defined(WRAPPER_USE_PUTENV)
size_t len;
TCHAR *envBuf;
#endif
/* Get the current environment variable value so we can avoid allocating and
* setting the variable if it has not changed its value. */
oldVal = _tgetenv(name);
if (value == NULL) {
/*_tprintf("clear %s=\n", name);*/
/* Only clear the variable if it is actually set to avoid unnecessary leaks. */
if (oldVal != NULL) {
#ifdef WIN32
#if defined(WRAPPER_USE_PUTENV_S)
if (_tputenv_s(name, TEXT("")) == EINVAL) {
_tprintf(TEXT("Unable to clear environment variable: %s\n"), name);
result = TRUE;
}
#else
len = _tcslen(name) + 1 + 1;
envBuf = malloc(sizeof(TCHAR) * len);
if (!envBuf) {
outOfMemory(TEXT("SEI"), 1);
result = TRUE;
} else {
_sntprintf(envBuf, len, TEXT("%s="), name);
/* The memory pointed to by envBuf should only be freed if this is UNICODE. */
if (_tputenv(envBuf)) {
_tprintf(TEXT("Unable to clear environment variable: %s\n"), name);
result = TRUE;
}
}
#endif
#else
#if defined(WRAPPER_USE_PUTENV)
len = _tcslen(name) + 1 + 1;
envBuf = malloc(sizeof(TCHAR) * len);
if (!envBuf) {
outOfMemory(TEXT("SEI"), 1);
result = TRUE;
} else {
_sntprintf(envBuf, len, TEXT("%s="), name);
/* The memory pointed to by envBuf should only be freed if this is UNICODE. */
if (_tputenv(envBuf)) {
_tprintf(TEXT("Unable to clear environment variable: %s\n"), name);
result = TRUE;
}
#ifdef UNICODE
free(envBuf);
#endif
}
#else
_tunsetenv(name);
#endif
#endif
}
} else {
/*_tprintf("set %s=%s\n", name, value);*/
if ((oldVal == NULL) || (_tcscmp(oldVal, value) != 0)) {
#ifdef WIN32
#if defined(WRAPPER_USE_PUTENV_S)
if (_tputenv_s(name, value) == EINVAL) {
_tprintf(TEXT("Unable to set environment variable: %s=%s\n"), name, value);
result = TRUE;
}
#else
len = _tcslen(name) + 1 + _tcslen(value) + 1;
envBuf = malloc(sizeof(TCHAR) * len);
if (!envBuf) {
outOfMemory(TEXT("SEI"), 2);
result = TRUE;
} else {
_sntprintf(envBuf, len, TEXT("%s=%s"), name, value);
/* The memory pointed to by envBuf should only be freed if this is UNICODE. */
if (_tputenv(envBuf)) {
_tprintf(TEXT("Unable to set environment variable: %s=%s\n"), name, value);
result = TRUE;
}
}
#endif
#else
#if defined(WRAPPER_USE_PUTENV)
len = _tcslen(name) + 1 + _tcslen(value) + 1;
envBuf = malloc(sizeof(TCHAR) * len);
if (!envBuf) {
outOfMemory(TEXT("SEI"), 2);
result = TRUE;
} else {
_sntprintf(envBuf, len, TEXT("%s=%s"), name, value);
/* The memory pointed to by envBuf should only be freed if this is UNICODE. */
if (_tputenv(envBuf)) {
_tprintf(TEXT("Unable to set environment variable: %s=%s\n"), name, value);
result = TRUE;
}
#ifdef UNICODE
free(envBuf);
#endif
}
#else
if (_tsetenv(name, value, TRUE)) {
_tprintf(TEXT("Unable to set environment variable: %s=%s\n"), name, value);
result = TRUE;
}
#endif
#endif
}
}
#if !defined(WIN32) && defined(UNICODE)
if (oldVal != NULL) {
free(oldVal);
}
#endif
return result;
}
/**
* Sets an environment variable with the specified value.
* The function will only set the variable if its value is changed, but if
* it does, the call will result in a memory leak the size of the string:
* "name=value".
*
* @param name Name of the variable being set.
* @param value Value to be set, NULL to clear it.
* @param source Where the variable came from. If value is WRAPPER_ENV_SOURCE_PARENT
* then the value may be NULL and will never be set to the environment.
*
* Return TRUE if there were any problems, FALSE otherwise.
*/
int setEnv(const TCHAR *name, const TCHAR *value, int source) {
EnvSrc **thisEnvSrcRef;
EnvSrc *thisEnvSrc;
size_t len;
TCHAR *nameCopy;
EnvSrc *newEnvSrc;
int cmpRes;
#ifdef _DEBUG
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT("setEnv(%s, %s, %d)"), name, value, source);
#endif
thisEnvSrcRef = &baseEnvSrc;
thisEnvSrc = baseEnvSrc;
/* Create a copy of the name so we can store it. */
len = _tcslen(name) + 1;
nameCopy = malloc(sizeof(TCHAR) * len);
if (!nameCopy) {
outOfMemory(TEXT("SE"), 1);
return TRUE;
}
_sntprintf(nameCopy, len, TEXT("%s"), name);
/* Figure out where we want to set the value. */
while (thisEnvSrc) {
cmpRes = strcmpIgnoreCase(thisEnvSrc->name, name);
if (cmpRes == 0) {
/* This is the same value. It is being changed. */
/* The nameCopy is not needed so free it up. */
free(nameCopy);
thisEnvSrc->source |= source;
if (source != ENV_SOURCE_PARENT) {
return setEnvInner(name, value);
}
return FALSE;
} else if (cmpRes > 0) {
/* This EnvSrc would be after the one being set, so we need to insert it. */
newEnvSrc = malloc(sizeof(EnvSrc));
if (!newEnvSrc) {
outOfMemory(TEXT("SEV"), 2);
return TRUE;
}
newEnvSrc->source = source;
newEnvSrc->name = nameCopy;
newEnvSrc->next = thisEnvSrc;
*thisEnvSrcRef = newEnvSrc;
if (source != ENV_SOURCE_PARENT) {
return setEnvInner(name, value);
}
return FALSE;
} else {
/* This EnvSrc would be before the one being set, so keep looking. */
thisEnvSrcRef = &(thisEnvSrc->next);
thisEnvSrc = thisEnvSrc->next;
}
}
/* If we get here then we are at the end of the list. */
thisEnvSrc = malloc(sizeof(EnvSrc));
if (!thisEnvSrc) {
outOfMemory(TEXT("SEV"), 3);
return TRUE;
}
thisEnvSrc->source = source;
thisEnvSrc->name = nameCopy;
thisEnvSrc->next = NULL;
*thisEnvSrcRef = thisEnvSrc;
if (source != ENV_SOURCE_PARENT) {
return setEnvInner(name, value);
}
return FALSE;
}
/* Trims any whitespace from the beginning and end of the in string
* and places the results in the out buffer. Assumes that the out
* buffer is at least as large as the in buffer. */
void trim(const TCHAR *in, TCHAR *out) {
size_t len;
size_t first;
size_t last;
len = _tcslen(in);
if (len > 0) {
first = 0;
last = len - 1;
/* Right Trim */
while (((in[first] == ' ') || (in[first] == '\t')) && (first < last)) {
first++;
}
/* Left Trim */
while ((last > first) && ((in[last] == ' ') || (in[last] == '\t'))) {
last--;
}
/* Copy over what is left. */
len = last - first + 1;
if (len > 0) {
_tcsncpy(out, in + first, len);
}
}
out[len] = TEXT('\0');
}
/**
* Used to set a NULL terminated list of property names whose values should be
* escaped when read in from a file. '\\' will become '\' and '\n' will
* become '^J', all other characters following '\' will be left as is.
*
* @param propertyNames NULL terminated list of property names. Property names
* can contain a single '*' wildcard which will match 0 or
* more characters.
*/
void setEscapedProperties(const TCHAR **propertyNames) {
escapedPropertyNames = propertyNames;
}
/**
* Returns true if the specified property matches one of the property names
* previosly set in a call to setEscapableProperties()
*
* @param propertyName Property name to test.
*
* @return TRUE if the property should be escaped. FALSE otherwise.
*/
int isEscapedProperty(const TCHAR *propertyName) {
size_t nameLen;
size_t i;
const TCHAR *pattern;
TCHAR *wildPos;
size_t headLen;
size_t tailLen;
int matched;
size_t patternI;
size_t nameI;
if (escapedPropertyNames) {
nameLen = _tcslen(propertyName);
i = 0;
while (escapedPropertyNames[i]) {
pattern = escapedPropertyNames[i];
if (strcmpIgnoreCase(pattern, propertyName) == 0) {
/* Direct Match. */
#ifdef _DEBUG
_tprintf(TEXT("Property %s matched pattern %s\n"), propertyName, pattern);
#endif
return TRUE;
} else {
wildPos = _tcschr(pattern, TEXT('*'));
if (wildPos) {
/* The string contains a wildcard. */
/* Try to match the head of the property name. */
headLen = wildPos - pattern;
if (headLen < nameLen) {
matched = TRUE;
patternI = 0;
nameI = 0;
while (patternI < headLen) {
if (pattern[patternI] != propertyName[nameI]) {
matched = FALSE;
break;
}
patternI++;
nameI++;
}
if (matched) {
tailLen = _tcslen(pattern) - headLen - 1;
if (tailLen < nameLen - headLen) {
matched = TRUE;
patternI = headLen + 1;
nameI = nameLen - tailLen;
while (nameI < nameLen) {
if (pattern[patternI] != propertyName[nameI]) {
matched = FALSE;
break;
}
patternI++;
nameI++;
}
if (matched) {
#ifdef _DEBUG
_tprintf(TEXT("Property %s matched pattern %s\n"), propertyName, pattern);
#endif
return TRUE;
}
}
}
}
}
}
i++;
}
}
return FALSE;
}
/**
* Expands escaped characters and returns a newly malloced string with the result.
* '\n' replaced with '^J'
* '\\' replaced with '\'
* Other escaped characters will show as is.
*
* @param buffer Original buffer containing escaped characters.
*
* @return The new expanded buffer. It is the responsibility of the caller to free memory later.
*/
TCHAR *expandEscapedCharacters(const TCHAR* buffer) {
size_t inPos;
size_t outPos;
TCHAR *outBuffer;
int i;
TCHAR c1, c2;
/* First count the length of the required output buffer to hold the current line. Use the same code twice to avoid maintenance problems. */
outBuffer = NULL;
for (i = 0; i < 2; i++) {
inPos = 0;
outPos = 0;
do {
c1 = buffer[inPos];
/* The real backslash is #92. The yen mark from files loaded from ShiftJIS is #165. */
if ((c1 == TEXT('\\')) || (c1 == 165)) {
/* Escape. */
c2 = buffer[inPos + 1];
if (c2 == TEXT('n')) {
/* Line feed. */
inPos++;
if (outBuffer) {
outBuffer[outPos] = TEXT('\n');
}
outPos++;
} else if ((c2 == TEXT('\\')) || (c2 == 165)) {
/* Back slash. */
inPos++;
if (outBuffer) {
outBuffer[outPos] = c1;
}
outPos++;
} else if (c2 == 0) {
/* Premature End of buffer. Show the backslash. */
if (outBuffer) {
outBuffer[outPos] = c1;
}
outPos++;
c1 = 0;
} else {
/* Unknown char, show the unescaped backslash. */
inPos++;
if (outBuffer) {
outBuffer[outPos] = c1;
outBuffer[outPos + 1] = c2;
}
outPos += 2;
}
inPos++;
} else if (c1 == 0) {
/* End of buffer. */
} else {
/* Normal character. */
if (outBuffer) {
outBuffer[outPos] = c1;
}
outPos++;
inPos++;
}
} while (c1 != 0);
/* string terminator. */
if (outBuffer) {
outBuffer[outPos] = TEXT('\0');
}
outPos++;
if (outBuffer) {
/* We have have full outBuffer. Fall through. */
} else {
/* First pass. We need to allocate the outBuffer. */
outBuffer = malloc(outPos * sizeof(TCHAR));
if (!outBuffer) {
outOfMemory(TEXT("ELF"), 1);
return NULL;
}
}
}
return outBuffer;
}
/**
* Adds a single property to the properties structure.
*
* @param properties Properties structure to add to.
* @param filename Name of the file from which the property was loaded. NULL, if not from a file.
* @param lineNum Line number of the property declaration in the file. Ignored if filename is NULL.
* @param propertyName Name of the new Property.
* @param propertyValue Initial property value.
* @param finalValue TRUE if the property should be set as static.
* @param quotable TRUE if the property could contain quotes.
* @param escapable TRUE if the propertyValue can be escaped if its propertyName
* is in the list set with setEscapableProperties().
* @param internal TRUE if the property is a Wrapper internal property.
*
* @return The newly created Property, or NULL if there was a reported error.
*/
Property* addProperty(Properties *properties, const TCHAR* filename, int lineNum, const TCHAR *propertyName, const TCHAR *propertyValue, int finalValue, int quotable, int escapable, int internal) {
int setValue;
Property *property;
TCHAR *oldVal;
TCHAR *propertyNameTrim;
TCHAR *propertyValueTrim;
TCHAR *propertyExpandedValue;
#ifdef _DEBUG
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT("addProperty(properties, %s, '%s', '%s', %d, %d, %d, %d)"),
(filename ? filename : TEXT("")), propertyName, propertyValue, finalValue, quotable, escapable, internal);
#endif
/* It is possible that the propertyName and or properyValue contains extra spaces. */
propertyNameTrim = malloc(sizeof(TCHAR) * (_tcslen(propertyName) + 1));
if (!propertyNameTrim) {
outOfMemory(TEXT("AP"), 1);
return NULL;
}
trim(propertyName, propertyNameTrim);
propertyValueTrim = malloc(sizeof(TCHAR) * ( _tcslen(propertyValue) + 1));
if (!propertyValueTrim) {
outOfMemory(TEXT("AP"), 4);
free(propertyNameTrim);
return NULL;
}
trim(propertyValue, propertyValueTrim);
#ifdef _DEBUG
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT(" trimmed name='%s', value='%s'"),
propertyNameTrim, propertyValueTrim);
#endif
/* See if the property already exists */
setValue = TRUE;
property = getInnerProperty(properties, propertyNameTrim, FALSE);
if (property == NULL) {
/* This is a new property */
property = createInnerProperty();
if (!property) {
free(propertyNameTrim);
free(propertyValueTrim);
return NULL;
}
/* Store a copy of the name */
property->name = malloc(sizeof(TCHAR) * (_tcslen(propertyNameTrim) + 1));
if (!property->name) {
outOfMemory(TEXT("AP"), 3);
disposeInnerProperty(property);
free(propertyNameTrim);
free(propertyValueTrim);
return NULL;
}
_tcsncpy(property->name, propertyNameTrim, _tcslen(propertyNameTrim) + 1);
/* Insert this property at the correct location. Value will still be null. */
insertInnerProperty(properties, property);
} else {
/* The property was already set. Only change it if non final */
if (property->internal) {
setValue = FALSE;
if (properties->debugProperties) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS,
TEXT("The \"%s\" property is defined by the Wrapper internally and can not be overwritten.\n Ignoring redefinition on line #%d of configuration file: %s\n Fixed Value %s=%s\n Ignored Value %s=%s"),
propertyNameTrim, lineNum, (filename ? filename : TEXT("")), propertyNameTrim, property->value, propertyNameTrim, propertyValueTrim);
}
} else if (property->finalValue) {
setValue = FALSE;
if (properties->debugProperties) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS,
TEXT("The \"%s\" property was defined on the Wrapper command line and can not be overwritten.\n Ignoring redefinition on line #%d of configuration file: %s\n Fixed Value %s=%s\n Ignored Value %s=%s"),
propertyNameTrim, lineNum, (filename ? filename : TEXT("")), propertyNameTrim, property->value, propertyNameTrim, propertyValueTrim);
}
} else {
if (properties->debugProperties) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS,
TEXT("The \"%s\" property was redefined on line #%d of configuration file: %s\n Old Value %s=%s\n New Value %s=%s"),
propertyNameTrim, lineNum, (filename ? filename : TEXT("")), propertyNameTrim, property->value, propertyNameTrim, propertyValueTrim);
}
}
}
free(propertyNameTrim);
if (setValue) {
if (escapable && isEscapedProperty(property->name)) {
/* Expand the value. */
#ifdef _DEBUG
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT("expanding value of %s"), property->name);
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT(" value : %s"), propertyValueTrim);
#endif
propertyExpandedValue = expandEscapedCharacters(propertyValueTrim);
if (!propertyExpandedValue) {
free(propertyValueTrim);
return NULL;
}
#ifdef _DEBUG
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT(" expanded: %s"), propertyExpandedValue);
#endif
/* Set the property value. */
setInnerProperty(properties, property, propertyExpandedValue, FALSE);
free(propertyExpandedValue);
} else {
/* Set the property value. */
setInnerProperty(properties, property, propertyValueTrim, FALSE);
}
if (property->value == NULL) {
return NULL;
}
/* Store the final flag */
property->finalValue = finalValue;
/* Store the quotable flag. */
property->quotable = quotable;
/* Store the internal flab. */
property->internal = internal;
/* Prepare the property by expanding any environment variables that are defined. */
prepareProperty(properties, property, FALSE);
/* See if this is a special property */
if ((_tcslen(property->name) > 12) && (_tcsstr(property->name, TEXT("set.default.")) == property->name)) {
/* This property is an environment variable definition that should only
* be set if the environment variable does not already exist. Get the
* value back out of the property as it may have had environment
* replacements. */
oldVal = _tgetenv(property->name + 12);
if (oldVal == NULL) {
#ifdef _DEBUG
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT("set default env('%s', '%s')"),
property->name + 12, property->value);
#endif
setEnv(property->name + 12, property->value, (internal ? ENV_SOURCE_WRAPPER : ENV_SOURCE_CONFIG));
} else {
#ifdef _DEBUG
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT(
"not setting default env('%s', '%s'), already set to '%s'"),
property->name + 12, property->value, oldVal);
#endif
#if !defined(WIN32) && defined(UNICODE)
free(oldVal);
#endif
}
} else if ((_tcslen(property->name) > 4) && (_tcsstr(property->name, TEXT("set.")) == property->name)) {
/* This property is an environment variable definition. Get the
* value back out of the property as it may have had environment
* replacements. */
#ifdef _DEBUG
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT("set env('%s', '%s')"),
property->name + 4, property->value);
#endif
setEnv(property->name + 4, property->value, (internal ? ENV_SOURCE_WRAPPER : ENV_SOURCE_CONFIG));
}
}
free(propertyValueTrim);
return property;
}
/**
* Takes a name/value pair in the form = and attempts to add
* it to the specified properties table.
*
* @param properties Properties structure to add to.
* @param filename Name of the file from which the property was loaded. NULL, if not from a file.
* @param lineNum Line number of the property declaration in the file. Ignored if filename is NULL.
* @param propertyNameValue The "name=value" pair to create the property from.
* @param finalValue TRUE if the property should be set as static.
* @param quotable TRUE if the property could contain quotes.
* @param internal TRUE if the property is a Wrapper internal property.
*
* Returns 0 if successful, otherwise 1
*/
int addPropertyPair(Properties *properties, const TCHAR* filename, int lineNum, const TCHAR *propertyNameValue, int finalValue, int quotable, int internal) {
TCHAR buffer[MAX_PROPERTY_NAME_VALUE_LENGTH];
TCHAR *d;
/* Make a copy of the pair that we can edit */
if (_tcslen(propertyNameValue) + 1 >= MAX_PROPERTY_NAME_VALUE_LENGTH) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_FATAL,
TEXT("The following property name value pair is too large. Need to increase the internal buffer size: %s"), propertyNameValue);
return 1;
}
_tcsncpy(buffer, propertyNameValue, MAX_PROPERTY_NAME_VALUE_LENGTH);
/* Locate the first '=' in the pair */
if ((d = _tcschr(buffer, TEXT('='))) != NULL) {
/* Null terminate the first half of the line. */
*d = TEXT('\0');
d++;
if (addProperty(properties, filename, lineNum, buffer, d, finalValue, quotable, FALSE, internal) != NULL) {
return 0;
} else {
return 1;
}
} else {
return 1;
}
}
const TCHAR* getStringProperty(Properties *properties, const TCHAR *propertyName, const TCHAR *defaultValue) {
Property *property;
property = getInnerProperty(properties, propertyName, TRUE);
if (property == NULL) {
if (defaultValue != NULL) {
property = addProperty(properties, NULL, 0, propertyName, defaultValue, FALSE, FALSE, FALSE, FALSE);
if (property) {
return property->value;
} else {
/* We failed to add the property, but still return the default. */
return defaultValue;
}
} else {
return NULL;
}
} else {
return property->value;
}
}
const TCHAR* getFileSafeStringProperty(Properties *properties, const TCHAR *propertyName, const TCHAR *defaultValue) {
Property *property;
TCHAR *buffer;
int i;
property = getInnerProperty(properties, propertyName, TRUE);
if (property == NULL) {
if (defaultValue != NULL) {
addProperty(properties, NULL, 0, propertyName, defaultValue, FALSE, FALSE, FALSE, FALSE);
}
return defaultValue;
} else {
buffer = property->value;
if (_tcschr(buffer, TEXT('%'))) {
i = 0;
while (buffer[i]) {
if (buffer[i] == TEXT('%')) {
buffer[i] = TEXT('_');
}
i++;
}
}
return buffer;
}
}
/**
* Does a quick sort of the property values, keeping the values together.
*/
void sortStringProperties(long unsigned int *propertyIndices, TCHAR **propertyNames, TCHAR **propertyValues, int low, int high) {
int i = low;
int j = high;
long int tempIndex;
TCHAR *tempName;
TCHAR *tempValue;
long unsigned int x = propertyIndices[(low + high) / 2];
do {
while (propertyIndices[i] < x) {
i++;
}
while (propertyIndices[j] > x) {
j--;
}
if (i <= j) {
/* Swap i and j values. */
tempIndex = propertyIndices[i];
tempName = propertyNames[i];
tempValue = propertyValues[i];
propertyIndices[i] = propertyIndices[j];
propertyNames[i] = propertyNames[j];
propertyValues[i] = propertyValues[j];
propertyIndices[j] = tempIndex;
propertyNames[j] = tempName;
propertyValues[j] = tempValue;
i++;
j--;
}
} while (i <= j);
/* Recurse */
if (low < j) {
sortStringProperties(propertyIndices, propertyNames, propertyValues, low, j);
}
if (i < high) {
sortStringProperties(propertyIndices, propertyNames, propertyValues, i, high);
}
}
/**
* Returns a sorted array of all properties beginning with {propertyNameBase}.
* Only numerical characters can be returned between the two.
*
* The calling code must always call freeStringProperties to make sure that the
* malloced propertyNames, propertyValues, and propertyIndices arrays are freed
* up correctly. This is only necessary if the function returns 0.
*
* @param properties The full properties structure.
* @param propertyNameHead All matching properties must begin with this value.
* @param propertyNameTail All matching properties must end with this value.
* @param all If FALSE then the array will start with #1 and loop up until the
* next property is not found, if TRUE then all properties will be
* returned, even if there are gaps in the series.
* @param matchAny If FALSE only numbers are allowed as placeholder
* @param propertyNames Returns a pointer to a NULL terminated array of
* property names.
* @param propertyValues Returns a pointer to a NULL terminated array of
* property values.
* @param propertyIndices Returns a pointer to a 0 terminated array of
* the index numbers used in each property name of
* the propertyNames array.
*
* @return 0 if successful, -1 if there was an error.
*/
int getStringProperties(Properties *properties, const TCHAR *propertyNameHead, const TCHAR *propertyNameTail, int all, int matchAny, TCHAR ***propertyNames, TCHAR ***propertyValues, long unsigned int **propertyIndices) {
int j;
int k;
size_t headLen;
size_t tailLen;
size_t thisLen;
TCHAR *thisHead;
TCHAR *thisTail;
size_t i;
Property *property;
size_t indexLen;
TCHAR indexS[11];
int ok;
TCHAR c;
int count;
*propertyIndices = NULL;
headLen = _tcslen(propertyNameHead);
tailLen = _tcslen(propertyNameTail);
for (j = 0; j < 2; j++) {
count = 0;
property = properties->first;
while (property != NULL) {
thisLen = _tcslen(property->name);
if (matchAny && thisLen < headLen + tailLen - 1) {
/* Too short, not what we are looking for. */
} else if (!matchAny && thisLen < headLen + tailLen + 1) {
/* Too short, not what we are looking for. */
} else {
thisHead = malloc(sizeof(TCHAR) * (headLen + 1));
if (!thisHead) {
outOfMemory(TEXT("GSPS"), 1);
} else {
_tcsncpy(thisHead, property->name, headLen);
thisHead[headLen] = 0;
if (strcmpIgnoreCase(thisHead, propertyNameHead) == 0) {
/* Head matches. */
thisTail = malloc(sizeof(TCHAR) * (tailLen + 1));
if (!thisTail) {
outOfMemory(TEXT("GSPS"), 2);
} else {
_tcsncpy(thisTail, property->name + thisLen - tailLen, tailLen + 1);
if (strcmpIgnoreCase(thisTail, propertyNameTail) == 0) {
/* Tail matches. */
if (matchAny) {
indexLen = thisLen - headLen - tailLen + 1;
} else {
indexLen = thisLen - headLen - tailLen;
}
if (indexLen <= 10) {
_tcsncpy(indexS, property->name + headLen, indexLen);
indexS[indexLen] = 0;
ok = TRUE;
for (i = 0; i < indexLen; i++) {
c = indexS[i];
if (matchAny == FALSE && ((c < '0') || (c > '9'))) {
ok = FALSE;
break;
}
}
if (ok) {
if (*propertyIndices) {
/* We found it. */
prepareProperty(properties, property, FALSE);
(*propertyIndices)[count] = _tcstoul(indexS, NULL, 10);
(*propertyNames)[count] = property->name;
(*propertyValues)[count] = property->value;
}
count++;
}
}
}
free(thisTail);
}
}
free(thisHead);
}
}
/* Keep looking */
property = property->next;
}
if (*propertyIndices == NULL) {
/* First pass */
*propertyNames = malloc(sizeof(TCHAR *) * (count + 1));
if (!(*propertyNames)) {
outOfMemory(TEXT("GSPS"), 3);
*propertyNames = NULL;
*propertyValues = NULL;
*propertyIndices = NULL;
return -1;
}
*propertyValues = malloc(sizeof(TCHAR *) * (count + 1));
if (!(*propertyValues)) {
outOfMemory(TEXT("GSPS"), 4);
free(*propertyNames);
*propertyNames = NULL;
*propertyValues = NULL;
*propertyIndices = NULL;
return -1;
}
*propertyIndices = malloc(sizeof(long unsigned int) * (count + 1));
if (!(*propertyIndices)) {
outOfMemory(TEXT("GSPS"), 5);
free(*propertyNames);
free(*propertyValues);
*propertyNames = NULL;
*propertyValues = NULL;
*propertyIndices = NULL;
return -1;
}
if (count == 0) {
/* The count is 0 so no need to continue through the loop again. */
(*propertyNames)[0] = NULL;
(*propertyValues)[0] = NULL;
(*propertyIndices)[0] = 0;
return 0;
}
} else {
/* Second pass */
(*propertyNames)[count] = NULL;
(*propertyValues)[count] = NULL;
(*propertyIndices)[count] = 0;
sortStringProperties(*propertyIndices, *propertyNames, *propertyValues, 0, count - 1);
/* If we don't want all of the properties then we need to remove the extra ones.
* Names and values are not allocated, so setting them to NULL is fine.*/
if (!all) {
for (k = 0; k < count; k++) {
if ((*propertyIndices)[k] != k + 1) {
(*propertyNames)[k] = NULL;
(*propertyValues)[k] = NULL;
(*propertyIndices)[k] = 0;
}
}
}
/*
for (k = 0; k < count; k++) {
if ((*propertyNames)[k]) {
_tprintf("[%d] #%lu: %s=%s\n", k, (*propertyIndices)[k], (*propertyNames)[k], (*propertyValues)[k]);
}
}
*/
return 0;
}
}
/* For compiler */
return 0;
}
/**
* Frees up an array of properties previously returned by getStringProperties().
*/
void freeStringProperties(TCHAR **propertyNames, TCHAR **propertyValues, long unsigned int *propertyIndices) {
/* The property names are not malloced. */
free(propertyNames);
/* The property values are not malloced. */
free(propertyValues);
free(propertyIndices);
}
int getIntProperty(Properties *properties, const TCHAR *propertyName, int defaultValue) {
TCHAR buffer[16];
Property *property;
int i;
TCHAR c;
int value;
property = getInnerProperty(properties, propertyName, TRUE);
if (property == NULL) {
_sntprintf(buffer, 16, TEXT("%d"), defaultValue);
addProperty(properties, NULL, 0, propertyName, buffer, FALSE, FALSE, FALSE, FALSE);
return defaultValue;
} else {
value = (int)_tcstol(property->value, NULL, 0);
/* Make sure that the property does not contain invalid characters. */
i = 0;
do {
c = property->value[i];
if ((i > 0) && (c == TEXT('\0'))) {
/* Fall through */
} else if ((i == 0) && (c == TEXT('-'))) {
/* Negative number. This is Ok. */
} else if ((c < TEXT('0')) || (c > TEXT('9'))) {
if (i == 0) {
/* If the bad character is the first character then use the default value. */
value = defaultValue;
}
if (properties->logWarnings) {
log_printf(WRAPPER_SOURCE_WRAPPER, properties->logWarningLogLevel,
TEXT("Encountered an invalid numerical value for configuration property %s=%s. Resolving to %d."),
propertyName, property->value, value);
}
break;
}
i++;
} while (c != TEXT('\0'));
return value;
}
}
int getBooleanProperty(Properties *properties, const TCHAR *propertyName, int defaultValue) {
const TCHAR *defaultValueS;
Property *property;
const TCHAR *propertyValue;
if (defaultValue) {
defaultValueS = TEXT("true");
} else {
defaultValueS = TEXT("false");
}
property = getInnerProperty(properties, propertyName, TRUE);
if (property == NULL) {
propertyValue = defaultValueS;
} else {
propertyValue = property->value;
}
if (strcmpIgnoreCase(propertyValue, TEXT("true")) == 0) {
return TRUE;
} else if (strcmpIgnoreCase(propertyValue, TEXT("false")) == 0) {
return FALSE;
} else {
if (properties->logWarnings) {
log_printf(WRAPPER_SOURCE_WRAPPER, properties->logWarningLogLevel,
TEXT("Encountered an invalid boolean value for configuration property %s=%s. Resolving to %s."),
propertyName, propertyValue, TEXT("FALSE"));
}
return FALSE;
}
}
int isQuotableProperty(Properties *properties, const TCHAR *propertyName) {
Property *property;
property = getInnerProperty(properties, propertyName, FALSE);
if (property == NULL) {
return FALSE;
} else {
return property->quotable;
}
}
void dumpProperties(Properties *properties) {
Property *property;
property = properties->first;
while (property != NULL) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT(" name:%s value:%s"), property->name, property->value);
property = property->next;
}
}
/**
* Set to TRUE if warnings about property values should be logged.
*/
void setLogPropertyWarnings(Properties *properties, int logWarnings) {
properties->logWarnings = logWarnings;
}
/**
* Level at which any property warnings are logged.
*/
void setLogPropertyWarningLogLevel(Properties *properties, int logLevel) {
properties->logWarningLogLevel = logLevel;
}
/**
* Returns the minimum value. This is used in place of the __min macro when the parameters should not be called more than once.
*/
int propIntMin(int value1, int value2) {
if (value1 < value2) {
return value1;
} else {
return value2;
}
}
/**
* Returns the maximum value. This is used in place of the __max macro when the parameters should not be called more than once.
*/
int propIntMax(int value1, int value2) {
if (value1 > value2) {
return value1;
} else {
return value2;
}
}
/** Creates a linearized representation of all of the properties.
* The returned buffer must be freed by the calling code. */
TCHAR *linearizeProperties(Properties *properties, TCHAR separator) {
Property *property;
size_t size;
TCHAR *c;
TCHAR *fullBuffer;
TCHAR *work, *buffer;
/* First we need to figure out how large a buffer will be needed to linearize the properties. */
size = 0;
property = properties->first;
while (property != NULL) {
/* Add the length of the basic property. */
size += _tcslen(property->name);
size++; /* '=' */
size += _tcslen(property->value);
/* Handle any characters that will need to be escaped. */
c = property->name;
while ((c = _tcschr(c, separator)) != NULL) {
size++;
c++;
}
c = property->value;
while ((c = _tcschr(c, separator)) != NULL) {
size++;
c++;
}
size++; /* separator */
property = property->next;
}
size++; /* null terminated. */
/* Now that we know how much space this will all take up, allocate a buffer. */
fullBuffer = buffer = calloc(sizeof(TCHAR) , size);
if (!fullBuffer) {
outOfMemory(TEXT("LP"), 1);
return NULL;
}
/* Now actually build up the output. Any separator characters need to be escaped with themselves. */
property = properties->first;
while (property != NULL) {
/* name */
work = property->name;
while ((c = _tcschr(work, separator)) != NULL) {
_tcsncpy(buffer, work, c - work + 1);
buffer += c - work + 1;
buffer[0] = separator;
buffer++;
work = c + 1;
}
_tcsncpy(buffer, work, size - _tcslen(fullBuffer));
buffer += _tcslen(work);
/* equals */
buffer[0] = TEXT('=');
buffer++;
/* value */
work = property->value;
while ((c = _tcschr(work, separator)) != NULL) {
_tcsncpy(buffer, work, c - work + 1);
buffer += c - work + 1;
buffer[0] = separator;
buffer++;
work = c + 1;
}
_tcsncpy(buffer, work, size - _tcslen(fullBuffer));
buffer += _tcslen(work);
/* separator */
buffer[0] = separator;
buffer++;
property = property->next;
}
/* null terminate. */
buffer[0] = 0;
buffer++;
return fullBuffer;
}
wrapper_3.5.22_src/src/c/property.h 100644 0 0 25363 12224722016 14440 0 ustar 0 0 /*
* Copyright (c) 1999, 2013 Tanuki Software, Ltd.
* http://www.tanukisoftware.com
* All rights reserved.
*
* This software is the proprietary information of Tanuki Software.
* You shall use it only in accordance with the terms of the
* license agreement you entered into with Tanuki Software.
* http://wrapper.tanukisoftware.com/doc/english/licenseOverview.html
*
*
* Portions of the Software have been derived from source code
* developed by Silver Egg Technology under the following license:
*
* Copyright (c) 2001 Silver Egg Technology
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sub-license, and/or
* sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*/
#ifndef _PROPERTY_H
#define _PROPERTY_H
#include "wrapper_hashmap.h"
#ifndef TRUE
#define TRUE -1
#endif
#ifndef FALSE
#define FALSE 0
#endif
/* This defines the largest environment variable that we are able
* to work with. It can be expanded if needed. */
#define MAX_PROPERTY_NAME_LENGTH 512
#define MAX_PROPERTY_VALUE_LENGTH 16384
#define MAX_PROPERTY_NAME_VALUE_LENGTH MAX_PROPERTY_NAME_LENGTH + 1 + MAX_PROPERTY_VALUE_LENGTH
#define ENV_SOURCE_PARENT 1
#define ENV_SOURCE_WRAPPER 2
#define ENV_SOURCE_CONFIG 4
#ifdef WIN32
#define ENV_SOURCE_REG_SYSTEM 8
#define ENV_SOURCE_REG_ACCOUNT 16
#endif
typedef struct EnvSrc EnvSrc;
struct EnvSrc {
int source; /* Source of the variable. */
TCHAR* name; /* Name of the environment variable. */
EnvSrc *next; /* Next variable in the chain. */
};
extern EnvSrc *baseEnvSrc;
typedef struct Property Property;
struct Property {
TCHAR *name; /* The name of the property. */
TCHAR *value; /* The value of the property. */
int finalValue; /* TRUE if the Property can not be changed. */
int quotable; /* TRUE if quotes can be optionally added around the value. */
int internal; /* TRUE if the Property is internal. */
Property *next; /* Pointer to the next Property in a linked list */
Property *previous; /* Pointer to the next Property in a linked list */
};
typedef struct Properties Properties;
struct Properties {
int debugProperties; /* TRUE if debug information on Properties should be shown. */
int logWarnings; /* Flag that controls whether or not warnings will be logged. */
int logWarningLogLevel; /* Log level at which any log warnings will be logged. */
Property *first; /* Pointer to the first property. */
Property *last; /* Pointer to the last property. */
PHashMap warnedVarMap; /* Map of undefined environment variables for which the user was warned. */
};
/**
* Sets an environment variable with the specified value.
* The function will only set the variable if its value is changed, but if
* it does, the call will result in a memory leak the size of the string:
* "name=value".
*
* @param name Name of the variable being set.
* @param value Value to be set, NULL to clear it.
* @param source Where the variable came from. If value is WRAPPER_ENV_SOURCE_PARENT
* then the value may be NULL and will never be set to the environment.
*
* Return TRUE if there were any problems, FALSE otherwise.
*/
extern int setEnv(const TCHAR *name, const TCHAR *value, int source);
/**
* Create a Properties structure loaded in from the specified file.
* Must call disposeProperties to free up allocated memory.
*
* @param properties Properties structure to load into.
* @param filename File to load the properties from.
* @param preload TRUE if this is a preload call that should have supressed error output.
*
* @return TRUE if there were any problems, FALSE if successful.
*/
extern int loadProperties(Properties *properties, const TCHAR* filename, int preload);
/**
* Create a Properties structure. Must call disposeProperties to free up
* allocated memory.
*/
extern Properties* createProperties();
/**
* Free all memory allocated by a Properties structure. The properties
* pointer will no longer be valid.
*/
extern void disposeProperties(Properties *properties);
/**
* Free all memory allocated by a Properties structure. The properties
* pointer will no longer be valid.
*/
extern void disposeEnvironment();
/**
* Remove a single Property from a Properties. All associated memory is
* freed up.
*/
extern void removeProperty(Properties *properties, const TCHAR *propertyName);
/**
* Used to set a NULL terminated list of property names whose values should be
* escaped when read in from a file. '\\' will become '\' and '\n' will
* become '^J', all other characters following '\' will be left as is.
*
* @param propertyNames NULL terminated list of property names. Property names
* can contain a single '*' wildcard which will match 0 or
* more characters.
*/
extern void setEscapedProperties(const TCHAR **propertyNames);
/**
* Returns true if the specified property matches one of the property names
* previosly set in a call to setEscapableProperties()
*
* @param propertyName Property name to test.
*
* @return TRUE if the property should be escaped. FALSE otherwise.
*/
extern int isEscapedProperty(const TCHAR *propertyName);
/**
* Adds a single property to the properties structure.
*
* @param properties Properties structure to add to.
* @param filename Name of the file from which the property was loaded. NULL, if not from a file.
* @param lineNum Line number of the property declaration in the file. Ignored if filename is NULL.
* @param propertyName Name of the new Property.
* @param propertyValue Initial property value.
* @param finalValue TRUE if the property should be set as static.
* @param quotable TRUE if the property could contain quotes.
* @param escapable TRUE if the propertyValue can be escaped if its propertyName
* is in the list set with setEscapableProperties().
* @param internal TRUE if the property is a Wrapper internal property.
*
* @return The newly created Property, or NULL if there was a reported error.
*/
extern Property* addProperty(Properties *properties, const TCHAR* filename, int lineNum, const TCHAR *propertyName, const TCHAR *propertyValue, int finalValue, int quotable, int escapable, int internal);
/**
* Takes a name/value pair in the form = and attempts to add
* it to the specified properties table.
*
* @param properties Properties structure to add to.
* @param filename Name of the file from which the property was loaded. NULL, if not from a file.
* @param lineNum Line number of the property declaration in the file. Ignored if filename is NULL.
* @param propertyNameValue The "name=value" pair to create the property from.
* @param finalValue TRUE if the property should be set as static.
* @param quotable TRUE if the property could contain quotes.
* @param internal TRUE if the property is a Wrapper internal property.
*
* Returns 0 if successful, otherwise 1
*/
extern int addPropertyPair(Properties *properties, const TCHAR* filename, int lineNum, const TCHAR *propertyNameValue, int finalValue, int quotable, int internal);
extern const TCHAR* getStringProperty(Properties *properties, const TCHAR *propertyName, const TCHAR *defaultValue);
extern const TCHAR* getFileSafeStringProperty(Properties *properties, const TCHAR *propertyName, const TCHAR *defaultValue);
/**
* Returns a sorted array of all properties beginning with {propertyNameBase}.
* Only numerical characters can be returned between the two.
*
* The calling code must always call freeStringProperties to make sure that the
* malloced propertyNames, propertyValues, and propertyIndices arrays are freed
* up correctly. This is only necessary if the function returns 0.
*
* @param properties The full properties structure.
* @param propertyNameHead All matching properties must begin with this value.
* @param propertyNameTail All matching properties must end with this value.
* @param all If FALSE then the array will start with #1 and loop up until the
* next property is not found, if TRUE then all properties will be
* returned, even if there are gaps in the series.
* @param matchAny If FALSE only numbers are allowed as placeholder
* @param propertyNames Returns a pointer to a NULL terminated array of
* property names.
* @param propertyValues Returns a pointer to a NULL terminated array of
* property values.
* @param propertyIndices Returns a pointer to a 0 terminated array of
* the index numbers used in each property name of
* the propertyNames array.
*
* @return 0 if successful, -1 if there was an error.
*/
extern int getStringProperties(Properties *properties, const TCHAR *propertyNameHead, const TCHAR *propertyNameTail, int all, int matchAny, TCHAR ***propertyNames, TCHAR ***propertyValues, long unsigned int **propertyIndices);
/**
* Frees up an array of properties previously returned by getStringProperties().
*/
extern void freeStringProperties(TCHAR **propertyNames, TCHAR **propertyValues, long unsigned int *propertyIndices);
extern int getIntProperty(Properties *properties, const TCHAR *propertyName, int defaultValue);
extern int getBooleanProperty(Properties *properties, const TCHAR *propertyName, int defaultValue);
extern int isQuotableProperty(Properties *properties, const TCHAR *propertyName);
extern void dumpProperties(Properties *properties);
/**
* Set to TRUE if warnings about property values should be logged.
*/
extern void setLogPropertyWarnings(Properties *properties, int logWarnings);
/**
* Level at which any property warnings are logged.
*/
extern void setLogPropertyWarningLogLevel(Properties *properties, int logLevel);
/**
* Returns the minimum value. This is used in place of the __min macro when the parameters should not be called more than once.
*/
extern int propIntMin(int value1, int value2);
/**
* Returns the maximum value. This is used in place of the __max macro when the parameters should not be called more than once.
*/
extern int propIntMax(int value1, int value2);
/** Creates a linearized representation of all of the properties.
* The returned buffer must be freed by the calling code. */
extern TCHAR *linearizeProperties(Properties *properties, TCHAR separator);
#endif
wrapper_3.5.22_src/src/c/psapi.h 100644 0 0 7517 12224722016 13651 0 ustar 0 0 /*++ BUILD Version: 0001 // Increment this if a change has global effects
Copyright (c) 1994 Microsoft Corporation
Module Name:
psapi.h
Abstract:
Include file for APIs provided by PSAPI.DLL
Author:
Richard Shupak [richards] 06-Jan-1994
Revision History:
--*/
#ifndef _PSAPI_H_
#define _PSAPI_H_
#ifdef __cplusplus
extern "C" {
#endif
BOOL
WINAPI
EnumProcesses(
DWORD * lpidProcess,
DWORD cb,
DWORD * cbNeeded
);
BOOL
WINAPI
EnumProcessModules(
HANDLE hProcess,
HMODULE *lphModule,
DWORD cb,
LPDWORD lpcbNeeded
);
DWORD
WINAPI
GetModuleBaseNameA(
HANDLE hProcess,
HMODULE hModule,
LPSTR lpBaseName,
DWORD nSize
);
DWORD
WINAPI
GetModuleBaseNameW(
HANDLE hProcess,
HMODULE hModule,
LPWSTR lpBaseName,
DWORD nSize
);
#ifdef UNICODE
#define GetModuleBaseName GetModuleBaseNameW
#else
#define GetModuleBaseName GetModuleBaseNameA
#endif // !UNICODE
DWORD
WINAPI
GetModuleFileNameExA(
HANDLE hProcess,
HMODULE hModule,
LPSTR lpFilename,
DWORD nSize
);
DWORD
WINAPI
GetModuleFileNameExW(
HANDLE hProcess,
HMODULE hModule,
LPWSTR lpFilename,
DWORD nSize
);
#ifdef UNICODE
#define GetModuleFileNameEx GetModuleFileNameExW
#else
#define GetModuleFileNameEx GetModuleFileNameExA
#endif // !UNICODE
typedef struct _MODULEINFO {
LPVOID lpBaseOfDll;
DWORD SizeOfImage;
LPVOID EntryPoint;
} MODULEINFO, *LPMODULEINFO;
BOOL
WINAPI
GetModuleInformation(
HANDLE hProcess,
HMODULE hModule,
LPMODULEINFO lpmodinfo,
DWORD cb
);
BOOL
WINAPI
EmptyWorkingSet(
HANDLE hProcess
);
BOOL
WINAPI
QueryWorkingSet(
HANDLE hProcess,
PVOID pv,
DWORD cb
);
BOOL
WINAPI
InitializeProcessForWsWatch(
HANDLE hProcess
);
typedef struct _PSAPI_WS_WATCH_INFORMATION {
LPVOID FaultingPc;
LPVOID FaultingVa;
} PSAPI_WS_WATCH_INFORMATION, *PPSAPI_WS_WATCH_INFORMATION;
BOOL
WINAPI
GetWsChanges(
HANDLE hProcess,
PPSAPI_WS_WATCH_INFORMATION lpWatchInfo,
DWORD cb
);
DWORD
WINAPI
GetMappedFileNameW(
HANDLE hProcess,
LPVOID lpv,
LPWSTR lpFilename,
DWORD nSize
);
DWORD
WINAPI
GetMappedFileNameA(
HANDLE hProcess,
LPVOID lpv,
LPSTR lpFilename,
DWORD nSize
);
#ifdef UNICODE
#define GetMappedFilenameEx GetMappedFilenameExW
#else
#define GetMappedFilenameEx GetMappedFilenameExA
#endif // !UNICODE
BOOL
WINAPI
EnumDeviceDrivers(
LPVOID *lpImageBase,
DWORD cb,
LPDWORD lpcbNeeded
);
DWORD
WINAPI
GetDeviceDriverBaseNameA(
LPVOID ImageBase,
LPSTR lpBaseName,
DWORD nSize
);
DWORD
WINAPI
GetDeviceDriverBaseNameW(
LPVOID ImageBase,
LPWSTR lpBaseName,
DWORD nSize
);
#ifdef UNICODE
#define GetDeviceDriverBaseName GetDeviceDriverBaseNameW
#else
#define GetDeviceDriverBaseName GetDeviceDriverBaseNameA
#endif // !UNICODE
DWORD
WINAPI
GetDeviceDriverFileNameA(
LPVOID ImageBase,
LPSTR lpFilename,
DWORD nSize
);
DWORD
WINAPI
GetDeviceDriverFileNameW(
LPVOID ImageBase,
LPWSTR lpFilename,
DWORD nSize
);
#ifdef UNICODE
#define GetDeviceDriverFileName GetDeviceDriverFileNameW
#else
#define GetDeviceDriverFileName GetDeviceDriverFileNameA
#endif // !UNICODE
// Structure for GetProcessMemoryInfo()
typedef struct _PROCESS_MEMORY_COUNTERS {
DWORD cb;
DWORD PageFaultCount;
DWORD PeakWorkingSetSize;
DWORD WorkingSetSize;
DWORD QuotaPeakPagedPoolUsage;
DWORD QuotaPagedPoolUsage;
DWORD QuotaPeakNonPagedPoolUsage;
DWORD QuotaNonPagedPoolUsage;
DWORD PagefileUsage;
DWORD PeakPagefileUsage;
} PROCESS_MEMORY_COUNTERS;
typedef PROCESS_MEMORY_COUNTERS *PPROCESS_MEMORY_COUNTERS;
BOOL
WINAPI
GetProcessMemoryInfo(
HANDLE Process,
PPROCESS_MEMORY_COUNTERS ppsmemCounters,
DWORD cb
);
#ifdef __cplusplus
}
#endif
#endif
wrapper_3.5.22_src/src/c/resource.h 100644 0 0 667 12224722016 14343 0 ustar 0 0 //{{NO_DEPENDENCIES}}
// Microsoft Developer Studio generated include file.
// Used by Wrapper.rc
//
#define IDI_WRAPPER 102
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 106
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1002
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
wrapper_3.5.22_src/src/c/runnmake.bat 100644 0 0 774 12224722010 14644 0 ustar 0 0 @echo off
setlocal
rem Copyright (c) 1999, 2013 Tanuki Software Inc.
rem
rem Java Service Wrapper windows build script. This script is designed to be
rem called by the ant build.xml file.
rem
rem %1 Makefile name
rem %2 Visual Studio environment script
rem %3 script argument
rem %4 script argument
rem %5 script argument
echo Configuring the Visual Studio environment...
echo call %2 %3 %4 %5
call %2 %3 %4 %5
echo Run the make file...
echo nmake /f %1 /c all
nmake /f %1 /c all
wrapper_3.5.22_src/src/c/test.c 100644 0 0 23306 12224722016 13521 0 ustar 0 0 /*
* Copyright (c) 1999, 2013 Tanuki Software, Ltd.
* http://www.tanukisoftware.com
* All rights reserved.
*
* This software is the proprietary information of Tanuki Software.
* You shall use it only in accordance with the terms of the
* license agreement you entered into with Tanuki Software.
* http://wrapper.tanukisoftware.com/doc/english/licenseOverview.html
*/
#ifdef CUNIT
#include
#include
#include
#include "CUnit/Basic.h"
#include "logger.h"
#include "wrapper_i18n.h"
#include "wrapper.h"
/**
* The suite initialization function.
* Opens the temporary file used by the tests.
* Returns zero on success, non-zero otherwise.
*/
int init_suite1(void) {
return 0;
}
/**
* The suite cleanup function.
* Closes the temporary file used by the tests.
* Returns zero on success, non-zero otherwise.
*/
int clean_suite1(void) {
return 0;
}
void dummyLogFileChanged(const TCHAR *logFile) {
}
int init_wrapper(void) {
initLogging(dummyLogFileChanged);
logRegisterThread(WRAPPER_THREAD_MAIN);
setLogfileLevelInt(LEVEL_NONE);
setConsoleLogFormat(TEXT("LPM"));
setConsoleLogLevelInt(LEVEL_DEBUG);
setConsoleFlush(TRUE);
setSyslogLevelInt(LEVEL_NONE);
return 0;
}
/**
* Simple test that passes.
*/
void testPass(void) {
CU_ASSERT(0 == 0);
}
/**
* Simple test that passes.
*/
void testFail(void) {
CU_ASSERT(0 == 1);
}
/********************************************************************
* Common Tools
*******************************************************************/
TCHAR *randomChars = TEXT("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-");
#define WORK_BUFFER_LEN 4096
TCHAR workBuffer[WORK_BUFFER_LEN];
int getRandom(int min, int max) {
int num;
int rNum;
num = max + 1 - min;
if (num <= 0) {
return min;
}
/* Some platforms use very large RAND_MAX values that cause overflow problems in our math */
if (RAND_MAX > 0x10000) {
rNum = (int)((rand() >> 8) * num / (RAND_MAX >> 8));
} else {
rNum = (int)(rand() * num / RAND_MAX);
}
return min + rNum;
}
/**
* Creates a string of random characters that is within the specified range of lengths.
* It is the responsibility of the caller to free up the string.
*
* @param minLen Minimum Length of the string.
* @param maxLen Maximum Length of the string.
*
* @return the requested string, or NULL if out of memory.
*/
TCHAR *buildRandomString(int minLen, int maxLen) {
int num;
int len;
TCHAR *str;
int i;
num = _tcslen(randomChars);
len = getRandom(minLen, maxLen);
str = malloc(sizeof(TCHAR) * (len + 1));
if (!str) {
return NULL;
}
for (i = 0; i < len; i++) {
str[i] = randomChars[getRandom(0, num - 1)];
}
str[len] = TEXT('\0');
return str;
}
/**
* Creates a string of random characters that is within the specified range of lengths.
* It is the responsibility of the caller to free up the string.
*
* @param minLen Minimum Length of the string.
* @param maxLen Maximum Length of the string.
*
* @return the requested string, or NULL if out of memory.
*/
TCHAR *buildRandomStrinWithTail(int minLen, int maxLen, int tail) {
int num;
size_t len;
size_t strLen;
TCHAR *str;
size_t i;
TCHAR tailStr[32];
_sntprintf(tailStr, 32, TEXT("-%d"), tail);
num = _tcslen(randomChars);
len = getRandom(minLen, maxLen);
strLen = len + _tcslen(tailStr) + 1;
str = malloc(sizeof(TCHAR) * strLen);
if (!str) {
return NULL;
}
for (i = 0; i < len; i++) {
str[i] = randomChars[getRandom(0, num - 1)];
}
str[len] = TEXT('\0');
_tcsncat(str, tailStr, strLen);
return str;
}
/**
* Frees up an array and its contents. Depends on the values being NULL if they are not allocated.
*
* @param array Array to be freed.
*/
void freeTCHARArray(TCHAR **array, int len) {
int i;
if (array) {
for (i = 0; i < len; i++) {
if (array[i]) {
free(array[i]);
}
}
free(array);
}
}
/********************************************************************
* Filter Tests
*******************************************************************/
void subTestWrapperWildcardMatch(const TCHAR *pattern, const TCHAR *text, size_t expectedMinLen, int expectedMatch) {
size_t minLen;
int matched;
minLen = wrapperGetMinimumTextLengthForPattern(pattern);
if (minLen != expectedMinLen) {
_sntprintf(workBuffer, WORK_BUFFER_LEN, TEXT("wrapperGetMinimumTextLengthForPattern(\"%s\") returned %d rather than expected %d."), pattern, minLen, expectedMinLen);
_tprintf(TEXT("%s\n"), workBuffer);
CU_FAIL(workBuffer);
} else {
_sntprintf(workBuffer, WORK_BUFFER_LEN, TEXT("wrapperGetMinimumTextLengthForPattern(\"%s\") returned %d."), pattern, minLen);
CU_PASS(workBuffer);
}
matched = wrapperWildcardMatch(text, pattern, expectedMinLen);
if (matched != expectedMatch) {
_sntprintf(workBuffer, WORK_BUFFER_LEN, TEXT("wrapperWildcardMatch(\"%s\", \"%s\", %d) returned %s rather than expected %s."),
text, pattern, expectedMinLen, (matched ? TEXT("TRUE") : TEXT("FALSE")), (expectedMatch ? TEXT("TRUE") : TEXT("FALSE")));
_tprintf(TEXT("%s\n"), workBuffer);
CU_FAIL(workBuffer);
} else {
_sntprintf(workBuffer, WORK_BUFFER_LEN, TEXT("wrapperWildcardMatch(\"%s\", \"%s\", %d) returned %s."),
text, pattern, expectedMinLen, (matched ? TEXT("TRUE") : TEXT("FALSE")));
CU_PASS(workBuffer);
}
}
void testWrapperWildcardMatch() {
subTestWrapperWildcardMatch(TEXT("a"), TEXT("a"), 1, TRUE);
subTestWrapperWildcardMatch(TEXT("a"), TEXT("b"), 1, FALSE);
subTestWrapperWildcardMatch(TEXT("a"), TEXT(""), 1, FALSE);
subTestWrapperWildcardMatch(TEXT("a"), TEXT("abc"), 1, TRUE);
subTestWrapperWildcardMatch(TEXT("b"), TEXT("abc"), 1, TRUE);
subTestWrapperWildcardMatch(TEXT("c"), TEXT("abc"), 1, TRUE);
subTestWrapperWildcardMatch(TEXT("d"), TEXT("abc"), 1, FALSE);
subTestWrapperWildcardMatch(TEXT("?"), TEXT("a"), 1, TRUE);
subTestWrapperWildcardMatch(TEXT("?"), TEXT(""), 1, FALSE);
subTestWrapperWildcardMatch(TEXT("*"), TEXT(""), 0, TRUE);
subTestWrapperWildcardMatch(TEXT("*"), TEXT("a"), 0, TRUE);
subTestWrapperWildcardMatch(TEXT("*"), TEXT("abc"), 0, TRUE);
subTestWrapperWildcardMatch(TEXT("*a"), TEXT("a"), 1, TRUE);
subTestWrapperWildcardMatch(TEXT("*a"), TEXT("abc"), 1, TRUE);
subTestWrapperWildcardMatch(TEXT("*b"), TEXT("abc"), 1, TRUE);
subTestWrapperWildcardMatch(TEXT("a*"), TEXT("a"), 1, TRUE);
subTestWrapperWildcardMatch(TEXT("a*"), TEXT("abc"), 1, TRUE);
subTestWrapperWildcardMatch(TEXT("b*"), TEXT("abc"), 1, TRUE);
subTestWrapperWildcardMatch(TEXT("*a*"), TEXT("a"), 1, TRUE);
subTestWrapperWildcardMatch(TEXT("*a*"), TEXT("abc"), 1, TRUE);
subTestWrapperWildcardMatch(TEXT("*b*"), TEXT("abc"), 1, TRUE);
subTestWrapperWildcardMatch(TEXT("HEAD*TAIL"), TEXT("This is the HEAD and this is the TAIL....."), 8, TRUE);
subTestWrapperWildcardMatch(TEXT("HEAD**TAIL"), TEXT("This is the HEAD and this is the TAIL....."), 8, TRUE);
subTestWrapperWildcardMatch(TEXT("*HEAD*TAIL*"), TEXT("This is the HEAD and this is the TAIL....."), 8, TRUE);
subTestWrapperWildcardMatch(TEXT("HEAD*TAIL"), TEXT("This is the HEAD and this is the TaIL....."), 8, FALSE);
subTestWrapperWildcardMatch(TEXT("HEAD**TAIL"), TEXT("This is the HEAD and this is the TaIL....."), 8, FALSE);
subTestWrapperWildcardMatch(TEXT("*HEAD*TAIL*"), TEXT("This is the HEAD and this is the TaIL....."), 8, FALSE);
subTestWrapperWildcardMatch(TEXT("HEAD*TA?L"), TEXT("This is the HEAD and this is the TAIL....."), 8, TRUE);
subTestWrapperWildcardMatch(TEXT("HEAD**TA?L"), TEXT("This is the HEAD and this is the TAIL....."), 8, TRUE);
subTestWrapperWildcardMatch(TEXT("*HEAD*TA?L*"), TEXT("This is the HEAD and this is the TAIL....."), 8, TRUE);
}
/* The main() function for setting up and running the tests.
* Returns a CUE_SUCCESS on successful running, another
* CUnit error code on failure.
*/
int main()
{
CU_pSuite pSuite = NULL;
CU_pSuite filterSuite = NULL;
CU_pSuite javaAdditionalParamSuite = NULL;
/* Initialize the random seed. */
srand((unsigned)time(NULL));
/* initialize the CUnit test registry */
if (CUE_SUCCESS != CU_initialize_registry())
return CU_get_error();
/* add a suite to the registry */
pSuite = CU_add_suite("Suite_1", init_suite1, clean_suite1);
if (NULL == pSuite) {
CU_cleanup_registry();
return CU_get_error();
}
filterSuite = CU_add_suite("Filter Suite", init_wrapper, NULL);
if (NULL == filterSuite) {
CU_cleanup_registry();
return CU_get_error();
}
javaAdditionalParamSuite = CU_add_suite("Java Additional Parameter Suite", NULL, NULL);
if (NULL == javaAdditionalParamSuite) {
CU_cleanup_registry();
return CU_get_error();
}
/* add the tests to the suite */
/*
if ((NULL == CU_add_test(pSuite, "test of pass", testPass)) ||
(NULL == CU_add_test(pSuite, "test of fail", testFail)) {
CU_cleanup_registry();
return CU_get_error();
}
*/
CU_add_test(filterSuite, "wrapperWildcardMatch", testWrapperWildcardMatch);
CU_add_test(javaAdditionalParamSuite, "loadJavaAdditionalCallback()", testJavaAdditionalParamSuite);
/* Run all tests using the CUnit Basic interface */
CU_basic_set_mode(CU_BRM_VERBOSE);
CU_basic_run_tests();
CU_cleanup_registry();
return CU_get_error();
}
#endif
wrapper_3.5.22_src/src/c/wrapper.c 100644 0 0 1224204 12224722016 14263 0 ustar 0 0 /*
* Copyright (c) 1999, 2013 Tanuki Software, Ltd.
* http://www.tanukisoftware.com
* All rights reserved.
*
* This software is the proprietary information of Tanuki Software.
* You shall use it only in accordance with the terms of the
* license agreement you entered into with Tanuki Software.
* http://wrapper.tanukisoftware.com/doc/english/licenseOverview.html
*
*
* Portions of the Software have been derived from source code
* developed by Silver Egg Technology under the following license:
*
* Copyright (c) 2001 Silver Egg Technology
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sub-license, and/or
* sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*/
/**
* Author:
* Leif Mortenson
* Ryan Shaw
*/
#include
#include
#include
#include
#include
#include
#include
#ifdef CUNIT
#include "CUnit/Basic.h"
#endif
#include "wrapper_i18n.h"
#include "wrapperinfo.h"
#include "wrapper.h"
#include "logger.h"
#include "wrapper_file.h"
#ifdef WIN32
#include
#include
#include
#include
#include
/* MS Visual Studio 8 went and deprecated the POXIX names for functions.
* Fixing them all would be a big headache for UNIX versions. */
#pragma warning(disable : 4996)
/* Defines for MS Visual Studio 6 */
#ifndef _INTPTR_T_DEFINED
typedef long intptr_t;
#define _INTPTR_T_DEFINED
#endif
#define EADDRINUSE WSAEADDRINUSE
#define EWOULDBLOCK WSAEWOULDBLOCK
#define ENOTSOCK WSAENOTSOCK
#define ECONNRESET WSAECONNRESET
#else /* UNIX */
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define SOCKET int
#define HANDLE int
#define INVALID_HANDLE_VALUE -1
#define INVALID_SOCKET -1
#define SOCKET_ERROR -1
#if defined(SOLARIS)
#include
#include
#elif defined(AIX) || defined(HPUX) || defined(MACOSX) || defined(OSF1)
#elif defined(IRIX)
#define PATH_MAX FILENAME_MAX
#elif defined(FREEBSD)
#include
#include
#else /* LINUX */
#include
#endif
/*
* Mac OSX 10.5 does not define the environ variable. This is work around for that.
*/
#ifdef MACOSX
#include
#define environ *_NSGetEnviron();
#endif
extern char** environ;
#endif /* WIN32 */
WrapperConfig *wrapperData;
TCHAR packetBuffer[MAX_LOG_SIZE + 1];
TCHAR *keyChars = TEXT("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-");
/* Properties structure loaded in from the configuration file. */
Properties *properties;
/* Mutex for syncronization of the tick timer. */
#ifdef WIN32
HANDLE tickMutexHandle = NULL;
#else
pthread_mutex_t tickMutex = PTHREAD_MUTEX_INITIALIZER;
#endif
/* Server Pipe Handles. */
HANDLE protocolActiveServerPipeIn = INVALID_HANDLE_VALUE;
HANDLE protocolActiveServerPipeOut = INVALID_HANDLE_VALUE;
/* Flag for indicating the connected pipes */
int protocolActiveServerPipeConnected = FALSE;
/* Server Socket. */
SOCKET protocolActiveServerSD = INVALID_SOCKET;
/* Client Socket. */
SOCKET protocolActiveBackendSD = INVALID_SOCKET;
int disposed = FALSE;
int loadConfiguration();
#define READ_BUFFER_BLOCK_SIZE 1024
char *wrapperChildWorkBuffer = NULL;
size_t wrapperChildWorkBufferSize = 0;
size_t wrapperChildWorkBufferLen = 0;
time_t wrapperChildWorkLastDataTime = 0;
int wrapperChildWorkLastDataTimeMillis = 0;
/**
* Constructs a tm structure from a pair of Strings like "20091116" and "1514".
* The time returned will be in the local time zone. This is not 100% accurate
* as it doesn't take into account the time zone in which the dates were
* originally set.
*/
struct tm getInfoTime(const TCHAR *date, const TCHAR *time) {
struct tm buildTM;
TCHAR temp[5];
memset(&buildTM, 0, sizeof(struct tm));
/* Year */
_tcsncpy( temp, date, 4 );
temp[4] = 0;
buildTM.tm_year = _ttoi( temp ) - 1900;
/* Month */
_tcsncpy( temp, date + 4, 2 );
temp[2] = 0;
buildTM.tm_mon = _ttoi( temp ) - 1;
/* Day */
_tcsncpy( temp, date + 6, 2 );
temp[2] = 0;
buildTM.tm_mday = _ttoi( temp );
/* Hour */
_tcsncpy( temp, time, 2 );
temp[2] = 0;
buildTM.tm_hour = _ttoi( temp );
/* Minute */
_tcsncpy( temp, time + 2, 2 );
temp[2] = 0;
buildTM.tm_min = _ttoi( temp );
return buildTM;
}
struct tm wrapperGetReleaseTime() {
return getInfoTime(wrapperReleaseDate, wrapperReleaseTime);
}
struct tm wrapperGetBuildTime() {
return getInfoTime(wrapperBuildDate, wrapperBuildTime);
}
/**
* Adds default properties used to set global environment variables.
*
* These are done by setting properties rather than call setEnv directly
* so that it will be impossible for users to override their values by
* creating a "set.XXX=NNN" property in the configuration file.
*/
void wrapperAddDefaultProperties() {
size_t bufferLen;
TCHAR* buffer, *langTemp, *confDirTemp;
#ifdef WIN32
int work, pos2;
TCHAR pathSep = TEXT('\\');
#else
TCHAR pathSep = TEXT('/');
#endif
int pos;
/* IMPORTANT - If any new values are added here, this work buffer length may need to be calculated differently. */
bufferLen = 1;
bufferLen = __max(bufferLen, _tcslen(TEXT("set.WRAPPER_LANG=")) + 3 + 1);
bufferLen = __max(bufferLen, _tcslen(TEXT("set.WRAPPER_PID=")) + 10 + 1); /* 32-bit PID would be max of 10 characters */
bufferLen = __max(bufferLen, _tcslen(TEXT("set.WRAPPER_BITS=")) + _tcslen(wrapperBits) + 1);
bufferLen = __max(bufferLen, _tcslen(TEXT("set.WRAPPER_ARCH=")) + _tcslen(wrapperArch) + 1);
bufferLen = __max(bufferLen, _tcslen(TEXT("set.WRAPPER_OS=")) + _tcslen(wrapperOS) + 1);
bufferLen = __max(bufferLen, _tcslen(TEXT("set.WRAPPER_HOSTNAME=")) + _tcslen(wrapperData->hostName) + 1);
bufferLen = __max(bufferLen, _tcslen(TEXT("set.WRAPPER_HOST_NAME=")) + _tcslen(wrapperData->hostName) + 1);
if (wrapperData->confDir == NULL) {
if (_tcsrchr(wrapperData->argConfFile, pathSep) != NULL) {
pos = (int)(_tcsrchr(wrapperData->argConfFile, pathSep) - wrapperData->argConfFile);
} else {
pos = -1;
}
#ifdef WIN32
if (_tcsrchr(wrapperData->argConfFile, TEXT('/')) != NULL) {
pos2 = (int)(_tcsrchr(wrapperData->argConfFile, TEXT('/')) - wrapperData->argConfFile);
} else {
pos2 = -1;
}
pos = __max(pos, pos2);
#endif
if (pos == -1) {
confDirTemp = malloc(sizeof(TCHAR) * 2);
if (!confDirTemp) {
outOfMemory(TEXT("WADP"), 1);
return;
}
_tcsncpy(confDirTemp, TEXT("."), 2);
} else if (pos == 0) {
confDirTemp = malloc(sizeof(TCHAR) * 2);
if (!confDirTemp) {
outOfMemory(TEXT("WADP"), 2);
return;
}
_sntprintf(confDirTemp, 2, TEXT("%c"), pathSep);
} else {
confDirTemp = malloc(sizeof(TCHAR) * (pos + 1));
if (!confDirTemp) {
outOfMemory(TEXT("WADP"), 3);
return;
}
_tcsncpy(confDirTemp, wrapperData->argConfFile, pos);
confDirTemp[pos] = TEXT('\0');
}
#ifdef WIN32
/* Get buffer size, including '\0' */
work = GetFullPathName(confDirTemp, 0, NULL, NULL);
if (!work) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_FATAL,
TEXT("Unable to resolve the conf directory: %s"), getLastErrorText());
free(confDirTemp);
return;
}
wrapperData->confDir = malloc(sizeof(TCHAR) * work);
if (!wrapperData->confDir) {
outOfMemory(TEXT("WADP"), 4);
free(confDirTemp);
return;
}
if (!GetFullPathName(confDirTemp, work, wrapperData->confDir, NULL)) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_FATAL,
TEXT("Unable to resolve the conf directory: %s"), getLastErrorText());
free(confDirTemp);
return;
}
#else
/* The solaris implementation of realpath will return a relative path if a relative
* path is provided. We always need an abosulte path here. So build up one and
* then use realpath to remove any .. or other relative references. */
wrapperData->confDir = malloc(sizeof(TCHAR) * (PATH_MAX + 1));
if (!wrapperData->confDir) {
outOfMemory(TEXT("WADP"), 5);
free(confDirTemp);
return;
}
if (_trealpath(confDirTemp, wrapperData->confDir) == NULL) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_FATAL,
TEXT("Unable to resolve the original working directory: %s"), getLastErrorText());
free(confDirTemp);
return;
}
#endif
setEnv(TEXT("WRAPPER_CONF_DIR"), wrapperData->confDir, ENV_SOURCE_WRAPPER);
free(confDirTemp);
}
buffer = malloc(sizeof(TCHAR) * bufferLen);
if (!buffer) {
outOfMemory(TEXT("WADP"), 1);
return;
}
langTemp = _tgetenv(TEXT("LANG"));
if ((langTemp == NULL) || (_tcslen(langTemp) == 0)) {
_sntprintf(buffer, bufferLen, TEXT("set.WRAPPER_LANG=en"));
} else {
#ifdef WIN32
_sntprintf(buffer, bufferLen, TEXT("set.WRAPPER_LANG=%.2s"), langTemp);
#else
_sntprintf(buffer, bufferLen, TEXT("set.WRAPPER_LANG=%.2S"), langTemp);
#endif
}
#if !defined(WIN32) && defined(UNICODE)
if (langTemp) {
free(langTemp);
}
#endif
addPropertyPair(properties, NULL, 0, buffer, TRUE, FALSE, TRUE);
_sntprintf(buffer, bufferLen, TEXT("set.WRAPPER_PID=%d"), wrapperData->wrapperPID);
addPropertyPair(properties, NULL, 0, buffer, TRUE, FALSE, TRUE);
_sntprintf(buffer, bufferLen, TEXT("set.WRAPPER_BITS=%s"), wrapperBits);
addPropertyPair(properties, NULL, 0, buffer, TRUE, FALSE, TRUE);
_sntprintf(buffer, bufferLen, TEXT("set.WRAPPER_ARCH=%s"), wrapperArch);
addPropertyPair(properties, NULL, 0, buffer, TRUE, FALSE, TRUE);
_sntprintf(buffer, bufferLen, TEXT("set.WRAPPER_OS=%s"), wrapperOS);
addPropertyPair(properties, NULL, 0, buffer, TRUE, FALSE, TRUE);
_sntprintf(buffer, bufferLen, TEXT("set.WRAPPER_HOSTNAME=%s"), wrapperData->hostName);
addPropertyPair(properties, NULL, 0, buffer, TRUE, FALSE, TRUE);
_sntprintf(buffer, bufferLen, TEXT("set.WRAPPER_HOST_NAME=%s"), wrapperData->hostName);
addPropertyPair(properties, NULL, 0, buffer, TRUE, FALSE, TRUE);
#ifdef WIN32
addPropertyPair(properties, NULL, 0, TEXT("set.WRAPPER_FILE_SEPARATOR=\\"), TRUE, FALSE, TRUE);
addPropertyPair(properties, NULL, 0, TEXT("set.WRAPPER_PATH_SEPARATOR=;"), TRUE, FALSE, TRUE);
#else
addPropertyPair(properties, NULL, 0, TEXT("set.WRAPPER_FILE_SEPARATOR=/"), TRUE, FALSE, TRUE);
addPropertyPair(properties, NULL, 0, TEXT("set.WRAPPER_PATH_SEPARATOR=:"), TRUE, FALSE, TRUE);
#endif
free(buffer);
}
/**
* This function is here to help Community Edition users who are attempting
* to generate a hostId.
*/
int showHostIds(int logLevel) {
log_printf(WRAPPER_SOURCE_WRAPPER, logLevel, TEXT(""));
log_printf(WRAPPER_SOURCE_WRAPPER, logLevel, TEXT("The Community Edition of the Java Service Wrapper does not implement\nHostIds."));
log_printf(WRAPPER_SOURCE_WRAPPER, logLevel, TEXT(""));
log_printf(WRAPPER_SOURCE_WRAPPER, logLevel, TEXT("If you have requested a trial license, or purchased a license, you\nmay be looking for the Standard or Professional Editions of the Java\nService Wrapper. They can be downloaded here:"));
log_printf(WRAPPER_SOURCE_WRAPPER, logLevel, TEXT(" http://wrapper.tanukisoftware.com/download"));
log_printf(WRAPPER_SOURCE_WRAPPER, logLevel, TEXT(""));
return FALSE;
}
/**
* Loads the current environment into a table so we can debug it later.
*
* @return TRUE if there were problems, FALSE if successful.
*/
int loadEnvironment() {
size_t len;
TCHAR *sourcePair;
TCHAR *pair;
TCHAR *equal;
TCHAR *name;
TCHAR *value;
#ifdef WIN32
LPTCH lpvEnv;
LPTSTR lpszVariable;
#else
/* The compiler won't let us reverence environ directly in the for loop on OSX because it is actually a function. */
char **environment = environ;
int i;
#endif
#ifdef _DEBUG
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT("Loading Environment..."));
#endif
#ifdef WIN32
lpvEnv = GetEnvironmentStrings();
if (!lpvEnv)
{
_tprintf(TEXT("GetEnvironmentStrings failed (%s)\n"), getLastErrorText());
return TRUE;
}
lpszVariable = (LPTSTR)lpvEnv;
while (lpszVariable[0] != '\0') {
sourcePair = lpszVariable;
#else
i = 0;
while (environment[i]) {
len = mbstowcs(NULL, environment[i], 0);
if (len == (size_t)-1) {
/* Invalid string. Skip. */
} else {
sourcePair = malloc(sizeof(TCHAR) * (len + 1));
if (!sourcePair) {
outOfMemory(TEXT("LE"), 1);
_tprintf(TEXT(" Invalid character string: %s (%s)\n"), environment[i], getLastErrorText());
return TRUE;
}
mbstowcs(sourcePair, environment[i], len + 1);
#endif
len = _tcslen(sourcePair);
/* We need a copy of the variable pair so we can split it. */
pair = malloc(sizeof(TCHAR) * (len + 1));
if (!pair) {
outOfMemory(TEXT("LE"), 1);
#ifndef WIN32
free(sourcePair);
#endif
return TRUE;
}
_sntprintf(pair, len + 1, TEXT("%s"), sourcePair);
equal = _tcschr(pair, TEXT('='));
if (equal) {
name = pair;
value = &(equal[1]);
equal[0] = TEXT('\0');
if (_tcslen(name) <= 0) {
name = NULL;
}
if (_tcslen(value) <= 0) {
value = NULL;
}
/* It is possible that the name was empty. */
if (name) {
setEnv(name, value, ENV_SOURCE_PARENT);
}
}
free(pair);
#ifdef WIN32
lpszVariable += len + 1;
#else
free(sourcePair);
}
i++;
#endif
}
#ifdef _DEBUG
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT("Loading Environment complete."));
#endif
return FALSE;
}
/**
* Updates a string value by making a copy of the original. Any old value is
* first freed.
*/
void updateStringValue(TCHAR **ptr, const TCHAR *value) {
if (*ptr != NULL) {
free(*ptr);
*ptr = NULL;
}
if (value != NULL) {
*ptr = malloc(sizeof(TCHAR) * (_tcslen(value) + 1));
if (!(*ptr)) {
outOfMemory(TEXT("USV"), 1);
/* TODO: This is pretty bad. Not sure how to recover... */
} else {
_tcsncpy(*ptr, value, _tcslen(value) + 1);
}
}
}
#ifndef WIN32 /* UNIX */
int getSignalMode(const TCHAR *modeName, int defaultMode) {
if (!modeName) {
return defaultMode;
}
if (strcmpIgnoreCase(modeName, TEXT("IGNORE")) == 0) {
return WRAPPER_SIGNAL_MODE_IGNORE;
} else if (strcmpIgnoreCase(modeName, TEXT("RESTART")) == 0) {
return WRAPPER_SIGNAL_MODE_RESTART;
} else if (strcmpIgnoreCase(modeName, TEXT("SHUTDOWN")) == 0) {
return WRAPPER_SIGNAL_MODE_SHUTDOWN;
} else if (strcmpIgnoreCase(modeName, TEXT("FORWARD")) == 0) {
return WRAPPER_SIGNAL_MODE_FORWARD;
} else {
return defaultMode;
}
}
/**
* Return FALSE if successful, TRUE if there were problems.
*/
int wrapperBuildUnixDaemonInfo() {
if (!wrapperData->configured) {
/** Get the daemonize flag. */
wrapperData->daemonize = getBooleanProperty(properties, TEXT("wrapper.daemonize"), FALSE);
/** Configure the HUP signal handler. */
wrapperData->signalHUPMode = getSignalMode(getStringProperty(properties, TEXT("wrapper.signal.mode.hup"), NULL), WRAPPER_SIGNAL_MODE_FORWARD);
/** Configure the USR1 signal handler. */
wrapperData->signalUSR1Mode = getSignalMode(getStringProperty(properties, TEXT("wrapper.signal.mode.usr1"), NULL), WRAPPER_SIGNAL_MODE_FORWARD);
/** Configure the USR2 signal handler. */
wrapperData->signalUSR2Mode = getSignalMode(getStringProperty(properties, TEXT("wrapper.signal.mode.usr2"), NULL), WRAPPER_SIGNAL_MODE_FORWARD);
}
return FALSE;
}
#endif
/**
* Dumps the table of environment variables, and their sources.
*
* @param logLevel Level at which to log the output.
*/
void dumpEnvironment(int logLevel) {
EnvSrc *envSrc;
TCHAR *envVal;
log_printf(WRAPPER_SOURCE_WRAPPER, logLevel, TEXT(""));
log_printf(WRAPPER_SOURCE_WRAPPER, logLevel, TEXT("Environment variables (Source | Name=Value) BEGIN:"));
envSrc = baseEnvSrc;
while (envSrc) {
envVal = _tgetenv(envSrc->name);
log_printf(WRAPPER_SOURCE_WRAPPER, logLevel, TEXT(" %c%c%c%c%c | %s=%s"),
(envSrc->source & ENV_SOURCE_PARENT ? TEXT('P') : TEXT('-')),
#ifdef WIN32
(envSrc->source & ENV_SOURCE_REG_SYSTEM ? TEXT('S') : TEXT('-')),
(envSrc->source & ENV_SOURCE_REG_ACCOUNT ? TEXT('A') : TEXT('-')),
#else
TEXT('-'),
TEXT('-'),
#endif
(envSrc->source & ENV_SOURCE_WRAPPER ? TEXT('W') : TEXT('-')),
(envSrc->source & ENV_SOURCE_CONFIG ? TEXT('C') : TEXT('-')),
envSrc->name,
(envVal ? envVal : TEXT(""))
);
#if !defined(WIN32) && defined(UNICODE)
if (envVal) {
free(envVal);
}
#endif
envSrc = envSrc->next;
}
log_printf(WRAPPER_SOURCE_WRAPPER, logLevel, TEXT("Environment variables END:"));
log_printf(WRAPPER_SOURCE_WRAPPER, logLevel, TEXT(""));
}
void wrapperLoadLoggingProperties(int preload) {
const TCHAR *logfilePath;
int logfileRollMode;
setLogPropertyWarnings(properties, !preload);
setLogPropertyWarningLogLevel(properties, getLogLevelForName(getStringProperty(properties, TEXT("wrapper.property_warning.loglevel"), TEXT("WARN"))));
setLogWarningThreshold(getIntProperty(properties, TEXT("wrapper.log.warning.threshold"), 0));
wrapperData->logLFDelayThreshold = propIntMax(propIntMin(getIntProperty(properties, TEXT("wrapper.log.lf_delay.threshold"), 500), 3600000), 0);
logfilePath = getFileSafeStringProperty(properties, TEXT("wrapper.logfile"), TEXT("wrapper.log"));
setLogfilePath(logfilePath, wrapperData->workingDir, preload);
logfileRollMode = getLogfileRollModeForName(getStringProperty(properties, TEXT("wrapper.logfile.rollmode"), TEXT("SIZE")));
if (logfileRollMode == ROLL_MODE_UNKNOWN) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_WARN,
TEXT("wrapper.logfile.rollmode invalid. Disabling log file rolling."));
logfileRollMode = ROLL_MODE_NONE;
} else if (logfileRollMode == ROLL_MODE_DATE) {
if (!_tcsstr(logfilePath, ROLL_MODE_DATE_TOKEN)) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_WARN,
TEXT("wrapper.logfile must contain \"%s\" for a roll mode of DATE. Disabling log file rolling."),
ROLL_MODE_DATE_TOKEN);
logfileRollMode = ROLL_MODE_NONE;
}
}
setLogfileRollMode(logfileRollMode);
/* Load log file format */
setLogfileFormat(getStringProperty(properties, TEXT("wrapper.logfile.format"), LOG_FORMAT_LOGFILE_DEFAULT));
/* Load log file log level */
setLogfileLevel(getStringProperty(properties, TEXT("wrapper.logfile.loglevel"), TEXT("INFO")));
/* Load max log filesize log level */
setLogfileMaxFileSize(getStringProperty(properties, TEXT("wrapper.logfile.maxsize"), TEXT("0")));
/* Load log files level */
setLogfileMaxLogFiles(getIntProperty(properties, TEXT("wrapper.logfile.maxfiles"), 0));
/* Load log file purge pattern */
setLogfilePurgePattern(getFileSafeStringProperty(properties, TEXT("wrapper.logfile.purge.pattern"), TEXT("")));
/* Load log file purge sort */
setLogfilePurgeSortMode(wrapperFileGetSortMode(getStringProperty(properties, TEXT("wrapper.logfile.purge.sort"), TEXT("TIMES"))));
/* Get the close timeout. */
wrapperData->logfileCloseTimeout = propIntMax(propIntMin(getIntProperty(properties, TEXT("wrapper.logfile.close.timeout"), getIntProperty(properties, TEXT("wrapper.logfile.inactivity.timeout"), 1)), 3600), -1);
setLogfileAutoClose(wrapperData->logfileCloseTimeout == 0);
/* Get the flush timeout. */
wrapperData->logfileFlushTimeout = propIntMax(propIntMin(getIntProperty(properties, TEXT("wrapper.logfile.flush.timeout"), 1), 3600), 0);
setLogfileAutoFlush(wrapperData->logfileFlushTimeout == 0);
/* Load console format */
setConsoleLogFormat(getStringProperty(properties, TEXT("wrapper.console.format"), LOG_FORMAT_CONSOLE_DEFAULT));
setConsoleLogLevel(getStringProperty(properties, TEXT("wrapper.console.loglevel"), TEXT("INFO")));
/* Load the console flush flag. */
setConsoleFlush(getBooleanProperty(properties, TEXT("wrapper.console.flush"), FALSE));
#ifdef WIN32
/* Load the console direct flag. */
setConsoleDirect(getBooleanProperty(properties, TEXT("wrapper.console.direct"), TRUE));
#endif
/* Load the console loglevel targets. */
setConsoleFatalToStdErr(getBooleanProperty(properties, TEXT("wrapper.console.fatal_to_stderr"), TRUE));
setConsoleErrorToStdErr(getBooleanProperty(properties, TEXT("wrapper.console.error_to_stderr"), TRUE));
setConsoleWarnToStdErr(getBooleanProperty(properties, TEXT("wrapper.console.warn_to_stderr"), FALSE));
/* Load syslog log level */
setSyslogLevel(getStringProperty(properties, TEXT("wrapper.syslog.loglevel"), TEXT("NONE")));
#ifndef WIN32
/* Load syslog facility */
setSyslogFacility(getStringProperty(properties, TEXT("wrapper.syslog.facility"), TEXT("USER")));
#endif
/* Load syslog event source name */
setSyslogEventSourceName(getStringProperty(properties, TEXT("wrapper.syslog.ident"), getStringProperty(properties, TEXT("wrapper.name"), getStringProperty(properties, TEXT("wrapper.ntservice.name"), TEXT("wrapper")))));
/* Register the syslog message file if syslog is enabled */
if (getSyslogLevelInt() < LEVEL_NONE) {
registerSyslogMessageFile();
}
/* Get the debug status (Property is deprecated but flag is still used) */
wrapperData->isDebugging = getBooleanProperty(properties, TEXT("wrapper.debug"), FALSE);
if (wrapperData->isDebugging) {
/* For backwards compatability */
setConsoleLogLevelInt(LEVEL_DEBUG);
setLogfileLevelInt(LEVEL_DEBUG);
} else {
if (getLowLogLevel() <= LEVEL_DEBUG) {
wrapperData->isDebugging = TRUE;
}
}
}
/**
* Load the configuration.
*
* @param preload TRUE if the configuration is being preloaded.
*
* Return TRUE if there were any problems.
*/
int wrapperLoadConfigurationProperties(int preload) {
int i;
int firstCall;
#ifdef WIN32
int work;
int defaultUMask;
#else
mode_t defaultUMask;
#endif
const TCHAR* prop;
/* Unless this is the first call, we need to dispose the previous properties object. */
if (properties) {
firstCall = FALSE;
disposeProperties(properties);
properties = NULL;
} else {
firstCall = TRUE;
if (wrapperData->originalWorkingDir) {
free(wrapperData->originalWorkingDir);
}
/* This is the first time, so preserve the working directory. */
#ifdef WIN32
/* Get buffer size, including '\0' */
work = GetFullPathName(TEXT("."), 0, NULL, NULL);
if (!work) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_FATAL,
TEXT("Unable to resolve the original working directory: %s"), getLastErrorText());
return TRUE;
}
wrapperData->originalWorkingDir = malloc(sizeof(TCHAR) * work);
if (!wrapperData->originalWorkingDir) {
outOfMemory(TEXT("WLCP"), 3);
return TRUE;
}
if (!GetFullPathName(TEXT("."), work, wrapperData->originalWorkingDir, NULL)) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_FATAL,
TEXT("Unable to resolve the original working directory: %s"), getLastErrorText());
return TRUE;
}
#else
/* The solaris implementation of realpath will return a relative path if a relative
* path is provided. We always need an abosulte path here. So build up one and
* then use realpath to remove any .. or other relative references. */
wrapperData->originalWorkingDir = malloc(sizeof(TCHAR) * (PATH_MAX + 1));
if (!wrapperData->originalWorkingDir) {
outOfMemory(TEXT("WLCP"), 4);
return TRUE;
}
if (_trealpath(TEXT("."), wrapperData->originalWorkingDir) == NULL) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_FATAL,
TEXT("Unable to resolve the original working directory: %s"), getLastErrorText());
return TRUE;
}
#endif
if (wrapperData->configFile) {
free(wrapperData->configFile);
}
/* This is the first time, so preserve the full canonical location of the
* configuration file. */
#ifdef WIN32
work = GetFullPathName(wrapperData->argConfFile, 0, NULL, NULL);
if (!work) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_FATAL,
TEXT("Unable to resolve the full path of the configuration file, %s: %s"),
wrapperData->argConfFile, getLastErrorText());
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_FATAL,
TEXT("Current working directory is: %s"), wrapperData->originalWorkingDir);
return TRUE;
}
wrapperData->configFile = malloc(sizeof(TCHAR) * work);
if (!wrapperData->configFile) {
outOfMemory(TEXT("WLCP"), 1);
return TRUE;
}
if (!GetFullPathName(wrapperData->argConfFile, work, wrapperData->configFile, NULL)) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_FATAL,
TEXT("Unable to resolve the full path of the configuration file, %s: %s"),
wrapperData->argConfFile, getLastErrorText());
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_FATAL, TEXT(
"Current working directory is: %s"), wrapperData->originalWorkingDir);
return TRUE;
}
#else
/* The solaris implementation of realpath will return a relative path if a relative
* path is provided. We always need an abosulte path here. So build up one and
* then use realpath to remove any .. or other relative references. */
wrapperData->configFile = malloc(sizeof(TCHAR) * (PATH_MAX + 1));
if (!wrapperData->configFile) {
outOfMemory(TEXT("WLCP"), 2);
return TRUE;
}
if (_trealpath(wrapperData->argConfFile, wrapperData->configFile) == NULL) {
/* Most likely the file does not exist. The wrapperData->configFile has the first
* file that could not be found. May not be the config file directly if symbolic
* links are involved. */
if (wrapperData->argConfFileDefault) {
/* The output buffer is likely to contain undefined data.
* To be on the safe side and in order to report the error
* below correctly we need to override the data first.*/
_sntprintf(wrapperData->configFile, PATH_MAX + 1, TEXT("%s"), wrapperData->argConfFile);
/* This was the default config file name. We know that the working directory
* could be resolved so the problem must be that the default config file does
* not exist. This problem will be reported later and the wrapperData->configFile
* variable will have the correct full path.
* Fall through for now and the user will get a better error later. */
} else {
if (!preload) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_FATAL, TEXT(
"Unable to open configuration file: %s (%s)\n Current working directory: %s"),
wrapperData->argConfFile, getLastErrorText(), wrapperData->originalWorkingDir);
}
return TRUE;
}
}
#endif
}
/* Create a Properties structure. */
properties = createProperties();
if (!properties) {
return TRUE;
}
setLogPropertyWarnings(properties, !preload);
wrapperAddDefaultProperties();
/* The argument prior to the argBase will be the configuration file, followed
* by 0 or more command line properties. The command line properties need to be
* loaded first, followed by the configuration file. */
if (strcmpIgnoreCase(wrapperData->argCommand, TEXT("-translate")) != 0) {
for (i = 0; i < wrapperData->argCount; i++) {
if (addPropertyPair(properties, NULL, 0, wrapperData->argValues[i], TRUE, TRUE, FALSE)) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_FATAL,
TEXT("The argument '%s' is not a valid property name-value pair."),
wrapperData->argValues[i]);
return TRUE;
}
}
}
/* Now load the configuration file.
* When this happens, the working directory MUST be set to the original working dir. */
#ifdef WIN32
if (loadProperties(properties, wrapperData->configFile, preload)) {
#else
if (loadProperties(properties, wrapperData->configFile, (preload | wrapperData->daemonize))) {
#endif
/* File not found. */
/* If this was a default file name then we don't want to show this as
* an error here. It will be handled by the caller. */
/* Debug is not yet available as the config file is not yet loaded. */
if ((!preload) && (!wrapperData->argConfFileDefault)) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_FATAL, TEXT("Failed to load configuration: %s"), wrapperData->configFile);
}
return TRUE;
}
/* Config file found. */
wrapperData->argConfFileFound = TRUE;
if (firstCall) {
/* If the working dir was configured, we need to extract it and preserve its value.
* This must be done after the configuration has been completely loaded. */
prop = getStringProperty(properties, TEXT("wrapper.working.dir"), TEXT("."));
if (prop && (_tcslen(prop) > 0)) {
if (wrapperData->workingDir) {
free(wrapperData->workingDir);
}
#ifdef WIN32
work = GetFullPathName(prop, 0, NULL, NULL);
if (!work) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_FATAL,
TEXT("Unable to resolve the working directory %s: %s"), prop, getLastErrorText());
return TRUE;
}
wrapperData->workingDir = malloc(sizeof(TCHAR) * work);
if (!wrapperData->workingDir) {
outOfMemory(TEXT("WLCP"), 5);
return TRUE;
}
if (!GetFullPathName(prop, work, wrapperData->workingDir, NULL)) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_FATAL,
TEXT("Unable to resolve the working directory %s: %s"), prop, getLastErrorText());
return TRUE;
}
#else
/* The solaris implementation of realpath will return a relative path if a relative
* path is provided. We always need an abosulte path here. So build up one and
* then use realpath to remove any .. or other relative references. */
wrapperData->workingDir = malloc(sizeof(TCHAR) * (PATH_MAX + 1));
if (!wrapperData->workingDir) {
outOfMemory(TEXT("WLCP"), 6);
return TRUE;
}
if (_trealpath(prop, wrapperData->workingDir) == NULL) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_FATAL,
TEXT("Unable to resolve the working directory %s: %s"), prop, getLastErrorText());
return TRUE;
}
#endif
}
}
#ifdef _DEBUG
/* Display the active properties */
_tprintf(TEXT("Debug Configuration Properties:\n"));
dumpProperties(properties);
#endif
/* Now that the configuration is loaded, we need to update the working directory if the user specified one.
* This must be done now so that anything that references the working directory, including the log file
* and language pack locations will work correctly. */
if (wrapperData->workingDir && wrapperSetWorkingDir(wrapperData->workingDir, !preload)) {
return TRUE;
}
if (wrapperData->umask == -1) {
/** Get the umask value for the various files. */
#ifdef WIN32
defaultUMask = _umask(0);
_umask(defaultUMask);
#else
defaultUMask = umask((mode_t)0);
umask(defaultUMask);
#endif
wrapperData->umask = getIntProperty(properties, TEXT("wrapper.umask"), defaultUMask);
}
wrapperData->javaUmask = getIntProperty(properties, TEXT("wrapper.java.umask"), wrapperData->umask);
wrapperData->pidFileUmask = getIntProperty(properties, TEXT("wrapper.pidfile.umask"), wrapperData->umask);
wrapperData->lockFileUmask = getIntProperty(properties, TEXT("wrapper.lockfile.umask"), wrapperData->umask);
wrapperData->javaPidFileUmask = getIntProperty(properties, TEXT("wrapper.java.pidfile.umask"), wrapperData->umask);
wrapperData->javaIdFileUmask = getIntProperty(properties, TEXT("wrapper.java.idfile.umask"), wrapperData->umask);
wrapperData->statusFileUmask = getIntProperty(properties, TEXT("wrapper.statusfile.umask"), wrapperData->umask);
wrapperData->javaStatusFileUmask = getIntProperty(properties, TEXT("wrapper.java.statusfile.umask"), wrapperData->umask);
wrapperData->anchorFileUmask = getIntProperty(properties, TEXT("wrapper.anchorfile.umask"), wrapperData->umask);
setLogfileUmask(getIntProperty(properties, TEXT("wrapper.logfile.umask"), wrapperData->umask));
#ifndef WIN32
/** If in the first call here and the wrapper will deamonize, then we don't need
* to proceed any further anymore as the properties will be loaded properly at
* the second time...
*/
if ((firstCall == TRUE) && (!wrapperBuildUnixDaemonInfo()) && wrapperData->daemonize) {
return FALSE;
}
#endif
/* Load the configuration. */
if ((strcmpIgnoreCase(wrapperData->argCommand, TEXT("-translate")) != 0) && loadConfiguration()) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_FATAL,
TEXT("Problem loading wrapper configuration file: %s"), wrapperData->configFile);
return TRUE;
}
return FALSE;
}
void wrapperGetCurrentTime(struct timeb *timeBuffer) {
#ifdef WIN32
ftime(timeBuffer);
#else
struct timeval tv;
gettimeofday(&tv, NULL);
timeBuffer->time = (time_t)tv.tv_sec;
timeBuffer->millitm = (unsigned short)(tv.tv_usec / 1000);
#endif
}
/**
* This function stops the pipes (quite in a brutal way)
*/
void protocolStopServerPipe() {
if (protocolActiveServerPipeIn != INVALID_HANDLE_VALUE) {
#ifdef WIN32
CloseHandle(protocolActiveServerPipeIn);
#else
close(protocolActiveServerPipeIn);
#endif
protocolActiveServerPipeIn = INVALID_HANDLE_VALUE;
log_printf(WRAPPER_SOURCE_PROTOCOL, LEVEL_INFO, TEXT("backend pipe closed."));
}
if (protocolActiveServerPipeOut != INVALID_HANDLE_VALUE) {
#ifdef WIN32
CloseHandle(protocolActiveServerPipeOut);
#else
close(protocolActiveServerPipeOut);
#endif
protocolActiveServerPipeOut = INVALID_HANDLE_VALUE;
log_printf(WRAPPER_SOURCE_PROTOCOL, LEVEL_INFO, TEXT("backend pipe closed."));
}
}
void protocolStopServerSocket() {
int rc;
/* Close the socket. */
if (protocolActiveServerSD != INVALID_SOCKET) {
if (wrapperData->isDebugging) {
log_printf(WRAPPER_SOURCE_PROTOCOL, LEVEL_DEBUG, TEXT("closing backend server."));
}
#ifdef WIN32
rc = closesocket(protocolActiveServerSD);
#else /* UNIX */
rc = close(protocolActiveServerSD);
#endif
if (rc == SOCKET_ERROR) {
if (wrapperData->isDebugging) {
log_printf(WRAPPER_SOURCE_PROTOCOL, LEVEL_DEBUG, TEXT("server socket close failed. (%d)"), wrapperGetLastError());
}
}
protocolActiveServerSD = INVALID_SOCKET;
}
wrapperData->actualPort = 0;
}
void protocolStopServer() {
if (wrapperData->backendType == WRAPPER_BACKEND_TYPE_PIPE) {
protocolStopServerPipe();
} else {
protocolStopServerSocket();
}
}
int protocolActiveServerPipeStarted = FALSE;
void protocolStartServerPipe() {
size_t pipeNameLen;
TCHAR *pipeName;
#ifdef WIN32
pipeNameLen = 17 + 10 + 1 + 10 + 3;
#else
pipeNameLen = 12 + 10 + 1 + 10 + 3;
#endif
pipeName = malloc(sizeof(TCHAR) * (pipeNameLen + 1));
if (!pipeName) {
outOfMemory(TEXT("PSSP"), 1);
return;
}
#ifdef WIN32
_sntprintf(pipeName, pipeNameLen, TEXT("\\\\.\\pipe\\wrapper-%d-%d-out"), wrapperData->wrapperPID, wrapperData->jvmRestarts + 1);
if ((protocolActiveServerPipeOut = CreateNamedPipe(pipeName,
PIPE_ACCESS_OUTBOUND,/* + FILE_FLAG_FIRST_PIPE_INSTANCE, */
PIPE_TYPE_MESSAGE | /* message type pipe */
PIPE_READMODE_MESSAGE | /* message-read mode */
PIPE_NOWAIT, /* nonblocking mode */
1, /* only allow 1 connection at a time */
32768,
32768,
0,
NULL)) == INVALID_HANDLE_VALUE) {
#else
_sntprintf(pipeName, pipeNameLen, TEXT("/tmp/wrapper-%d-%d-out"), wrapperData->wrapperPID, wrapperData->jvmRestarts + 1);
if (_tmkfifo(pipeName, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH) == INVALID_HANDLE_VALUE) {
#endif
log_printf(WRAPPER_SOURCE_PROTOCOL, LEVEL_ERROR, TEXT("Unable to create backend pipe: %s"), getLastErrorText());
free(pipeName);
return;
}
if (wrapperData->isDebugging) {
log_printf(WRAPPER_SOURCE_PROTOCOL, LEVEL_DEBUG, TEXT("server listening on pipe %s."), pipeName);
}
#ifdef WIN32
_sntprintf(pipeName, pipeNameLen, TEXT("\\\\.\\pipe\\wrapper-%d-%d-in"), wrapperData->wrapperPID, wrapperData->jvmRestarts + 1);
if ((protocolActiveServerPipeIn = CreateNamedPipe(pipeName,
PIPE_ACCESS_INBOUND,/* + FILE_FLAG_FIRST_PIPE_INSTANCE,*/
PIPE_TYPE_MESSAGE | /* message type pipe */
PIPE_READMODE_MESSAGE | /* message-read mode*/
PIPE_NOWAIT, /* nonblocking mode*/
1,
32768,
32768,
0,
NULL)) == INVALID_HANDLE_VALUE) {
#else
_sntprintf(pipeName, pipeNameLen, TEXT("/tmp/wrapper-%d-%d-in"), wrapperData->wrapperPID, wrapperData->jvmRestarts + 1);
if (_tmkfifo(pipeName, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH) == INVALID_HANDLE_VALUE) {
#endif
log_printf(WRAPPER_SOURCE_PROTOCOL, LEVEL_ERROR, TEXT("Unable to create backend pipe: %s"), getLastErrorText());
free(pipeName);
return;
}
if (wrapperData->isDebugging) {
log_printf(WRAPPER_SOURCE_PROTOCOL, LEVEL_DEBUG, TEXT("server listening on pipe %s."), pipeName);
}
protocolActiveServerPipeStarted = TRUE;
free(pipeName);
}
void protocolStartServerSocket() {
struct sockaddr_in addr_srv;
int rc;
int port;
int fixedPort;
#ifdef UNICODE
char* tempAddress;
size_t len;
#endif
/*int optVal;*/
#ifdef WIN32
u_long dwNoBlock = TRUE;
#endif
/* Create the server socket. */
protocolActiveServerSD = socket(AF_INET, SOCK_STREAM, 0);
if (protocolActiveServerSD == INVALID_SOCKET) {
log_printf(WRAPPER_SOURCE_PROTOCOL, LEVEL_ERROR,
TEXT("server socket creation failed. (%s)"), getLastErrorText());
return;
}
/* Make sure the socket is reused. */
/* We actually do not want to do this as it makes it possible for more than one Wrapper
* instance to bind to the same port. The second instance succeeds to bind, but any
* attempts to connect to that port will go to the first Wrapper. This would of course
* cause attempts to launch the second JVM to fail.
* Leave this code here as a future development note.
optVal = 1;
#ifdef WIN32
if (setsockopt(protocolActiveServerSD, SOL_SOCKET, SO_REUSEADDR, (TCHAR *)&optVal, sizeof(optVal)) < 0) {
#else
if (setsockopt(protocolActiveServerSD, SOL_SOCKET, SO_REUSEADDR, &optVal, sizeof(optVal)) < 0) {
#endif
log_printf(WRAPPER_SOURCE_PROTOCOL, LEVEL_ERROR,
"server socket SO_REUSEADDR failed. (%s)", getLastErrorText());
wrapperProtocolClose();
protocolStopServer();
return;
}
*/
/* Make the socket non-blocking */
#ifdef WIN32
rc = ioctlsocket(protocolActiveServerSD, FIONBIO, &dwNoBlock);
#else /* UNIX */
rc = fcntl(protocolActiveServerSD, F_SETFL, O_NONBLOCK);
#endif
if (rc == SOCKET_ERROR) {
log_printf(WRAPPER_SOURCE_PROTOCOL, LEVEL_ERROR,
TEXT("server socket ioctlsocket failed. (%s)"), getLastErrorText());
wrapperProtocolClose();
protocolStopServer();
return;
}
/* If a port was specified in the configuration file then we want to
* try to use that port or find the next available port. If 0 was
* specified, then we will silently start looking for an available
* port starting at 32000. */
port = wrapperData->port;
if (port <= 0) {
port = wrapperData->portMin;
fixedPort = FALSE;
} else {
fixedPort = TRUE;
}
tryagain:
/* Try binding to the port. */
/*log_printf(WRAPPER_SOURCE_PROTOCOL, LEVEL_STATUS, TEXT("Trying port %d"), port);*/
/* Cleanup the addr_srv first */
memset(&addr_srv, 0, sizeof(addr_srv));
addr_srv.sin_family = AF_INET;
if (wrapperData->portAddress == NULL) {
addr_srv.sin_addr.s_addr = inet_addr("127.0.0.1");
} else {
#ifdef UNICODE
#ifdef WIN32
len = WideCharToMultiByte(CP_OEMCP, 0, wrapperData->portAddress, -1, NULL, 0, NULL, NULL);
if (len <= 0) {
log_printf(WRAPPER_SOURCE_PROTOCOL, LEVEL_WARN,
TEXT("Invalid multibyte sequence in port address \"%s\" : %s"), wrapperData->portAddress, getLastErrorText());
return;
}
tempAddress = malloc(len);
if (!tempAddress) {
outOfMemory(TEXT("PSSS"), 1);
return;
}
WideCharToMultiByte(CP_OEMCP, 0, wrapperData->portAddress, -1, tempAddress, (int)len, NULL, NULL);
#else
len = wcstombs(NULL, wrapperData->portAddress, 0) + 1;
_tprintf(TEXT("%d hanth %s\n"), len, wrapperData->portAddress);
if (len == (size_t)-1) {
log_printf(WRAPPER_SOURCE_PROTOCOL, LEVEL_WARN,
TEXT("Invalid multibyte sequence in port address \"%s\" : %s"), wrapperData->portAddress, getLastErrorText());
return;
}
tempAddress = malloc(len);
if (!tempAddress) {
outOfMemory(TEXT("PSSS"), 2);
return;
}
wcstombs(tempAddress, wrapperData->portAddress, len);
_tprintf(TEXT("%d hanth % s\n"), len, tempAddress);
#endif
addr_srv.sin_addr.s_addr = inet_addr(tempAddress);
free(tempAddress);
#else
addr_srv.sin_addr.s_addr = inet_addr(wrapperData->portAddress);
#endif
}
addr_srv.sin_port = htons((u_short)port);
#ifdef WIN32
rc = bind(protocolActiveServerSD, (struct sockaddr FAR *)&addr_srv, sizeof(addr_srv));
#else /* UNIX */
rc = bind(protocolActiveServerSD, (struct sockaddr *)&addr_srv, sizeof(addr_srv));
#endif
if (rc == SOCKET_ERROR) {
rc = wrapperGetLastError();
/* The specified port could bot be bound. */
if (rc == EADDRINUSE ||
#ifdef WIN32
rc == WSAEACCES) {
#else
rc == EACCES) {
#endif
/* Address in use, try looking at the next one. */
if (fixedPort) {
/* The last port checked was the defined fixed port, switch to the dynamic range. */
port = wrapperData->portMin;
fixedPort = FALSE;
goto tryagain;
} else {
port++;
if (port <= wrapperData->portMax) {
goto tryagain;
}
}
}
/* Log an error. This is fatal, so die. */
if (wrapperData->port <= 0) {
log_printf(WRAPPER_SOURCE_PROTOCOL, LEVEL_FATAL,
TEXT("unable to bind listener to any port in the range %d to %d. (%s)"),
wrapperData->portMin, wrapperData->portMax, getLastErrorText());
} else {
log_printf(WRAPPER_SOURCE_PROTOCOL, LEVEL_FATAL,
TEXT("unable to bind listener port %d, or any port in the range %d to %d. (%s)"),
wrapperData->port, wrapperData->portMin, wrapperData->portMax, getLastErrorText());
}
wrapperStopProcess(getLastError(), TRUE);
wrapperProtocolClose();
protocolStopServer();
wrapperData->exitRequested = TRUE;
wrapperData->restartRequested = WRAPPER_RESTART_REQUESTED_NO;
return;
}
/* If we got here, then we are bound to the port */
if ((wrapperData->port > 0) && (port != wrapperData->port)) {
log_printf(WRAPPER_SOURCE_PROTOCOL, LEVEL_INFO, TEXT("port %d already in use, using port %d instead."), wrapperData->port, port);
}
wrapperData->actualPort = port;
if (wrapperData->isDebugging) {
log_printf(WRAPPER_SOURCE_PROTOCOL, LEVEL_DEBUG, TEXT("server listening on port %d."), wrapperData->actualPort);
}
/* Tell the socket to start listening. */
rc = listen(protocolActiveServerSD, 1);
if (rc == SOCKET_ERROR) {
log_printf(WRAPPER_SOURCE_PROTOCOL, LEVEL_ERROR, TEXT("server socket listen failed. (%d)"), wrapperGetLastError());
wrapperProtocolClose();
protocolStopServer();
return;
}
}
void protocolStartServer() {
if (wrapperData->backendType == WRAPPER_BACKEND_TYPE_PIPE) {
protocolStartServerPipe();
} else {
protocolStartServerSocket();
}
}
/* this functions connects the pipes once the other end is there */
void protocolOpenPipe() {
#ifdef WIN32
int result;
result = ConnectNamedPipe(protocolActiveServerPipeOut, NULL);
if (GetLastError() == ERROR_PIPE_LISTENING) {
return;
}
result = ConnectNamedPipe(protocolActiveServerPipeIn, NULL);
if (GetLastError() == ERROR_PIPE_LISTENING) {
return;
}
if ((result == 0) && (GetLastError() != ERROR_PIPE_CONNECTED) && (GetLastError() != ERROR_NO_DATA)) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_FATAL, TEXT("Pipe connect failed: %s"), getLastErrorText());
return;
}
#else
size_t pipeNameLen;
TCHAR *pipeName;
pipeNameLen = 12 + 10 + 1 + 10 + 3;
pipeName = malloc(sizeof(TCHAR) * (pipeNameLen + 1));
if (!pipeName) {
outOfMemory(TEXT("PSSP"), 1);
return;
}
_sntprintf(pipeName, pipeNameLen, TEXT("/tmp/wrapper-%d-%d-out"), wrapperData->wrapperPID, wrapperData->jvmRestarts);
protocolActiveServerPipeOut = _topen(pipeName, O_WRONLY | O_NONBLOCK, S_IWUSR | S_IRUSR);
if (protocolActiveServerPipeOut == INVALID_HANDLE_VALUE) {
free(pipeName);
return;
}
_sntprintf(pipeName, pipeNameLen, TEXT("/tmp/wrapper-%d-%d-in"), wrapperData->wrapperPID, wrapperData->jvmRestarts);
protocolActiveServerPipeIn = _topen(pipeName, O_RDONLY | O_NONBLOCK, S_IRUSR);
if (protocolActiveServerPipeIn == INVALID_HANDLE_VALUE) {
free(pipeName);
return;
}
free(pipeName);
#endif
protocolActiveServerPipeConnected = TRUE;
}
void protocolOpenSocket() {
struct sockaddr_in addr_srv;
int rc;
#if defined(WIN32)
u_long dwNoBlock = TRUE;
u_long addr_srv_len;
#elif (defined(HPUX) && !defined(ARCH_IA)) || defined(OSF1) || defined(IRIX)
int addr_srv_len;
#else
socklen_t addr_srv_len;
#endif
SOCKET newBackendSD = INVALID_SOCKET;
/* Is the server socket open? */
if (protocolActiveServerSD == INVALID_SOCKET) {
/* can't do anything yet. */
return;
}
/* Try accepting a socket. */
addr_srv_len = sizeof(addr_srv);
#ifdef WIN32
newBackendSD = accept(protocolActiveServerSD, (struct sockaddr FAR *)&addr_srv, &addr_srv_len);
#else /* UNIX */
newBackendSD = accept(protocolActiveServerSD, (struct sockaddr *)&addr_srv, &addr_srv_len);
#endif
if (newBackendSD == INVALID_SOCKET) {
rc = wrapperGetLastError();
/* EWOULDBLOCK != EAGAIN on some platforms. */
if ((rc == EWOULDBLOCK) || (rc == EAGAIN)) {
/* There are no incomming sockets right now. */
return;
} else {
if (wrapperData->isDebugging) {
log_printf(WRAPPER_SOURCE_PROTOCOL, LEVEL_DEBUG,
TEXT("socket creation failed. (%s)"), getLastErrorText());
}
return;
}
}
/* Is it already open? */
if (protocolActiveBackendSD != INVALID_SOCKET) {
log_printf(WRAPPER_SOURCE_PROTOCOL, LEVEL_WARN, TEXT("Ignoring unexpected backend socket connection from %s on port %d"),
(char *)inet_ntoa(addr_srv.sin_addr), ntohs(addr_srv.sin_port));
#ifdef WIN32
rc = closesocket(newBackendSD);
#else /* UNIX */
rc = close(newBackendSD);
#endif
if (rc == SOCKET_ERROR) {
if (wrapperData->isDebugging) {
log_printf(WRAPPER_SOURCE_PROTOCOL, LEVEL_DEBUG, TEXT("socket close failed. (%d)"), wrapperGetLastError());
}
}
return;
}
/* New connection, so continue. */
protocolActiveBackendSD = newBackendSD;
if (wrapperData->isDebugging) {
#ifdef UNICODE
TCHAR* socketSource;
int req;
#ifdef WIN32
req = MultiByteToWideChar(CP_OEMCP, 0, inet_ntoa(addr_srv.sin_addr), -1, NULL, 0);
socketSource = malloc(sizeof(TCHAR) * (req + 1));
if (!socketSource) {
outOfMemory(TEXT("PO"), 1);
return;
}
MultiByteToWideChar(CP_OEMCP, 0, inet_ntoa(addr_srv.sin_addr), -1, socketSource, req + 1);
#else
req = mbstowcs(NULL, inet_ntoa(addr_srv.sin_addr), 0);
socketSource = malloc(sizeof(TCHAR) * (req + 1));
if (!socketSource) {
outOfMemory(TEXT("PO"), 2);
return;
}
mbstowcs(socketSource, inet_ntoa(addr_srv.sin_addr), req + 1);
#endif
log_printf(WRAPPER_SOURCE_PROTOCOL, LEVEL_DEBUG, TEXT("accepted a socket from %s on port %d"),
socketSource, ntohs(addr_srv.sin_port));
free(socketSource);
#else
log_printf(WRAPPER_SOURCE_PROTOCOL, LEVEL_DEBUG, TEXT("accepted a socket from %s on port %d"),
inet_ntoa(addr_srv.sin_addr), ntohs(addr_srv.sin_port));
#endif
}
/* Make the socket non-blocking */
#ifdef WIN32
rc = ioctlsocket(protocolActiveBackendSD, FIONBIO, &dwNoBlock);
#else /* UNIX */
rc = fcntl(protocolActiveBackendSD, F_SETFL, O_NONBLOCK);
#endif
if (rc == SOCKET_ERROR) {
if (wrapperData->isDebugging) {
log_printf(WRAPPER_SOURCE_PROTOCOL, LEVEL_DEBUG,
TEXT("socket ioctlsocket failed. (%s)"), getLastErrorText());
}
wrapperProtocolClose();
return;
}
/* We got an incoming connection, so close down the listener to prevent further connections. */
protocolStopServer();
}
/**
* Attempt to accept a connection from a JVM client.
*/
void protocolOpen() {
if (wrapperData->backendType == WRAPPER_BACKEND_TYPE_PIPE) {
protocolOpenPipe();
} else {
protocolOpenSocket();
}
}
void protocolClosePipe() {
#ifndef WIN32
size_t pipeNameLen;
TCHAR *pipeName;
pipeNameLen = 12 + 10 + 1 + 10 + 3;
#endif
if (protocolActiveServerPipeConnected) {
if (wrapperData->isDebugging) {
log_printf(WRAPPER_SOURCE_PROTOCOL, LEVEL_DEBUG, TEXT("Closing backend pipe."));
}
#ifdef WIN32
if (protocolActiveServerPipeIn != INVALID_HANDLE_VALUE && !CloseHandle(protocolActiveServerPipeIn)) {
#else
if (close(protocolActiveServerPipeIn) == -1) {
#endif
log_printf(WRAPPER_SOURCE_PROTOCOL, LEVEL_ERROR, TEXT("Failed to close backend pipe: %s"), getLastErrorText());
}
#ifdef WIN32
if (protocolActiveServerPipeOut != INVALID_HANDLE_VALUE && !CloseHandle(protocolActiveServerPipeOut)) {
#else
if (close(protocolActiveServerPipeOut) == -1) {
#endif
log_printf(WRAPPER_SOURCE_PROTOCOL, LEVEL_ERROR, TEXT("Failed to close backend pipe: %s"), getLastErrorText());
}
#ifndef WIN32
pipeName = malloc(sizeof(TCHAR) * (pipeNameLen + 1));
if (!pipeName) {
outOfMemory(TEXT("PCP"), 1);
return;
}
_sntprintf(pipeName, pipeNameLen, TEXT("/tmp/wrapper-%d-%d-in"), wrapperData->wrapperPID, wrapperData->jvmRestarts);
_tunlink(pipeName);
_sntprintf(pipeName, pipeNameLen, TEXT("/tmp/wrapper-%d-%d-out"), wrapperData->wrapperPID, wrapperData->jvmRestarts);
_tunlink(pipeName);
#endif
protocolActiveServerPipeConnected = FALSE;
protocolActiveServerPipeStarted = FALSE;
protocolActiveServerPipeIn = INVALID_HANDLE_VALUE;
protocolActiveServerPipeOut = INVALID_HANDLE_VALUE;
}
}
void protocolCloseSocket() {
int rc;
/* Close the socket. */
if (protocolActiveBackendSD != INVALID_SOCKET) {
if (wrapperData->isDebugging) {
log_printf(WRAPPER_SOURCE_PROTOCOL, LEVEL_DEBUG, TEXT("Closing backend socket."));
}
#ifdef WIN32
rc = closesocket(protocolActiveBackendSD);
#else /* UNIX */
rc = close(protocolActiveBackendSD);
#endif
if (rc == SOCKET_ERROR) {
if (wrapperData->isDebugging) {
log_printf(WRAPPER_SOURCE_PROTOCOL, LEVEL_DEBUG, TEXT("socket close failed. (%d)"), wrapperGetLastError());
}
}
protocolActiveBackendSD = INVALID_SOCKET;
}
}
/**
* Close the backend socket.
*/
void wrapperProtocolClose() {
if (wrapperData->backendType == WRAPPER_BACKEND_TYPE_PIPE) {
protocolClosePipe();
} else {
protocolCloseSocket();
}
}
/**
* Returns the name of a given function code for debug purposes.
*/
TCHAR *wrapperProtocolGetCodeName(char code) {
static TCHAR unknownBuffer[14];
TCHAR *name;
switch (code) {
case WRAPPER_MSG_START:
name = TEXT("START");
break;
case WRAPPER_MSG_STOP:
name = TEXT("STOP");
break;
case WRAPPER_MSG_RESTART:
name = TEXT("RESTART");
break;
case WRAPPER_MSG_PING:
name = TEXT("PING");
break;
case WRAPPER_MSG_STOP_PENDING:
name = TEXT("STOP_PENDING");
break;
case WRAPPER_MSG_START_PENDING:
name = TEXT("START_PENDING");
break;
case WRAPPER_MSG_STARTED:
name = TEXT("STARTED");
break;
case WRAPPER_MSG_STOPPED:
name = TEXT("STOPPED");
break;
case WRAPPER_MSG_KEY:
name = TEXT("KEY");
break;
case WRAPPER_MSG_BADKEY:
name = TEXT("BADKEY");
break;
case WRAPPER_MSG_LOW_LOG_LEVEL:
name = TEXT("LOW_LOG_LEVEL");
break;
case WRAPPER_MSG_PING_TIMEOUT: /* No longer used. */
name = TEXT("PING_TIMEOUT");
break;
case WRAPPER_MSG_SERVICE_CONTROL_CODE:
name = TEXT("SERVICE_CONTROL_CODE");
break;
case WRAPPER_MSG_PROPERTIES:
name = TEXT("PROPERTIES");
break;
case WRAPPER_MSG_LOG + LEVEL_DEBUG:
name = TEXT("LOG(DEBUG)");
break;
case WRAPPER_MSG_LOG + LEVEL_INFO:
name = TEXT("LOG(INFO)");
break;
case WRAPPER_MSG_LOG + LEVEL_STATUS:
name = TEXT("LOG(STATUS)");
break;
case WRAPPER_MSG_LOG + LEVEL_WARN:
name = TEXT("LOG(WARN)");
break;
case WRAPPER_MSG_LOG + LEVEL_ERROR:
name = TEXT("LOG(ERROR)");
break;
case WRAPPER_MSG_LOG + LEVEL_FATAL:
name = TEXT("LOG(FATAL)");
break;
case WRAPPER_MSG_LOG + LEVEL_ADVICE:
name = TEXT("LOG(ADVICE)");
break;
case WRAPPER_MSG_LOG + LEVEL_NOTICE:
name = TEXT("LOG(NOTICE)");
break;
case WRAPPER_MSG_LOGFILE:
name = TEXT("LOGFILE");
break;
case WRAPPER_MSG_APPEAR_ORPHAN: /* No longer used. */
name = TEXT("APPEAR_ORPHAN");
break;
case WRAPPER_MSG_PAUSE:
name = TEXT("PAUSE");
break;
case WRAPPER_MSG_RESUME:
name = TEXT("RESUME");
break;
case WRAPPER_MSG_GC:
name = TEXT("GC");
break;
default:
_sntprintf(unknownBuffer, 14, TEXT("UNKNOWN(%d)"), code);
name = unknownBuffer;
break;
}
return name;
}
/* Mutex for syncronization of the wrapperProtocolFunction function. */
#ifdef WIN32
HANDLE protocolMutexHandle = NULL;
#else
pthread_mutex_t protocolMutex = PTHREAD_MUTEX_INITIALIZER;
#endif
/** Obtains a lock on the protocol mutex. */
int lockProtocolMutex() {
#ifdef WIN32
switch (WaitForSingleObject(protocolMutexHandle, INFINITE)) {
case WAIT_ABANDONED:
_tprintf(TEXT("Protocol mutex was abandoned.\n"));
fflush(NULL);
return -1;
case WAIT_FAILED:
_tprintf(TEXT("Protocol mutex wait failed.\n"));
fflush(NULL);
return -1;
case WAIT_TIMEOUT:
_tprintf(TEXT("Protocol mutex wait timed out.\n"));
fflush(NULL);
return -1;
default:
/* Ok */
break;
}
#else
if (pthread_mutex_lock(&protocolMutex)) {
_tprintf(TEXT("Failed to lock the Protocol mutex. %s\n"), getLastErrorText());
return -1;
}
#endif
return 0;
}
/** Releases a lock on the protocol mutex. */
int releaseProtocolMutex() {
#ifdef WIN32
if (!ReleaseMutex(protocolMutexHandle)) {
_tprintf(TEXT("Failed to release Protocol mutex. %s\n"), getLastErrorText());
fflush(NULL);
return -1;
}
#else
if (pthread_mutex_unlock(&protocolMutex)) {
_tprintf(TEXT("Failed to unlock the Protocol mutex. %s\n"), getLastErrorText());
return -1;
}
#endif
return 0;
}
size_t protocolSendBufferSize = 0;
char *protocolSendBuffer = NULL;
/**
* Sends a command to the JVM process.
*
* @param function The command to send. (This is intentionally an 8-bit char.)
* @param message Message to send along with the command.
*
* @return TRUE if there were any problems.
*/
int wrapperProtocolFunction(char function, const TCHAR *messageW) {
int rc;
int cnt, inWritten;
size_t len;
const TCHAR *logMsgW;
char *messageMB = NULL;
int returnVal = FALSE;
int ok = TRUE;
/* It is important than there is never more than one thread allowed in here at a time. */
if (lockProtocolMutex()) {
return TRUE;
}
/* We don't want to show the full properties log message. It is quite long and distracting. */
if (function == WRAPPER_MSG_PROPERTIES) {
logMsgW = TEXT("(Property Values)");
} else {
logMsgW = messageW;
}
if (ok) {
/* We will be trasmitting a MultiByte string of characters. So we need to convert the messageW. */
if (messageW) {
#ifdef UNICODE
#ifdef WIN32
len = WideCharToMultiByte(CP_OEMCP, 0, messageW, -1, NULL, 0, NULL, NULL);
if (len <= 0) {
log_printf(WRAPPER_SOURCE_PROTOCOL, LEVEL_WARN,
TEXT("Invalid multibyte sequence in protocol message \"%s\" : %s"), messageW, getLastErrorText());
returnVal = TRUE;
ok = FALSE;
} else {
messageMB = malloc(len);
if (!messageMB) {
outOfMemory(TEXT("WPF"), 1);
returnVal = TRUE;
ok = FALSE;
} else {
WideCharToMultiByte(CP_OEMCP, 0, messageW, -1, messageMB, (int)len, NULL, NULL);
}
}
#else
len = wcstombs(NULL, messageW, 0) + 1;
if (len == (size_t)-1) {
log_printf(WRAPPER_SOURCE_PROTOCOL, LEVEL_WARN,
TEXT("Invalid multibyte sequence in protocol message \"%s\" : %s"), messageW, getLastErrorText());
returnVal = TRUE;
ok = FALSE;
} else {
messageMB = malloc(len);
if (!messageMB) {
outOfMemory(TEXT("WPF"), 2);
returnVal = TRUE;
ok = FALSE;
} else {
wcstombs(messageMB, messageW, len);
}
}
#endif
#else
len = _tscslen(messageW) + 1;
messageMB = malloc(len);
if (!messageMB) {
outOfMemory(TEXT("WPF"), 3);
returnVal = TRUE;
ok = FALSE;
} else {
_tcsncpy(messageMB, messageW, len);
}
#endif
} else {
messageMB = NULL;
}
}
if (ok) {
/* We need to construct a single string that will be used to transmit the command + message. */
if (messageMB) {
len = 1 + strlen(messageMB) + 1;
} else {
len = 2;
}
if (protocolSendBufferSize < len) {
if (protocolSendBuffer) {
free(protocolSendBuffer);
}
protocolSendBuffer = malloc(sizeof(char) * len);
if (!protocolSendBuffer) {
outOfMemory(TEXT("WPF"), 4);
returnVal = TRUE;
ok = FALSE;
} else {
/* Build the packet */
protocolSendBuffer[0] = function;
if (messageMB) {
strncpy(&(protocolSendBuffer[1]), messageMB, len - 1);
} else {
protocolSendBuffer[1] = 0;
}
}
}
if (messageMB) {
free(messageMB);
}
}
if (ok) {
if (((protocolActiveBackendSD == INVALID_SOCKET) && (wrapperData->backendType == WRAPPER_BACKEND_TYPE_SOCKET))
|| ((protocolActiveServerPipeConnected == FALSE) && (wrapperData->backendType == WRAPPER_BACKEND_TYPE_PIPE))) {
/* A socket was not opened */
if (wrapperData->isDebugging) {
log_printf(WRAPPER_SOURCE_PROTOCOL, LEVEL_DEBUG,
TEXT("socket not open, so packet not sent %s : %s"),
wrapperProtocolGetCodeName(function), (logMsgW == NULL ? TEXT("NULL") : logMsgW));
}
returnVal = TRUE;
} else {
if (wrapperData->isDebugging) {
if ((function == WRAPPER_MSG_PING) && messageW && (_tcsstr(messageW, TEXT("silent")) == messageW)) {
/*
log_printf(WRAPPER_SOURCE_PROTOCOL, LEVEL_DEBUG,
TEXT("send a silent ping packet %s : %s"),
wrapperProtocolGetCodeName(function), (logMsgW == NULL ? TEXT("NULL") : logMsgW));
*/
} else {
log_printf(WRAPPER_SOURCE_PROTOCOL, LEVEL_DEBUG,
TEXT("send a packet %s : %s"),
wrapperProtocolGetCodeName(function), (logMsgW == NULL ? TEXT("NULL") : logMsgW));
}
}
if (wrapperData->backendType == WRAPPER_BACKEND_TYPE_PIPE) {
#ifdef WIN32
if (WriteFile(protocolActiveServerPipeOut, protocolSendBuffer, sizeof(char) * (int)len, &inWritten, NULL) == FALSE) {
#else
if ((inWritten = write(protocolActiveServerPipeOut, protocolSendBuffer, sizeof(char) * (int)len)) == -1) {
#endif
log_printf(WRAPPER_SOURCE_PROTOCOL, LEVEL_FATAL, TEXT("Writing to the backend pipe failed (%d): %s"), wrapperGetLastError(), getLastErrorText());
return FALSE;
}
} else {
cnt = 0;
do {
if (cnt > 0) {
wrapperSleep(10);
}
rc = send(protocolActiveBackendSD, protocolSendBuffer, sizeof(char) * (int)len, 0);
cnt++;
} while ((rc == SOCKET_ERROR) && (wrapperGetLastError() == EWOULDBLOCK) && (cnt < 200));
if (rc == SOCKET_ERROR) {
if (wrapperGetLastError() == EWOULDBLOCK) {
log_printf(WRAPPER_SOURCE_PROTOCOL, LEVEL_WARN, TEXT(
"socket send failed. Blocked for 2 seconds. %s"),
getLastErrorText());
#ifdef WIN32
} else if (wrapperGetLastError() == WSAECONNRESET) {
log_printf(WRAPPER_SOURCE_PROTOCOL, LEVEL_ERROR, TEXT(
"socket send failed. %s"), getLastErrorText());
#endif
} else {
if (wrapperData->isDebugging) {
log_printf(WRAPPER_SOURCE_PROTOCOL, LEVEL_DEBUG, TEXT(
"socket send failed. %s"), getLastErrorText());
}
}
wrapperProtocolClose();
returnVal = TRUE;
} else {
returnVal = FALSE;
}
}
}
}
/* Always make sure the mutex is released. */
if (releaseProtocolMutex()) {
returnVal = TRUE;
}
return returnVal;
}
/**
* Checks the status of the server backend.
*
* The backend will be initialized if the JVM is in a state where it should
* be up, otherwise the backend will be left alone.
*
* If the forceOpen flag is set then an attempt will be made to initialize
* the backend regardless of the JVM state.
*
* Returns TRUE if the backend is open and ready on return, FALSE if not.
*/
int wrapperCheckServerBackend(int forceOpen) {
if (((wrapperData->backendType == WRAPPER_BACKEND_TYPE_SOCKET) && (protocolActiveServerSD == INVALID_SOCKET)) ||
((wrapperData->backendType == WRAPPER_BACKEND_TYPE_PIPE) && (protocolActiveServerPipeStarted == FALSE))) {
/* The backend is not currently open and needs to be started,
* unless the JVM is DOWN or in a state where it is not needed. */
if ((!forceOpen) &&
((wrapperData->jState == WRAPPER_JSTATE_DOWN_CLEAN) ||
(wrapperData->jState == WRAPPER_JSTATE_LAUNCH_DELAY) ||
(wrapperData->jState == WRAPPER_JSTATE_RESTART) ||
(wrapperData->jState == WRAPPER_JSTATE_STOPPED) ||
(wrapperData->jState == WRAPPER_JSTATE_KILLING) ||
(wrapperData->jState == WRAPPER_JSTATE_KILL) ||
(wrapperData->jState == WRAPPER_JSTATE_KILLED) ||
(wrapperData->jState == WRAPPER_JSTATE_DOWN_CHECK) ||
(wrapperData->jState == WRAPPER_JSTATE_DOWN_FLUSH))) {
/* The JVM is down or in a state where the backend is not needed. */
return FALSE;
} else {
/* The backend should be open, try doing so. */
protocolStartServer();
if (((wrapperData->backendType == WRAPPER_BACKEND_TYPE_SOCKET) && (protocolActiveServerSD == INVALID_SOCKET)) ||
((wrapperData->backendType == WRAPPER_BACKEND_TYPE_PIPE) && (protocolActiveServerPipeStarted == FALSE))) {
/* Failed. */
return FALSE;
} else {
return TRUE;
}
}
} else {
/* Backend is ready. */
return TRUE;
}
}
/**
* Simple function to parse hexidecimal numbers into a TICKS
*/
TICKS hexToTICKS(TCHAR *buffer) {
TICKS value = 0;
TCHAR c;
int pos = 0;
while (TRUE) {
c = buffer[pos];
if ((c >= TEXT('a')) && (c <= TEXT('f'))) {
value = (value << 4) + (10 + c - TEXT('a'));
} else if ((c >= TEXT('A')) && (c <= TEXT('F'))) {
value = (value << 4) + (10 + c - TEXT('A'));
} else if ((c >= TEXT('0')) && (c <= TEXT('9'))) {
value = (value << 4) + (c - TEXT('0'));
} else {
/* Any other character or null is the end of the number. */
return value;
}
pos++;
}
}
/**
* Read any data sent from the JVM. This function will loop and read as many
* packets are available. The loop will only be allowed to go for 250ms to
* ensure that other functions are handled correctly.
*
* Returns 0 if all available data has been read, 1 if more data is waiting.
*/
int wrapperProtocolRead() {
char c;
char code;
int len;
#ifdef WIN32
int maxlen;
#endif
int pos;
TCHAR *tc;
int err;
struct timeb timeBuffer;
time_t startTime;
int startTimeMillis;
time_t now;
int nowMillis;
time_t durr;
wrapperGetCurrentTime(&timeBuffer);
startTime = now = timeBuffer.time;
startTimeMillis = nowMillis = timeBuffer.millitm;
/*
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_DEBUG, TEXT("now=%ld, nowMillis=%d"), now, nowMillis);
*/
while((durr = (now - startTime) * 1000 + (nowMillis - startTimeMillis)) < 250) {
/*
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_DEBUG, TEXT("durr=%ld"), durr);
*/
/* If we have an open client backend, then use it. */
if (((wrapperData->backendType == WRAPPER_BACKEND_TYPE_SOCKET) && (protocolActiveBackendSD == INVALID_SOCKET)) ||
((wrapperData->backendType == WRAPPER_BACKEND_TYPE_PIPE) && (protocolActiveServerPipeConnected == FALSE))) {
/* A Client backend is not open */
/* Is the server backend open? */
if (!wrapperCheckServerBackend(FALSE)) {
/* Backend is down. We can not read any packets. */
return 0;
}
/* Try accepting a connection */
protocolOpen();
if (((wrapperData->backendType == WRAPPER_BACKEND_TYPE_SOCKET) && (protocolActiveBackendSD == INVALID_SOCKET)) ||
((wrapperData->backendType == WRAPPER_BACKEND_TYPE_PIPE) && (protocolActiveServerPipeConnected == FALSE))) {
return 0;
}
}
if (wrapperData->backendType == WRAPPER_BACKEND_TYPE_SOCKET) {
/* Try receiving a packet code */
len = recv(protocolActiveBackendSD, (void*) &c, 1, 0);
if (len == SOCKET_ERROR) {
err = wrapperGetLastError();
if ((err != EWOULDBLOCK) && /* Windows - Would block. */
(err != EAGAIN)) { /* UNIX - Would block. */
if (wrapperData->isDebugging) {
log_printf(WRAPPER_SOURCE_PROTOCOL, LEVEL_DEBUG, TEXT("socket read failed. (%s)"), getLastErrorText());
}
wrapperProtocolClose();
}
return 0;
} else if (len != 1) {
if (wrapperData->isDebugging) {
log_printf(WRAPPER_SOURCE_PROTOCOL, LEVEL_DEBUG, TEXT("socket read no code (closed?)."));
}
wrapperProtocolClose();
return 0;
}
code = (char)c;
/* Read in any message */
pos = 0;
do {
len = recv(protocolActiveBackendSD, (void*) &c, 1, 0);
if (len == 1) {
if (c == 0) {
/* End of string */
len = 0;
} else if (pos < MAX_LOG_SIZE) {
packetBuffer[pos] = c;
pos++;
}
} else {
len = 0;
}
} while (len == 1);
/* terminate the string; */
packetBuffer[pos] = TEXT('\0');
} else if (wrapperData->backendType == WRAPPER_BACKEND_TYPE_PIPE) {
#ifdef WIN32
err = PeekNamedPipe(protocolActiveServerPipeIn, NULL, 0, NULL, &maxlen, NULL);
if ((err == 0) && (GetLastError() == ERROR_BROKEN_PIPE)) {
/* ERROR_BROKEN_PIPE - the client has closed the pipe. So most likely it just exited */
protocolActiveServerPipeIn = INVALID_HANDLE_VALUE;
}
if (maxlen == 0) {
/*no data available */
return 0;
}
if (ReadFile(protocolActiveServerPipeIn, &c, 1, &len, NULL) == TRUE || GetLastError() == ERROR_MORE_DATA) {
code = (char)c;
--maxlen;
pos = 0;
do {
ReadFile(protocolActiveServerPipeIn, &c, 1, &len, NULL);
if (len == 1) {
if (c == 0) {
/* End of string */
len = 0;
} else if (pos < MAX_LOG_SIZE) {
packetBuffer[pos] = c;
pos++;
}
} else {
len = 0;
}
} while (len == 1 && maxlen-- >= 0);
packetBuffer[pos] = TEXT('\0');
} else {
if (GetLastError() == ERROR_INVALID_HANDLE) {
return 0;
} else {
wrapperProtocolClose();
return 0;
}
}
#else
len = read(protocolActiveServerPipeIn, (void*) &c, 1);
if (len == SOCKET_ERROR) {
err = wrapperGetLastError();
if ((err != EWOULDBLOCK) && /* Windows - Would block. */
(err != EAGAIN)) { /* UNIX - Would block. */
if (wrapperData->isDebugging) {
log_printf(WRAPPER_SOURCE_PROTOCOL, LEVEL_DEBUG, TEXT("pipe read failed. (%s)"), getLastErrorText());
}
wrapperProtocolClose();
}
return 0;
} else if (len == 0) {
/*nothing read...*/
return 0;
}
code = (char)c;
/* Read in any message */
pos = 0;
do {
len = read(protocolActiveServerPipeIn, (void*) &c, 1);
if (len == 1) {
if (c == 0) {
/* End of string */
len = 0;
} else if (pos < MAX_LOG_SIZE) {
packetBuffer[pos] = c;
pos++;
}
} else {
len = 0;
}
} while (len == 1);
/* terminate the string; */
packetBuffer[pos] = TEXT('\0');
#endif
} else {
return 0;
}
if (wrapperData->isDebugging) {
if ((code == WRAPPER_MSG_PING) && (_tcsstr(packetBuffer, TEXT("silent")) == packetBuffer)) {
/*
log_printf(WRAPPER_SOURCE_PROTOCOL, LEVEL_DEBUG, TEXT("read a silent ping packet %s : %s"),
wrapperProtocolGetCodeName(code), packetBuffer);
*/
} else {
log_printf(WRAPPER_SOURCE_PROTOCOL, LEVEL_DEBUG, TEXT("read a packet %s : %s"),
wrapperProtocolGetCodeName(code), packetBuffer);
}
}
switch (code) {
case WRAPPER_MSG_STOP:
wrapperStopRequested(_ttoi(packetBuffer));
break;
case WRAPPER_MSG_RESTART:
wrapperRestartRequested();
break;
case WRAPPER_MSG_PING:
/* Because all versions of the wrapper.jar simply bounce back the ping message, the pingSendTicks should always exist. */
tc = _tcschr(packetBuffer, TEXT(' '));
if (tc) {
/* A pingSendTicks should exist. Parse the id following the space. It will be in the format 0xffffffff. */
wrapperPingResponded(hexToTICKS(&tc[1]), TRUE);
} else {
/* Should not happen, but just in case use the current ticks. */
wrapperPingResponded(wrapperGetTicks(), FALSE);
}
break;
case WRAPPER_MSG_STOP_PENDING:
wrapperStopPendingSignaled(_ttoi(packetBuffer));
break;
case WRAPPER_MSG_STOPPED:
wrapperStoppedSignaled();
break;
case WRAPPER_MSG_START_PENDING:
wrapperStartPendingSignaled(_ttoi(packetBuffer));
break;
case WRAPPER_MSG_STARTED:
wrapperStartedSignaled();
break;
case WRAPPER_MSG_KEY:
wrapperKeyRegistered(packetBuffer);
break;
case WRAPPER_MSG_LOG + LEVEL_DEBUG:
case WRAPPER_MSG_LOG + LEVEL_INFO:
case WRAPPER_MSG_LOG + LEVEL_STATUS:
case WRAPPER_MSG_LOG + LEVEL_WARN:
case WRAPPER_MSG_LOG + LEVEL_ERROR:
case WRAPPER_MSG_LOG + LEVEL_FATAL:
wrapperLogSignaled(code - WRAPPER_MSG_LOG, packetBuffer);
break;
case WRAPPER_MSG_APPEAR_ORPHAN:
/* No longer used. This is still here in case a mix of versions are used. */
break;
default:
if (wrapperData->isDebugging) {
log_printf(WRAPPER_SOURCE_PROTOCOL, LEVEL_DEBUG, TEXT("received unknown packet (%d:%s)"), code, packetBuffer);
}
break;
}
/* Get the time again */
wrapperGetCurrentTime(&timeBuffer);
now = timeBuffer.time;
nowMillis = timeBuffer.millitm;
}
/*
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_DEBUG, TEXT("done durr=%ld"), durr);
*/
if ((durr = (now - startTime) * 1000 + (nowMillis - startTimeMillis)) < 250) {
return 0;
} else {
return 1;
}
}
/******************************************************************************
* Wrapper inner methods.
*****************************************************************************/
/**
* IMPORTANT - Any logging done in here needs to be queued or it would cause a recursion problem.
*
* It is also critical that this is NEVER called from within the protocol function because it
* would cause a deadlock with the protocol semaphore. This means that it can never be called
* from within log_printf(...).
*/
void wrapperLogFileChanged(const TCHAR *logFile) {
if (wrapperData->isDebugging) {
log_printf_queue(TRUE, WRAPPER_SOURCE_WRAPPER, LEVEL_DEBUG, TEXT("active log file changed: %s"), logFile);
}
/* On startup, this function will always be called the first time the log file is set,
* we don't want to send the command in this case as it clutters the debug log output.
* Besides, the JVM will not be running anyway. */
if (wrapperData->jState != WRAPPER_JSTATE_DOWN_CLEAN) {
wrapperProtocolFunction(WRAPPER_MSG_LOGFILE, logFile);
}
}
/**
* Pre initialize the wrapper.
*/
int wrapperInitialize() {
TCHAR *retLocale;
#ifdef WIN32
int maxPathLen = _MAX_PATH;
#else
int maxPathLen = PATH_MAX;
#endif
/* Initialize the properties variable. */
properties = NULL;
/* Initialize the random seed. */
srand((unsigned)time(NULL));
/* Make sure all values are reliably set to 0. All required values should also be
* set below, but this extra step will protect against future changes. Some
* platforms appear to initialize maloc'd memory to 0 while others do not. */
wrapperData = malloc(sizeof(WrapperConfig));
if (!wrapperData) {
outOfMemory(TEXT("WI"), 1);
return 1;
}
memset(wrapperData, 0, sizeof(WrapperConfig));
/* Setup the initial values of required properties. */
wrapperData->configured = FALSE;
wrapperData->isConsole = TRUE;
wrapperSetWrapperState(WRAPPER_WSTATE_STARTING);
wrapperSetJavaState(WRAPPER_JSTATE_DOWN_CLEAN, 0, -1);
wrapperData->lastPingTicks = wrapperGetTicks();
wrapperData->lastLoggedPingTicks = wrapperGetTicks();
wrapperData->jvmCommand = NULL;
wrapperData->exitRequested = FALSE;
wrapperData->restartRequested = WRAPPER_RESTART_REQUESTED_INITIAL; /* The first JVM needs to be started. */
wrapperData->exitCode = 0;
wrapperData->jvmRestarts = 0;
wrapperData->jvmLaunchTicks = wrapperGetTicks();
wrapperData->failedInvocationCount = 0;
wrapperData->originalWorkingDir = NULL;
wrapperData->configFile = NULL;
wrapperData->workingDir = NULL;
wrapperData->outputFilterCount = 0;
wrapperData->confDir = NULL;
wrapperData->umask = -1;
wrapperData->language = NULL;
wrapperData->portAddress = NULL;
wrapperData->pingTimedOut = FALSE;
#ifdef WIN32
if (!(tickMutexHandle = CreateMutex(NULL, FALSE, NULL))) {
printf("Failed to create tick mutex. %s\n", getLastErrorText());
return 1;
}
/* Initialize control code queue. */
wrapperData->ctrlCodeQueue = malloc(sizeof(int) * CTRL_CODE_QUEUE_SIZE);
if (!wrapperData->ctrlCodeQueue) {
outOfMemory(TEXT("WI"), 2);
return 1;
}
wrapperData->ctrlCodeQueueWriteIndex = 0;
wrapperData->ctrlCodeQueueReadIndex = 0;
wrapperData->ctrlCodeQueueWrapped = FALSE;
#endif
if (initLogging(wrapperLogFileChanged)) {
return 1;
}
/* This will only be called by the main thread on startup.
* Immediately register this thread with the logger.
* This has to happen after the logging is initialized. */
logRegisterThread(WRAPPER_THREAD_MAIN);
setLogfilePath(TEXT("wrapper.log"), NULL, FALSE);
setLogfileRollMode(ROLL_MODE_SIZE);
setLogfileFormat(TEXT("LPTM"));
setLogfileLevelInt(LEVEL_DEBUG);
setLogfileAutoClose(FALSE);
setConsoleLogFormat(TEXT("LPM"));
setConsoleLogLevelInt(LEVEL_DEBUG);
setConsoleFlush(TRUE); /* Always flush immediately until the logfile is configured to make sure that problems are in a consistent location. */
setSyslogLevelInt(LEVEL_NONE);
#ifdef _DEBUG
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT("Wrapper Initializing... Minimum logging configured."));
#endif
/** Remember what the initial user directory was when the Wrapper was launched. */
wrapperData->initialPath = (TCHAR *)malloc((maxPathLen + 1) * sizeof(TCHAR));
if (!wrapperData->initialPath) {
outOfMemory(TEXT("WI"), 3);
return 1;
} else {
if (!(wrapperData->initialPath = _tgetcwd((TCHAR*)wrapperData->initialPath, maxPathLen + 1))) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_FATAL, TEXT("Failed to get the initial directory. (%s)"), getLastErrorText());
return 1;
}
}
/* Set a variable to the initial working directory. */
setEnv(TEXT("WRAPPER_INIT_DIR"), wrapperData->initialPath, ENV_SOURCE_WRAPPER);
#ifdef WIN32
if (!(protocolMutexHandle = CreateMutex(NULL, FALSE, NULL))) {
_tprintf(TEXT("Failed to create protocol mutex. %s\n"), getLastErrorText());
fflush(NULL);
return 1;
}
#endif
/* This is a sanity check to make sure that the datatype used for tick counts is correct. */
if (sizeof(TICKS) != 4) {
printf("Tick size incorrect %d != 4\n", (int)sizeof(TICKS));
fflush(NULL);
return 1;
}
/* Set the default locale here so any startup error messages will have a chance of working.
* We will go back and try to set the actual locale again later once it is configured. */
retLocale = _tsetlocale(LC_ALL, TEXT(""));
if (retLocale) {
/* Success. */
#ifdef _DEBUG
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT("tsetlocale() returned \"%s\""), retLocale);
#endif
#if !defined(WIN32) && defined(UNICODE)
free(retLocale);
#endif
} else {
/* Failure. */
#ifdef _DEBUG
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT("tsetlocale() returned NULL"));
#endif
}
if (loadEnvironment()) {
return 1;
}
#ifdef _DEBUG
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT("Wrapper Initialization complete."));
#endif
return 0;
}
void wrapperDataDispose() {
int i;
if (wrapperData->workingDir) {
free(wrapperData->workingDir);
wrapperData->workingDir = NULL;
}
if (wrapperData->originalWorkingDir) {
free(wrapperData->originalWorkingDir);
wrapperData->originalWorkingDir = NULL;
}
if (wrapperData->configFile) {
free(wrapperData->configFile);
wrapperData->configFile = NULL;
}
if (wrapperData->initialPath) {
free(wrapperData->initialPath);
wrapperData->initialPath = NULL;
}
if (wrapperData->classpath) {
free(wrapperData->classpath);
wrapperData->classpath = NULL;
}
if (wrapperData->portAddress) {
free(wrapperData->portAddress);
wrapperData->portAddress = NULL;
}
#ifdef WIN32
if (wrapperData->jvmCommand) {
free(wrapperData->jvmCommand);
wrapperData->jvmCommand = NULL;
}
if (wrapperData->userName) {
free(wrapperData->userName);
wrapperData->userName = NULL;
}
if (wrapperData->domainName) {
free(wrapperData->domainName);
wrapperData->domainName = NULL;
}
if (wrapperData->ntServiceLoadOrderGroup) {
free(wrapperData->ntServiceLoadOrderGroup);
wrapperData->ntServiceLoadOrderGroup = NULL;
}
if (wrapperData->ntServiceDependencies) {
free(wrapperData->ntServiceDependencies);
wrapperData->ntServiceDependencies = NULL;
}
if (wrapperData->ntServiceAccount) {
free(wrapperData->ntServiceAccount);
wrapperData->ntServiceAccount = NULL;
}
if (wrapperData->ntServicePassword) {
free(wrapperData->ntServicePassword);
wrapperData->ntServicePassword = NULL;
}
if (wrapperData->ctrlCodeQueue) {
free(wrapperData->ctrlCodeQueue);
wrapperData->ctrlCodeQueue = NULL;
}
#else
if(wrapperData->jvmCommand) {
for (i = 0; wrapperData->jvmCommand[i] != NULL; i++) {
free(wrapperData->jvmCommand[i]);
wrapperData->jvmCommand[i] = NULL;
}
free(wrapperData->jvmCommand);
wrapperData->jvmCommand = NULL;
}
#endif
if (wrapperData->outputFilterCount > 0) {
for (i = 0; i < wrapperData->outputFilterCount; i++) {
if (wrapperData->outputFilters[i]) {
free(wrapperData->outputFilters[i]);
wrapperData->outputFilters[i] = NULL;
}
if (wrapperData->outputFilterActionLists[i]) {
free(wrapperData->outputFilterActionLists[i]);
wrapperData->outputFilterActionLists[i] = NULL;
}
}
if (wrapperData->outputFilters) {
free(wrapperData->outputFilters);
wrapperData->outputFilters = NULL;
}
if (wrapperData->outputFilterActionLists) {
free(wrapperData->outputFilterActionLists);
wrapperData->outputFilterActionLists = NULL;
}
if (wrapperData->outputFilterMessages) {
free(wrapperData->outputFilterMessages);
wrapperData->outputFilterMessages = NULL;
}
if (wrapperData->outputFilterAllowWildFlags) {
free(wrapperData->outputFilterAllowWildFlags);
wrapperData->outputFilterAllowWildFlags = NULL;
}
if (wrapperData->outputFilterMinLens) {
free(wrapperData->outputFilterMinLens);
wrapperData->outputFilterMinLens = NULL;
}
}
if (wrapperData->pidFilename) {
free(wrapperData->pidFilename);
wrapperData->pidFilename = NULL;
}
if (wrapperData->lockFilename) {
free(wrapperData->lockFilename);
wrapperData->lockFilename = NULL;
}
if (wrapperData->javaPidFilename) {
free(wrapperData->javaPidFilename);
wrapperData->javaPidFilename = NULL;
}
if (wrapperData->javaIdFilename) {
free(wrapperData->javaIdFilename);
wrapperData->javaIdFilename = NULL;
}
if (wrapperData->statusFilename) {
free(wrapperData->statusFilename);
wrapperData->statusFilename = NULL;
}
if (wrapperData->javaStatusFilename) {
free(wrapperData->javaStatusFilename);
wrapperData->javaStatusFilename = NULL;
}
if (wrapperData->commandFilename) {
free(wrapperData->commandFilename);
wrapperData->commandFilename = NULL;
}
if (wrapperData->consoleTitle) {
free(wrapperData->consoleTitle);
wrapperData->consoleTitle = NULL;
}
if (wrapperData->serviceName) {
free(wrapperData->serviceName);
wrapperData->serviceName = NULL;
}
if (wrapperData->serviceDisplayName) {
free(wrapperData->serviceDisplayName);
wrapperData->serviceDisplayName = NULL;
}
if (wrapperData->serviceDescription) {
free(wrapperData->serviceDescription);
wrapperData->serviceDescription = NULL;
}
if (wrapperData->hostName) {
free(wrapperData->hostName);
wrapperData->hostName = NULL;
}
if (wrapperData->confDir) {
free(wrapperData->confDir);
wrapperData->confDir = NULL;
}
if (wrapperData->argConfFileDefault && wrapperData->argConfFile) {
free(wrapperData->argConfFile);
wrapperData->argConfFile = NULL;
}
if (wrapperData) {
free(wrapperData);
wrapperData = NULL;
}
}
/** Common wrapper cleanup code. */
void wrapperDispose() {
/* Make sure not to dispose twice. This should not happen, but check for safety. */
if (disposed) {
_tprintf(TEXT("wrapperDispose was called more than once."));
return;
}
disposed = TRUE;
#ifdef WIN32
if (protocolMutexHandle) {
if (!CloseHandle(protocolMutexHandle)) {
_tprintf(TEXT("Unable to close protocol mutex handle. %s\n"), getLastErrorText());
fflush(NULL);
}
}
/* Make sure that the startup thread has completed. */
disposeStartup();
#endif
/* Clean up the javaIO thread. This should be done before the timer thread. */
if (wrapperData->useJavaIOThread) {
disposeJavaIO();
}
/* Clean up the timer thread. */
if (!wrapperData->useSystemTime) {
disposeTimer();
}
/* Clean up the properties structure. */
disposeProperties(properties);
properties = NULL;
disposeEnvironment();
if (wrapperChildWorkBuffer) {
free(wrapperChildWorkBuffer);
wrapperChildWorkBuffer = NULL;
}
if (protocolSendBuffer) {
free(protocolSendBuffer);
protocolSendBuffer = NULL;
}
/* Clean up the logging system. Should happen near last. */
disposeLogging();
/* clean up the main wrapper data structure. This must be done last.*/
wrapperDataDispose();
}
/**
* Returns the file name base as a newly malloced TCHAR *. The resulting
* base file name will have any path and extension stripped.
*
* baseName should be long enough to always contain the base name.
* (_tcslen(fileName) + 1) is safe.
*/
void wrapperGetFileBase(const TCHAR *fileName, TCHAR *baseName) {
const TCHAR *start;
const TCHAR *end;
const TCHAR *c;
start = fileName;
end = &fileName[_tcslen(fileName)];
/* Strip off any path. */
#ifdef WIN32
c = _tcsrchr(start, TEXT('\\'));
#else
c = _tcsrchr(start, TEXT('/'));
#endif
if (c) {
start = &c[1];
}
/* Strip off any extension. */
c = _tcsrchr(start, TEXT('.'));
if (c) {
end = c;
}
/* Now create the new base name. */
_tcsncpy(baseName, start, end - start);
baseName[end - start] = TEXT('\0');
}
/**
* Returns a buffer containing a multi-line version banner. It is the responsibility of the caller
* to make sure it gets freed.
*/
TCHAR *generateVersionBanner() {
TCHAR *banner = TEXT("Java Service Wrapper %s Edition %s-bit %s\n Copyright (C) 1999-%s Tanuki Software, Ltd. All Rights Reserved.\n http://wrapper.tanukisoftware.com");
TCHAR *product = TEXT("Community");
TCHAR *copyright = TEXT("2013");
TCHAR *buffer;
size_t len;
len = _tcslen(banner) + _tcslen(product) + _tcslen(wrapperBits) + _tcslen(wrapperVersionRoot) + _tcslen(copyright) + 1;
buffer = malloc(sizeof(TCHAR) * len);
if (!buffer) {
outOfMemory(TEXT("GVB"), 1);
return NULL;
}
_sntprintf(buffer, len, banner, product, wrapperBits, wrapperVersionRoot, copyright);
return buffer;
}
/**
* Output the version.
*/
void wrapperVersionBanner() {
TCHAR *banner = generateVersionBanner();
if (!banner) {
return;
}
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, banner);
free(banner);
}
/**
* Output the application usage.
*/
void wrapperUsage(TCHAR *appName) {
TCHAR *confFileBase;
confFileBase = malloc(sizeof(TCHAR) * (_tcslen(appName) + 1));
if (!confFileBase) {
outOfMemory(TEXT("WU"), 1);
return;
}
wrapperGetFileBase(appName, confFileBase);
setSimpleLogLevels();
wrapperVersionBanner();
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT(""));
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT("Usage:"));
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT(" %s [configuration properties] [...]"), appName);
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT(" %s [configuration properties] [...]"), appName);
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT(" ( implicitly '-c')"));
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT(" %s "), appName);
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT(" ( implicitly '%s.conf')"), confFileBase);
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT(" %s"), appName);
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT(" ( implicitly '-c' and '%s.conf')"), confFileBase);
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT(""));
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT("where can be one of:"));
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT(" -c --console run as a Console application"));
#ifdef WIN32
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT(" -t --start starT an NT service"));
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT(" -a --pause pAuse a started NT service"));
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT(" -e --resume rEsume a paused NT service"));
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT(" -p --stop stoP a running NT service"));
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT(" -i --install Install as an NT service"));
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT(" -it --installstart Install and sTart as an NT service"));
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT(" -r --remove Uninstall/Remove as an NT service"));
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT(" -l= --controlcode= send a user controL Code to a running NT service"));
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT(" -d --dump request a thread Dump"));
/** Return mask: installed:1 running:2 interactive:4 automatic:8 manual:16 disabled:32 */
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT(" -q --query Query the current status of the service"));
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT(" -qs --querysilent Silently Query the current status of the service"));
/* Omit '-s' option from help as it is only used by the service manager. */
/*log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT(" -s --service used by service manager")); */
#endif
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT(" -v --version print the wrapper's version information."));
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT(" -? --help print this help message"));
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT(" -- mark the end of Wrapper arguments. All arguments after the\n '--' will be passed through unmodified to the java application."));
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT(""));
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT(" is the wrapper.conf to use. Name must be absolute or relative"));
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT(" to the location of %s"), appName);
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT(""));
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT("[configuration properties] are configuration name-value pairs which override values"));
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT(" in wrapper.conf. For example:"));
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT(" wrapper.debug=true"));
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT(""));
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT(" Please note that any file references must be absolute or relative to the location\n of the Wrapper executable."));
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT(""));
free(confFileBase);
}
/**
* Parse the main arguments.
*
* Returns FALSE if the application should exit with an error. A message will
* already have been logged.
*/
int wrapperParseArguments(int argc, TCHAR **argv) {
TCHAR *argConfFileBase;
TCHAR *c;
int delimiter, wrapperArgCount;
wrapperData->javaArgValueCount = 0;
delimiter = 1;
if (argc > 1
) {
for (delimiter = 0; delimiter < argc ; delimiter++) {
if ( _tcscmp(argv[delimiter], TEXT("--")) == 0) {
#if !defined(WIN32) && defined(UNICODE)
free(argv[delimiter]);
#endif
argv[delimiter] = NULL;
wrapperData->javaArgValueCount = argc - delimiter - 1;
if (delimiter + 1 < argc) {
wrapperData->javaArgValues = &argv[delimiter + 1];
}
break;
}
}
}
wrapperArgCount = delimiter ;
if (wrapperArgCount > 1) {
/* Store the name of the binary.*/
wrapperData->argBinary = argv[0];
if (argv[1][0] == TEXT('-')) {
/* Syntax 1 or 3 */
/* A command appears to have been specified. */
wrapperData->argCommand = &argv[1][1]; /* Strip off the '-' */
if (wrapperData->argCommand[0] == TEXT('\0')) {
wrapperUsage(argv[0]);
return FALSE;
}
/* Does the argument have a value? */
c = _tcschr(wrapperData->argCommand, TEXT('='));
if (c == NULL) {
wrapperData->argCommandArg = NULL;
} else {
wrapperData->argCommandArg = (TCHAR *)(c + 1);
c[0] = TEXT('\0');
}
if (wrapperArgCount > 2) {
if (_tcsncmp(wrapperData->argCommand, TEXT("-translate"), 5) == 0) {
if (wrapperArgCount > 3) {
wrapperData->argConfFile = argv[3];
wrapperData->argCount = wrapperArgCount - 4;
wrapperData->argValues = &argv[4];
}
return TRUE;
}
/* Syntax 1 */
/* A command and conf file were specified. */
wrapperData->argConfFile = argv[2];
wrapperData->argCount = wrapperArgCount - 3;
wrapperData->argValues = &argv[3];
} else {
/* Syntax 3 */
/* Only a command was specified. Assume a default config file name. */
argConfFileBase = malloc(sizeof(TCHAR) * (_tcslen(argv[0]) + 1));
if (!argConfFileBase) {
outOfMemory(TEXT("WPA"), 1);
return FALSE;
}
wrapperGetFileBase(argv[0], argConfFileBase);
/* The following malloc is only called once, but is never freed. */
wrapperData->argConfFile = malloc((_tcslen(argConfFileBase) + 5 + 1) * sizeof(TCHAR));
if (!wrapperData->argConfFile) {
outOfMemory(TEXT("WPA"), 2);
free(argConfFileBase);
return FALSE;
}
_sntprintf(wrapperData->argConfFile, _tcslen(argConfFileBase) + 5 + 1, TEXT("%s.conf"), argConfFileBase);
free(argConfFileBase);
wrapperData->argConfFileDefault = TRUE;
wrapperData->argCount = wrapperArgCount - 2;
wrapperData->argValues = &argv[2];
}
} else {
/* Syntax 2 */
/* A command was not specified, but there may be a config file. */
wrapperData->argCommand = TEXT("c");
wrapperData->argCommandArg = NULL;
wrapperData->argConfFile = argv[1];
wrapperData->argCount = wrapperArgCount - 2;
wrapperData->argValues = &argv[2];
}
} else {
/* Systax 4 */
/* A config file was not specified. Assume a default config file name. */
wrapperData->argCommand = TEXT("c");
wrapperData->argCommandArg = NULL;
argConfFileBase = malloc(sizeof(TCHAR) * (_tcslen(argv[0]) + 1));
if (!argConfFileBase) {
outOfMemory(TEXT("WPA"), 3);
return FALSE;
}
wrapperGetFileBase(argv[0], argConfFileBase);
/* The following malloc is only called once, but is never freed. */
wrapperData->argConfFile = malloc((_tcslen(argConfFileBase) + 5 + 1) * sizeof(TCHAR));
if (!wrapperData->argConfFile) {
outOfMemory(TEXT("WPA"), 4);
free(argConfFileBase);
return FALSE;
}
_sntprintf(wrapperData->argConfFile, _tcslen(argConfFileBase) + 5 + 1, TEXT("%s.conf"), argConfFileBase);
free(argConfFileBase);
wrapperData->argConfFileDefault = TRUE;
wrapperData->argCount = wrapperArgCount - 1;
wrapperData->argValues = &argv[1];
}
return TRUE;
}
/**
* Performs the specified action,
*
* @param actionList An array of action Ids ending with a value ACTION_LIST_END.
* Negative values are standard actions, positive are user
* custom events.
* @param triggerMsg The reason the actions are being fired.
* @param actionSourceCode Tracks where the action originated.
* @param logForActionNone Flag stating whether or not a message should be logged
* for the NONE action.
* @param exitCode Error code to use in case the action results in a shutdown.
*/
void wrapperProcessActionList(int *actionList, const TCHAR *triggerMsg, int actionSourceCode, int logForActionNone, int exitCode) {
int i;
int action;
if (actionList) {
i = 0;
while ((action = actionList[i]) != ACTION_LIST_END) {
switch(action) {
case ACTION_RESTART:
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT("%s Restarting JVM."), triggerMsg);
wrapperRestartProcess();
break;
case ACTION_SHUTDOWN:
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT("%s Shutting down."), triggerMsg);
wrapperStopProcess(exitCode, FALSE);
break;
case ACTION_DUMP:
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT("%s Requesting thread dump."), triggerMsg);
wrapperRequestDumpJVMState();
break;
case ACTION_DEBUG:
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT("%s Debugging."), triggerMsg);
break;
case ACTION_PAUSE:
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT("%s Pausing..."), triggerMsg);
wrapperPauseProcess(actionSourceCode);
break;
case ACTION_RESUME:
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT("%s Resuming..."), triggerMsg);
wrapperResumeProcess(actionSourceCode);
break;
#if defined(MACOSX)
case ACTION_ADVICE_NIL_SERVER:
if (wrapperData->isAdviserEnabled) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_ADVICE, TEXT(""));
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_ADVICE, TEXT(
"--------------------------------------------------------------------"));
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_ADVICE, TEXT(
"Advice:"));
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_ADVICE, TEXT(
"MACOSX is known to have problems displaying GUIs from processes\nrunning as a daemon launched from launchd. The above\n\"Returning nil _server\" means that you are encountering this\nproblem. This usually results in a long timeout which is affecting\nthe performance of your application."));
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_ADVICE, TEXT(
"--------------------------------------------------------------------"));
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_ADVICE, TEXT(""));
}
break;
#endif
case ACTION_NONE:
if (logForActionNone) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT("%s"), triggerMsg);
}
/* Do nothing but masks later filters */
break;
case ACTION_SUCCESS:
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT("%s Application has signalled success, consider this application started successful..."), triggerMsg);
wrapperData->failedInvocationCount = 0;
break;
case ACTION_GC:
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT("%s Requesting GC..."), triggerMsg);
wrapperRequestJVMGC(actionSourceCode);
break;
default:
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_WARN, TEXT("Unknown action type: %d"), action);
break;
}
i++;
}
}
}
/**
* Function that will recursively attempt to match two strings where the
* pattern can contain '?' or '*' wildcard characters. This function requires
* that the pattern be matched from the beginning of the text.
*
* @param text Text to be searched.
* @param textLen Length of the text.
* @param pattern Pattern to search for.
* @param patternLen Length of the pattern.
* @param minTextLen Minimum number of characters that the text needs to possibly match the pattern.
*
* @return TRUE if found, FALSE otherwise.
*
* 1) text=abcdefg textLen=7 pattern=a*d*efg patternLen=7 minTextLen=5
* 1.1) text=bcdefg textLen=6 pattern=d*efg patternLen=5 minTextLen=4
* 1.2) text=cdefg textLen=5 pattern=d*efg patternLen=5 minTextLen=4
* 1.3) text=defg textLen=4 pattern=d*efg patternLen=5 minTextLen=4
* 1.3.1) text=efg textLen=3 pattern=efg patternLen=3 minTextLen=3
*/
int wildcardMatchInner(const TCHAR *text, size_t textLen, const TCHAR *pattern, size_t patternLen, size_t minTextLen) {
size_t textIndex;
size_t patternIndex;
TCHAR patternChar;
size_t textIndex2;
TCHAR textChar;
/*log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_INFO, TEXT(" wildcardMatchInner(\"%s\", %d, \"%s\", %d, %d)"), text, textLen, pattern, patternLen, minTextLen);*/
textIndex = 0;
patternIndex = 0;
while ((textIndex < textLen) && (patternIndex < patternLen)) {
patternChar = pattern[patternIndex];
if (patternChar == TEXT('*')) {
/* The pattern '*' can match 0 or more characters. This requires a bit of recursion to work it out. */
textIndex2 = textIndex;
/* Loop over all possible starting locations. We know how many characters are needed to match (minTextLen - patternIndex) so we can stop there. */
while (textIndex2 < textLen - (minTextLen - (patternIndex + 1))) {
if (wildcardMatchInner(&(text[textIndex2]), textLen - textIndex2, &(pattern[patternIndex + 1]), patternLen - (patternIndex + 1), minTextLen - patternIndex)) {
/* Got a match in recursion. */
/*log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_INFO, TEXT(" wildcardMatchInner(\"%s\", %d, \"%s\", %d, %d) -> HERE1 textIndex=%d, patternIndex=%d, textIndex2=%d TRUE"), text, textLen, pattern, patternLen, minTextLen, textIndex, patternIndex, textIndex2);*/
return TRUE;
} else {
/* Failed to match. Try matching one more character against the '*'. */
textIndex2++;
}
}
/* If we get here then all possible starting locations failed. */
/*log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_INFO, TEXT(" wildcardMatchInner(\"%s\", %d, \"%s\", %d, %d) -> HERE2 textIndex=%d, patternIndex=%d, textIndex2=%d FALSE"), text, textLen, pattern, patternLen, minTextLen, textIndex, patternIndex, textIndex2);*/
return FALSE;
} else if (patternChar == TEXT('?')) {
/* Match any character. */
patternIndex++;
textIndex++;
} else {
textChar = text[textIndex];
if (patternChar == textChar) {
/* Characters match. */
patternIndex++;
textIndex++;
} else {
/* Characters do not match. We are done. */
/*log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_INFO, TEXT(" wildcardMatchInner(\"%s\", %d, \"%s\", %d, %d) -> HERE3 textIndex=%d, patternIndex=%d FALSE"), text, textLen, pattern, patternLen, minTextLen, textIndex, patternIndex);*/
return FALSE;
}
}
}
/* It is ok if there are text characters left over as we only need to match a substring, not the whole string. */
/* If there are any pattern chars left. Make sure that they are all wildcards. */
while (patternIndex < patternLen) {
if (pattern[patternIndex] != TEXT('*')) {
/*log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_INFO, TEXT(" wildcardMatchInner(\"%s\", %d, \"%s\", %d, %d) -> HERE4 pattern[%d]=%c FALSE"), text, textLen, pattern, patternLen, minTextLen, patternIndex, pattern[patternIndex]);*/
return FALSE;
}
patternIndex++;
}
/*log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_INFO, TEXT(" wildcardMatchInner(\"%s\", %d, \"%s\", %d, %d) -> HERE5 textIndex=%d, patternIndex=%d TRUE"), text, textLen, pattern, patternLen, minTextLen, textIndex, patternIndex);*/
return TRUE;
}
/**
* Test function to pause the current thread for the specified amount of time.
* This is used to test how the rest of the Wrapper behaves when a particular
* thread blocks for any reason.
*
* @param pauseTime Number of seconds to pause for. -1 will pause indefinitely.
* @param threadName Name of the thread that will be logged prior to pausing.
*/
void wrapperPauseThread(int pauseTime, const TCHAR *threadName) {
int i;
if (pauseTime > 0) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_WARN, TEXT("Pausing the \"%s\" thread for %d seconds..."), threadName, pauseTime);
for (i = 0; i < pauseTime; i++) {
wrapperSleep(1000);
}
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_WARN, TEXT("Resuming the \"%s\" thread..."), threadName);
} else if (pauseTime < 0) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_WARN, TEXT("Pausing the \"%s\" thread indefinitely."), threadName);
while(TRUE) {
wrapperSleep(1000);
}
}
}
/**
* Function that will recursively attempt to match two strings where the
* pattern can contain '?' or '*' wildcard characters.
*
* @param text Text to be searched.
* @param pattern Pattern to search for.
* @param patternLen Length of the pattern.
* @param minTextLen Minimum number of characters that the text needs to possibly match the pattern.
*
* @return TRUE if found, FALSE otherwise.
*/
int wrapperWildcardMatch(const TCHAR *text, const TCHAR *pattern, size_t minTextLen) {
size_t textLen;
size_t patternLen;
size_t textIndex;
/*log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_INFO, TEXT("wrapperWildcardMatch(\"%s\", \"%s\", %d)"), text, pattern, minTextLen);*/
textLen = _tcslen(text);
if (textLen < minTextLen) {
return FALSE;
}
patternLen = _tcslen(pattern);
/*log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_INFO, TEXT(" textLen=%d, patternLen=%d"), textLen, patternLen);*/
textIndex = 0;
while (textIndex <= textLen - minTextLen) {
if (wildcardMatchInner(&(text[textIndex]), textLen - textIndex, pattern, patternLen, minTextLen)) {
return TRUE;
}
textIndex++;
}
return FALSE;
}
/**
* Calculates the minimum text length which could be matched by the specified pattern.
* Patterns can contain '*' or '?' wildcards.
* '*' matches 0 or more characters.
* '?' matches exactly one character.
*
* @param pattern Pattern to calculate.
*
* @return The minimum text length of the pattern.
*/
size_t wrapperGetMinimumTextLengthForPattern(const TCHAR *pattern) {
size_t patternLen;
size_t patternIndex;
size_t minLen;
/*log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_INFO, TEXT("wrapperGetMinimumTextLengthForPattern(%s)"), pattern);*/
patternLen = _tcslen(pattern);
minLen = 0;
for (patternIndex = 0; patternIndex < patternLen; patternIndex++) {
if (pattern[patternIndex] == TEXT('*')) {
/* Matches 0 or more characters, so don't increment the minLen */
} else {
minLen++;
}
}
/*log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_INFO, TEXT("wrapperGetMinimumTextLengthForPattern(%s) -> %d"), pattern, minLen);*/
return minLen;
}
void logApplyFilters(const TCHAR *log) {
int i;
const TCHAR *filter;
const TCHAR *filterMessage;
int matched;
/* Look for output filters in the output. Only match the first. */
for (i = 0; i < wrapperData->outputFilterCount; i++) {
if (_tcslen(wrapperData->outputFilters[i]) > 0) {
/* The filter is defined. */
matched = FALSE;
filter = wrapperData->outputFilters[i];
if (wrapperData->outputFilterAllowWildFlags[i]) {
if (wrapperWildcardMatch(log, filter, wrapperData->outputFilterMinLens[i])) {
matched = TRUE;
}
} else {
/* Do a simple check to see if the pattern is found exactly as is. */
if (_tcsstr(log, filter)) {
/* Found an exact match for the pattern. */
/* Any wildcards in the pattern can be matched exactly if they exist in the output. This is by design. */
matched = TRUE;
}
}
if (matched) {
filterMessage = wrapperData->outputFilterMessages[i];
if ((!filterMessage) || (_tcslen(filterMessage) <= 0)) {
filterMessage = TEXT("Filter trigger matched.");
}
wrapperProcessActionList(wrapperData->outputFilterActionLists[i], filterMessage, WRAPPER_ACTION_SOURCE_CODE_FILTER, FALSE, 1);
/* break out of the loop */
break;
}
}
}
}
/**
* Logs a single line of child output allowing any filtering
* to be done in a common location.
*/
void logChildOutput(const char* log) {
TCHAR* tlog;
#ifdef UNICODE
int size;
#ifdef WIN32
TCHAR buffer[16];
UINT cp;
#endif
#endif
#ifdef UNICODE
#ifdef WIN32
GetLocaleInfo(GetThreadLocale(), LOCALE_IDEFAULTANSICODEPAGE, buffer, sizeof(buffer));
cp = _ttoi(buffer);
size = MultiByteToWideChar(cp, 0, log, -1 , NULL, 0) + 1;
tlog = (TCHAR*)malloc(size * sizeof(TCHAR));
if (!tlog) {
outOfMemory(TEXT("WLCO"), 1);
return;
}
MultiByteToWideChar(cp, 0, log, -1, (TCHAR*)tlog, size);
#else
size = mbstowcs(NULL, log, 0) + 1;
tlog = malloc(size * sizeof(TCHAR));
if (!tlog) {
outOfMemory(TEXT("WLCO"), 1);
return;
}
mbstowcs(tlog, log, size);
#endif
#else
tlog = (TCHAR*)log;
#endif
log_printf(wrapperData->jvmRestarts, LEVEL_INFO, tlog);
/* Look for output filters in the output. Only match the first. */
logApplyFilters(tlog);
#ifdef UNICODE
free(tlog);
#endif
}
/**
* This function is for moving a buffer inside itself.
*/
void safeMemCpy(char *buffer, size_t target, size_t src, size_t nbyte) {
size_t i;
for (i = 0; i < nbyte; i++) {
buffer[target + i] = buffer[src + i];
}
}
#define CHAR_LF 0x0a
/**
* Read and process any output from the child JVM Process.
*
* When maxTimeMS is non-zero this function will only be allowed to run for that maximum
* amount of time. This is done to make sure the calling function is allowed CPU for
* other activities. When timing out for this reason when there is more data in the
* pipe, this function will return TRUE to let the calling code know that it should
* not to any unnecessary sleeps. Otherwise FALSE will be returned.
*
* @param maxTimeMS The maximum number of milliseconds that this function will be allowed
* to run without returning. In reality no new reads will happen after
* this time, but actual processing may take longer.
*
* @return TRUE if the calling code should call this function again as soon as possible.
*/
int wrapperReadChildOutput(int maxTimeMS) {
struct timeb timeBuffer;
time_t startTime;
int startTimeMillis;
time_t now;
int nowMillis;
time_t durr;
char *tempBuffer;
char *cLF;
int currentBlockRead;
size_t loggedOffset;
int defer = FALSE;
int readThisPass = FALSE;
if (!wrapperChildWorkBuffer) {
/* Initialize the wrapperChildWorkBuffer. Set its initial size to the block size + 1.
* This is so that we can always add a \0 to the end of it. */
wrapperChildWorkBuffer = malloc(sizeof(char) * ((READ_BUFFER_BLOCK_SIZE * 2) + 1));
if (!wrapperChildWorkBuffer) {
outOfMemory(TEXT("WRCO"), 1);
return FALSE;
}
wrapperChildWorkBufferSize = READ_BUFFER_BLOCK_SIZE * 2;
}
wrapperGetCurrentTime(&timeBuffer);
startTime = now = timeBuffer.time;
startTimeMillis = nowMillis = timeBuffer.millitm;
#ifdef DEBUG_CHILD_OUTPUT
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_INFO, TEXT("wrapperReadChildOutput() BEGIN"));
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_INFO, TEXT("now=%ld, nowMillis=%d"), now, nowMillis);
#endif
/* Loop and read in CHILD_BLOCK_SIZE characters at a time.
*
* To keep a JVM outputting lots of content from freezing the Wrapper, we force a return every 250ms. */
while ((maxTimeMS <= 0) || ((durr = (now - startTime) * 1000 + (nowMillis - startTimeMillis)) < maxTimeMS)) {
#ifdef DEBUG_CHILD_OUTPUT
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_INFO, TEXT("durr=%ld"), durr);
#endif
/* If there is not enough space in the work buffer to read in a full block then it needs to be extended. */
if (wrapperChildWorkBufferLen + READ_BUFFER_BLOCK_SIZE > wrapperChildWorkBufferSize) {
#ifdef DEBUG_CHILD_OUTPUT
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_INFO, TEXT("Expand buffer."));
#endif
/* Increase the buffer quickly, but try not to get too big. Increase to a size that is the
* greater of size + 1024 or size * 1.1.
* Also make sure the new buffer is larger than the buffer len. This should not be necessary
* but is safer. */
wrapperChildWorkBufferSize = __max(wrapperChildWorkBufferLen + 1, __max(wrapperChildWorkBufferSize + READ_BUFFER_BLOCK_SIZE, wrapperChildWorkBufferSize + wrapperChildWorkBufferSize / 10));
tempBuffer = malloc(wrapperChildWorkBufferSize + 1);
if (!tempBuffer) {
outOfMemory(TEXT("WRCO"), 2);
return FALSE;
}
memcpy(tempBuffer, wrapperChildWorkBuffer, wrapperChildWorkBufferLen);
tempBuffer[wrapperChildWorkBufferLen] = '\0';
free(wrapperChildWorkBuffer);
wrapperChildWorkBuffer = tempBuffer;
#ifdef DEBUG_CHILD_OUTPUT
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_INFO, TEXT("buffer now %d bytes"), wrapperChildWorkBufferSize);
#endif
}
#ifdef DEBUG_CHILD_OUTPUT
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_INFO, TEXT("Try reading from pipe. totalBuffLen=%d, buffSize=%d"), wrapperChildWorkBufferLen, wrapperChildWorkBufferSize);
#endif
if (wrapperReadChildOutputBlock(wrapperChildWorkBuffer + (wrapperChildWorkBufferLen), (int)(wrapperChildWorkBufferSize - wrapperChildWorkBufferLen), ¤tBlockRead)) {
/* Error already reported. */
return FALSE;
}
if (currentBlockRead > 0) {
/* We read in a block, so increase the length. */
wrapperChildWorkBufferLen += currentBlockRead;
wrapperChildWorkLastDataTime = now;
wrapperChildWorkLastDataTimeMillis = nowMillis;
readThisPass = TRUE;
#ifdef DEBUG_CHILD_OUTPUT
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_INFO, TEXT(" Read %d bytes of new output. totalBuffLen=%d, buffSize=%d"), currentBlockRead, wrapperChildWorkBufferLen, wrapperChildWorkBufferSize);
#endif
}
/* Terminate the string just to avoid errors. The buffer has an extra character to handle this. */
wrapperChildWorkBuffer[wrapperChildWorkBufferLen] = '\0';
/* Loop over the contents of the buffer and try and extract as many lines as possible.
* Keep track of where we are to avoid unnecessary memory copies.
* At this point, the entire buffer will always be unlogged. */
loggedOffset = 0;
defer = FALSE;
while ((wrapperChildWorkBufferLen > loggedOffset) && (!defer)) {
#ifdef DEBUG_CHILD_OUTPUT
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_INFO, TEXT("Inner loop. totalBuffLen=%d, loggedOffset=%d, unloggedBuffLen=%d, buffSize=%d"), wrapperChildWorkBufferLen, loggedOffset, wrapperChildWorkBufferLen - loggedOffset, wrapperChildWorkBufferSize);
#endif
/* We have something in the buffer. Loop and see if we have a complete line to log.
* We will always find a LF at the end of the line. On Windows there may be a CR immediately before it. */
cLF = strchr(wrapperChildWorkBuffer + loggedOffset, (char)CHAR_LF);
if (cLF != NULL) {
/* We found a valid LF so we know that a full line is ready to be logged. */
#ifdef WIN32
if ((cLF > wrapperChildWorkBuffer) && ((cLF - sizeof(char))[0] == 0x0d)) {
#ifdef DEBUG_CHILD_OUTPUT
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_INFO, TEXT("Found CR+LF"));
#endif
/* Replace the CR with a NULL */
(cLF - sizeof(char))[0] = 0;
} else {
#endif
#ifdef DEBUG_CHILD_OUTPUT
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_INFO, TEXT("Found LF"));
#endif
#ifdef WIN32
}
#endif
/* Replace the LF with a NULL */
cLF[0] = '\0';
/* We have a string to log. */
#ifdef DEBUG_CHILD_OUTPUT
#ifdef UNICODE
/* It is not easy to log the string as is because they are not wide chars. Send it only to stdout. */
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_INFO, TEXT("Log: (see stdout)"));
#ifdef WIN32
wprintf(TEXT("Log: [%S]\n"), wrapperChildWorkBuffer + loggedOffset);
#else
wprintf(TEXT("Log: [%s]\n"), wrapperChildWorkBuffer + loggedOffset);
#endif
#else
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_INFO, TEXT("Log: [%s]"), wrapperChildWorkBuffer + loggedOffset);
#endif
#endif
/* Actually log the individual line of output. */
logChildOutput(wrapperChildWorkBuffer + loggedOffset);
/* Update the offset so we know how far we've logged. */
loggedOffset = cLF - wrapperChildWorkBuffer + 1;
#ifdef DEBUG_CHILD_OUTPUT
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_INFO, TEXT("loggedOffset: %d"), loggedOffset);
#endif
} else {
/* If we read this pass or if the last character is a CR on Windows then we always want to defer. */
if (readThisPass
#ifdef WIN32
|| (wrapperChildWorkBuffer[wrapperChildWorkBufferLen - 1] == 0x0d)
#endif
/* Avoid dumping partial lines because we call this funtion too quickly more than once.
* Never let the line be partial unless more than the LF-Delay threshold has expired. */
|| (wrapperData->logLFDelayThreshold == 0)
|| (((now - wrapperChildWorkLastDataTime) * 1000 + (nowMillis - wrapperChildWorkLastDataTimeMillis)) < wrapperData->logLFDelayThreshold)
) {
#ifdef DEBUG_CHILD_OUTPUT
#ifdef UNICODE
/* It is not easy to log the string as is because they are not wide chars. Send it only to stdout. */
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_INFO, TEXT("Incomplete line. Defer: (see stdout) Age: %d"),
(now - wrapperChildWorkLastDataTime) * 1000 + (nowMillis - wrapperChildWorkLastDataTimeMillis));
#ifdef WIN32
wprintf(TEXT("Defer Log: [%S]\n"), wrapperChildWorkBuffer + loggedOffset);
#else
wprintf(TEXT("Defer Log: [%s]\n"), wrapperChildWorkBuffer + loggedOffset);
#endif
#else
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_INFO, TEXT("Incomplete line. Defer: [%s] Age: %d"), wrapperChildWorkBuffer,
(now - wrapperChildWorkLastDataTime) * 1000 + (nowMillis - wrapperChildWorkLastDataTimeMillis));
#endif
#endif
defer = TRUE;
} else {
/* We have an incomplete line, but it was from a previous pass and is old enough, so we want to log it as it may be a prompt.
* This will always be the complete buffer. */
#ifdef DEBUG_CHILD_OUTPUT
#ifdef UNICODE
/* It is not easy to log the string as is because they are not wide chars. Send it only to stdout. */
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_INFO, TEXT("Incomplete line, but log now: (see stdout) Age: %d"),
(now - wrapperChildWorkLastDataTime) * 1000 + (nowMillis - wrapperChildWorkLastDataTimeMillis));
#ifdef WIN32
wprintf(TEXT("Log: [%S]\n"), wrapperChildWorkBuffer + loggedOffset);
#else
wprintf(TEXT("Log: [%s]\n"), wrapperChildWorkBuffer + loggedOffset);
#endif
#else
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_INFO, TEXT("Incomplete line, but log now: [%s] Age: %d"), wrapperChildWorkBuffer,
(now - wrapperChildWorkLastDataTime) * 1000 + (nowMillis - wrapperChildWorkLastDataTimeMillis));
#endif
#endif
logChildOutput(wrapperChildWorkBuffer + loggedOffset);
/* We know we read everything. */
loggedOffset = wrapperChildWorkBufferLen;
/* So we can safely reset the loggedOffset and clear the buffer. */
wrapperChildWorkBuffer[0] = '\0';
wrapperChildWorkBufferLen = 0;
loggedOffset = 0;
}
}
}
/* We have read as many lines from the buffered output as possible.
* If we still have any partial lines, then we need to make sure they are moved to the beginning of the buffer so we can read in another block. */
if (loggedOffset > 0) {
if (loggedOffset >= wrapperChildWorkBufferLen) {
/* We know we have read everything in. So we can efficiently clear the buffer. */
#ifdef DEBUG_CHILD_OUTPUT
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_INFO, TEXT("Cleared Buffer as everything was logged."));
#endif
wrapperChildWorkBuffer[0] = '\0';
wrapperChildWorkBufferLen = 0;
/* loggedOffset = 0; Not needed. */
} else {
/* We have logged one or more lines from the buffer, but unlogged content still exists. It needs to be moved to the head of the buffer. */
#ifdef DEBUG_CHILD_OUTPUT
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_INFO, TEXT("Moving %d bytes in buffer for next cycle."), wrapperChildWorkBufferLen - loggedOffset);
#endif
/* NOTE - This line intentionally does the copy within the same memory space. It is safe the way it is working however. */
wrapperChildWorkBufferLen = wrapperChildWorkBufferLen - loggedOffset;
safeMemCpy(wrapperChildWorkBuffer, 0, loggedOffset, wrapperChildWorkBufferLen);
/* Shouldn't be needed, but just to make sure the buffer has been ended properly */
wrapperChildWorkBuffer[wrapperChildWorkBufferLen] = 0;
/* loggedOffset = 0; Not needed. */
}
} else {
}
if (currentBlockRead <= 0) {
/* All done for now. */
if (wrapperChildWorkBufferLen > 0) {
#ifdef DEBUG_CHILD_OUTPUT
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_INFO, TEXT("wrapperReadChildOutput() END (Incomplete)"));
#endif
} else {
#ifdef DEBUG_CHILD_OUTPUT
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_INFO, TEXT("wrapperReadChildOutput() END"));
#endif
}
return FALSE;
}
/* Get the time again */
wrapperGetCurrentTime(&timeBuffer);
now = timeBuffer.time;
nowMillis = timeBuffer.millitm;
}
/* If we got here then we timed out. */
#ifdef DEBUG_CHILD_OUTPUT
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_INFO, TEXT("wrapperReadChildOutput() END TIMEOUT"));
#endif
return TRUE;
}
/**
* Immediately after a JVM is launched and whenever the log file name changes,
* the log file name is sent to the JVM where it can be referenced by applications.
*/
void sendLogFileName() {
TCHAR *currentLogFilePath;
currentLogFilePath = getCurrentLogfilePath();
wrapperProtocolFunction(WRAPPER_MSG_LOGFILE, currentLogFilePath);
free(currentLogFilePath);
}
/**
* Immediately after a JVM is launched, the wrapper configuration is sent to the
* JVM where it can be used as a properties object.
*/
void sendProperties() {
TCHAR *buffer;
buffer = linearizeProperties(properties, TEXT('\t'));
if (buffer) {
wrapperProtocolFunction(WRAPPER_MSG_PROPERTIES, buffer);
free(buffer);
}
}
/**
* Common cleanup code which should get called when we first decide that the JVM was down.
*/
void wrapperJVMDownCleanup(int setState) {
/* Only set the state to DOWN_CHECK if we are not already in a state which reflects this. */
if (setState) {
if (wrapperData->jvmCleanupTimeout > 0) {
wrapperSetJavaState(WRAPPER_JSTATE_DOWN_CHECK, wrapperGetTicks(), wrapperData->jvmCleanupTimeout);
} else {
wrapperSetJavaState(WRAPPER_JSTATE_DOWN_CHECK, wrapperGetTicks(), -1);
}
}
/* Remove java pid file if it was registered and created by this process. */
if (wrapperData->javaPidFilename) {
_tunlink(wrapperData->javaPidFilename);
}
#ifdef WIN32
if (!CloseHandle(wrapperData->javaProcess)) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_ERROR,
TEXT("Failed to close the Java process handle: %s"), getLastErrorText());
}
wrapperData->javaProcess = NULL;
#endif
/* Close any open socket to the JVM */
if (wrapperData->stoppedPacketReceived) {
wrapperProtocolClose();
} else {
/* Leave the socket open so the Wrapper has the chance to read any outstanding packets. */
}
}
/**
* Immediately kill the JVM process and set the JVM state to
* WRAPPER_JSTATE_DOWN_CHECK.
*/
int wrapperKillProcessNow() {
#ifdef WIN32
int ret;
#endif
/* Check to make sure that the JVM process is still running */
#ifdef WIN32
ret = WaitForSingleObject(wrapperData->javaProcess, 0);
if (ret == WAIT_TIMEOUT) {
#else
if (waitpid(wrapperData->javaPID, NULL, WNOHANG) == 0) {
#endif
/* JVM is still up when it should have already stopped itself. */
/* The JVM process is not responding so the only choice we have is to
* kill it. */
#ifdef WIN32
/* The TerminateProcess funtion will kill the process, but it
* does not correctly notify the process's DLLs that it is shutting
* down. Ideally, we would call ExitProcess, but that can only be
* called from within the process being killed. */
if (TerminateProcess(wrapperData->javaProcess, 0)) {
#else
if (kill(wrapperData->javaPID, SIGKILL) == 0) {
#endif
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_ERROR, TEXT("JVM did not exit on request, termination requested."));
return FALSE;
} else {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_ERROR, TEXT("JVM did not exit on request."));
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_ERROR,
TEXT(" Attempt to terminate process failed: %s"), getLastErrorText());
/* Terminating the current JVM failed. Cancel pending restart requests */
wrapperJVMDownCleanup(TRUE);
wrapperData->exitCode = 1;
return TRUE;
}
}
wrapperJVMDownCleanup(TRUE);
return FALSE;
}
/**
* Puts the Wrapper into a state where the JVM will be killed at the soonest
* possible opportunity. It is necessary to wait a moment if a final thread
* dump is to be requested. This call wll always set the JVM state to
* WRAPPER_JSTATE_KILLING.
*/
void wrapperKillProcess() {
#ifdef WIN32
int ret;
#endif
int delay = 0;
if ((wrapperData->jState == WRAPPER_JSTATE_DOWN_CLEAN) ||
(wrapperData->jState == WRAPPER_JSTATE_LAUNCH_DELAY) ||
(wrapperData->jState == WRAPPER_JSTATE_DOWN_CHECK) ||
(wrapperData->jState == WRAPPER_JSTATE_DOWN_FLUSH)) {
/* Already down. */
if (wrapperData->jState == WRAPPER_JSTATE_LAUNCH_DELAY) {
wrapperSetJavaState(WRAPPER_JSTATE_DOWN_CLEAN, wrapperGetTicks(), 0);
}
return;
}
/* Check to make sure that the JVM process is still running */
#ifdef WIN32
ret = WaitForSingleObject(wrapperData->javaProcess, 0);
if (ret == WAIT_TIMEOUT) {
#else
if (waitpid(wrapperData->javaPID, NULL, WNOHANG) == 0) {
#endif
/* JVM is still up when it should have already stopped itself. */
if (wrapperData->requestThreadDumpOnFailedJVMExit) {
wrapperRequestDumpJVMState();
delay = wrapperData->requestThreadDumpOnFailedJVMExitDelay;
}
}
wrapperSetJavaState(WRAPPER_JSTATE_KILLING, wrapperGetTicks(), delay);
}
/**
* Add some checks of the properties to try to catch the case where the user is making use of TestWrapper scripts.
*
* @return TRUE if there is such a missconfiguration. FALSE if all is Ok.
*/
int checkForTestWrapperScripts() {
const TCHAR* prop;
prop = getStringProperty(properties, TEXT("wrapper.java.mainclass"), NULL);
if (prop) {
if (_tcscmp(prop, TEXT("org.tanukisoftware.wrapper.test.Main")) == 0) {
/* This is the TestWrapper app. So don't check. */
} else {
/* This is a user application, so make sure that they are not using the TestWrapper scripts. */
prop = getStringProperty(properties, TEXT("wrapper.app.parameter.2"), NULL);
if (prop) {
if (_tcscmp(prop, TEXT("{{TestWrapperBat}}")) == 0) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_ERROR, TEXT(
""));
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_ERROR, TEXT(
"--------------------------------------------------------------------"));
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_ERROR, TEXT(
"We have detected that you are making use of the sample batch files\nthat are designed for the TestWrapper Example Application. When\nsetting up your own application, please copy fresh files over from\nthe Wrapper's src\\bin directory."));
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_ERROR, TEXT(
""));
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_ERROR, TEXT(
"Shutting down as this will likely cause problems with your\napplication startup."));
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_ERROR, TEXT(
""));
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_ERROR, TEXT(
"Please see the integration section of the documentation for more\ninformation."));
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_ERROR, TEXT(
" http://wrapper.tanukisoftware.com/integrate"));
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_ERROR, TEXT(
"--------------------------------------------------------------------"));
return TRUE;
} else if (_tcscmp(prop, TEXT("{{TestWrapperSh}}")) == 0) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_ERROR, TEXT(
""));
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_ERROR, TEXT(
"--------------------------------------------------------------------"));
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_ERROR, TEXT(
"We have detected that you are making use of the sample shell scripts\nthat are designed for the TestWrapper Example Application. When\nsetting up your own application, please copy fresh files over from\nthe Wrapper's src/bin directory."));
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_ERROR, TEXT(
""));
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_ERROR, TEXT(
"Shutting down as this will likely cause problems with your\napplication startup."));
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_ERROR, TEXT(
""));
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_ERROR, TEXT(
"Please see the integration section of the documentation for more\ninformation."));
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_ERROR, TEXT(
" http://wrapper.tanukisoftware.com/integrate"));
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_ERROR, TEXT(
"--------------------------------------------------------------------"));
return TRUE;
}
}
}
}
return FALSE;
}
#ifdef WIN32
#define OSBUFSIZE 256
/**
* Creates a human readable representation of the Windows OS the Wrapper is run on.
*
* @param pszOS the buffer the information gets stored to
* @return FALSE if error or no information could be retrieved. TRUE otherwise.
*/
BOOL GetOSDisplayString(TCHAR** pszOS) {
OSVERSIONINFOEX osvi;
SYSTEM_INFO si;
FARPROC pGNSI;
FARPROC pGPI;
DWORD dwType;
TCHAR buf[80];
ZeroMemory(&si, sizeof(SYSTEM_INFO));
ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
if (!GetVersionEx((OSVERSIONINFO*) &osvi)) {
return FALSE;
}
/* Call GetNativeSystemInfo if supported or GetSystemInfo otherwise.*/
pGNSI = GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetNativeSystemInfo");
if (NULL != pGNSI) {
pGNSI(&si);
} else {
GetSystemInfo(&si);
}
if ((VER_PLATFORM_WIN32_NT == osvi.dwPlatformId) && (osvi.dwMajorVersion > 4)) {
_tcsncpy(*pszOS, TEXT("Microsoft "), OSBUFSIZE);
/* Test for the specific product. */
if (osvi.dwMajorVersion == 6) {
if (osvi.dwMinorVersion == 0 ) {
if (osvi.wProductType == VER_NT_WORKSTATION) {
_tcsncat(*pszOS, TEXT("Windows Vista "), OSBUFSIZE);
} else {
_tcsncat(*pszOS, TEXT("Windows Server 2008 "), OSBUFSIZE);
}
}
if (osvi.dwMinorVersion == 1) {
if (osvi.wProductType == VER_NT_WORKSTATION) {
_tcsncat(*pszOS, TEXT("Windows 7 "), OSBUFSIZE);
} else {
_tcsncat(*pszOS, TEXT("Windows Server 2008 R2 "), OSBUFSIZE);
}
}
pGPI = GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetProductInfo");
pGPI(osvi.dwMajorVersion, osvi.dwMinorVersion, 0, 0, &dwType);
switch (dwType) {
case 1:
_tcsncat(*pszOS, TEXT("Ultimate Edition" ), OSBUFSIZE);
break;
case 48:
_tcsncat(*pszOS, TEXT("Professional"), OSBUFSIZE);
break;
case 3:
_tcsncat(*pszOS, TEXT("Home Premium Edition"), OSBUFSIZE);
break;
case 67:
_tcsncat(*pszOS, TEXT("Home Basic Edition"), OSBUFSIZE);
break;
case 4:
_tcsncat(*pszOS, TEXT("Enterprise Edition"), OSBUFSIZE);
break;
case 6:
_tcsncat(*pszOS, TEXT("Business Edition"), OSBUFSIZE);
break;
case 11:
_tcsncat(*pszOS, TEXT("Starter Edition"), OSBUFSIZE);
break;
case 18:
_tcsncat(*pszOS, TEXT("Cluster Server Edition"), OSBUFSIZE);
break;
case 8:
_tcsncat(*pszOS, TEXT("Datacenter Edition"), OSBUFSIZE);
break;
case 12:
_tcsncat(*pszOS, TEXT("Datacenter Edition (core installation)"), OSBUFSIZE);
break;
case 10:
_tcsncat(*pszOS, TEXT("Enterprise Edition"), OSBUFSIZE);
break;
case 14:
_tcsncat(*pszOS, TEXT("Enterprise Edition (core installation)"), OSBUFSIZE);
break;
case 15:
_tcsncat(*pszOS, TEXT("Enterprise Edition for Itanium-based Systems"), OSBUFSIZE);
break;
case 9:
_tcsncat(*pszOS, TEXT("Small Business Server"), OSBUFSIZE);
break;
case 25:
_tcsncat(*pszOS, TEXT("Small Business Server Premium Edition"), OSBUFSIZE);
break;
case 7:
_tcsncat(*pszOS, TEXT("Standard Edition"), OSBUFSIZE);
break;
case 13:
_tcsncat(*pszOS, TEXT("Standard Edition (core installation)"), OSBUFSIZE);
break;
case 17:
_tcsncat(*pszOS, TEXT("Web Server Edition"), OSBUFSIZE);
break;
}
}
if ((osvi.dwMajorVersion == 5) && (osvi.dwMinorVersion == 2)) {
if (GetSystemMetrics(89)) {
_tcsncat(*pszOS, TEXT("Windows Server 2003 R2, "), OSBUFSIZE);
} else if (osvi.wSuiteMask & 8192) {
_tcsncat(*pszOS, TEXT("Windows Storage Server 2003"), OSBUFSIZE);
} else if (osvi.wSuiteMask & 32768) {
_tcsncat(*pszOS, TEXT("Windows Home Server"), OSBUFSIZE);
} else if (osvi.wProductType == VER_NT_WORKSTATION && si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64) {
_tcsncat(*pszOS, TEXT("Windows XP Professional x64 Edition"), OSBUFSIZE);
} else {
_tcsncat(*pszOS, TEXT("Windows Server 2003, "), OSBUFSIZE);
}
/* Test for the server type. */
if (osvi.wProductType != VER_NT_WORKSTATION) {
if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64) {
if (osvi.wSuiteMask & VER_SUITE_DATACENTER) {
_tcsncat(*pszOS, TEXT("Datacenter Edition for Itanium-based Systems"), OSBUFSIZE);
} else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE) {
_tcsncat(*pszOS, TEXT("Enterprise Edition for Itanium-based Systems"), OSBUFSIZE);
}
} else if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) {
if (osvi.wSuiteMask & VER_SUITE_DATACENTER) {
_tcsncat(*pszOS, TEXT("Datacenter x64 Edition"), OSBUFSIZE);
} else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE) {
_tcsncat(*pszOS, TEXT("Enterprise x64 Edition"), OSBUFSIZE);
} else {
_tcsncat(*pszOS, TEXT("Standard x64 Edition"), OSBUFSIZE);
}
} else {
if (osvi.wSuiteMask & VER_SUITE_COMPUTE_SERVER) {
_tcsncat(*pszOS, TEXT("Compute Cluster Edition"), OSBUFSIZE);
} else if (osvi.wSuiteMask & VER_SUITE_DATACENTER) {
_tcsncat(*pszOS, TEXT("Datacenter Edition"), OSBUFSIZE);
} else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE) {
_tcsncat(*pszOS, TEXT("Enterprise Edition"), OSBUFSIZE);
} else if (osvi.wSuiteMask & VER_SUITE_BLADE) {
_tcsncat(*pszOS, TEXT("Web Edition" ), OSBUFSIZE);
} else {
_tcsncat(*pszOS, TEXT("Standard Edition"), OSBUFSIZE);
}
}
}
}
if ((osvi.dwMajorVersion == 5) && (osvi.dwMinorVersion == 1)) {
_tcsncat(*pszOS, TEXT("Windows XP "), OSBUFSIZE);
if (osvi.wSuiteMask & VER_SUITE_PERSONAL) {
_tcsncat(*pszOS, TEXT("Home Edition"), OSBUFSIZE);
} else {
_tcsncat(*pszOS, TEXT("Professional"), OSBUFSIZE);
}
}
if ((osvi.dwMajorVersion == 5) && (osvi.dwMinorVersion == 0)) {
_tcsncat(*pszOS, TEXT("Windows 2000 "), OSBUFSIZE);
if (osvi.wProductType == VER_NT_WORKSTATION) {
_tcsncat(*pszOS, TEXT("Professional"), OSBUFSIZE);
} else {
if (osvi.wSuiteMask & VER_SUITE_DATACENTER) {
_tcsncat(*pszOS, TEXT("Datacenter Server"), OSBUFSIZE);
} else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE) {
_tcsncat(*pszOS, TEXT("Advanced Server"), OSBUFSIZE);
} else {
_tcsncat(*pszOS, TEXT("Server"), OSBUFSIZE);
}
}
}
/* Include service pack (if any) and build number. */
if (_tcslen(osvi.szCSDVersion) > 0) {
_tcsncat(*pszOS, TEXT(" "), OSBUFSIZE);
_tcsncat(*pszOS, osvi.szCSDVersion, OSBUFSIZE);
}
_sntprintf(buf, 80, TEXT(" (build %d)"), osvi.dwBuildNumber);
_tcsncat(*pszOS, buf, OSBUFSIZE);
if (osvi.dwMajorVersion >= 6) {
if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) {
_tcsncat(*pszOS, TEXT(", 64-bit"), OSBUFSIZE);
} else if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL) {
_tcsncat(*pszOS, TEXT(", 32-bit"), OSBUFSIZE);
}
}
return TRUE;
} else {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_DEBUG, TEXT("Unknown Windows Version"));
return FALSE;
}
}
#endif
/**
* Launch common setup code.
*/
int wrapperRunCommonInner() {
const TCHAR *prop;
#ifdef WIN32
TCHAR* szOS;
#endif
struct tm timeTM;
TCHAR* tz1;
TCHAR* tz2;
#if defined(UNICODE)
size_t req;
#endif
/* Make sure the tick timer is working correctly. */
if (wrapperTickAssertions()) {
return 1;
}
/* Log a startup banner. */
wrapperVersionBanner();
/* The following code will display a licensed to block if a license key is found
* in the Wrapper configuration. This piece of code is required as is for
* Development License owners to be in complience with their development license.
* This code does not do any validation of the license keys and works differently
* from the license code found in the Standard and Professional Editions of the
* Wrapper. */
prop = getStringProperty(properties, TEXT("wrapper.license.type"), TEXT(""));
if (strcmpIgnoreCase(prop, TEXT("DEV")) == 0) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS,
TEXT(" Licensed to %s for %s"),
getStringProperty(properties, TEXT("wrapper.license.licensee"), TEXT("(LICENSE INVALID)")),
getStringProperty(properties, TEXT("wrapper.license.dev_application"), TEXT("(LICENSE INVALID)")));
}
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT(""));
if (checkForTestWrapperScripts()) {
return 1;
}
#ifdef WIN32
if (initializeStartup()) {
return 1;
}
#endif
if (wrapperData->isDebugging) {
timeTM = wrapperGetReleaseTime();
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_DEBUG, TEXT("Release time: %04d/%02d/%02d %02d:%02d:%02d"),
timeTM.tm_year + 1900, timeTM.tm_mon + 1, timeTM.tm_mday,
timeTM.tm_hour, timeTM.tm_min, timeTM.tm_sec );
timeTM = wrapperGetBuildTime();
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_DEBUG, TEXT("Build time: %04d/%02d/%02d %02d:%02d:%02d"),
timeTM.tm_year + 1900, timeTM.tm_mon + 1, timeTM.tm_mday,
timeTM.tm_hour, timeTM.tm_min, timeTM.tm_sec );
/* Display timezone information. */
tzset();
#if defined(UNICODE)
#if !defined(WIN32)
req = mbstowcs(NULL, tzname[0], 0) + 1;
tz1 = malloc(req * sizeof(TCHAR));
if (!tz1) {
outOfMemory(TEXT("LHN"), 1);
} else {
mbstowcs(tz1, tzname[0], req);
req = mbstowcs(NULL, tzname[1], 0) + 1;
tz2 = malloc(req * sizeof(TCHAR));
if (!tz2) {
outOfMemory(TEXT("LHN"), 2);
free(tz1);
} else {
mbstowcs(tz2, tzname[1], req);
#else
req = MultiByteToWideChar(CP_OEMCP, 0, tzname[0], -1, NULL, 0);
tz1 = malloc(req * sizeof(TCHAR));
if (!tz1) {
outOfMemory(TEXT("LHN"), 1);
} else {
MultiByteToWideChar(CP_OEMCP,0, tzname[0], -1, tz1, (int)req);
req = MultiByteToWideChar(CP_OEMCP, 0, tzname[1], -1, NULL, 0);
tz2 = malloc(req * sizeof(TCHAR));
if (!tz2) {
free(tz1);
outOfMemory(TEXT("LHN"), 2);
} else {
MultiByteToWideChar(CP_OEMCP,0, tzname[1], -1, tz2, (int)req);
#endif
#else
tz1 = tzname[0];
tz2 = tzname[1];
#endif
#ifndef FREEBSD
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_DEBUG, TEXT("Timezone: %s (%s) Offset: %ld, hasDaylight: %d"),
tz1, tz2, timezone, daylight);
#else
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_DEBUG, TEXT("Timezone: %s (%s) Offset: %ld"),
tz1, tz2, timezone);
#endif
if (wrapperData->useSystemTime) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_DEBUG, TEXT("Using system timer."));
} else {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_DEBUG, TEXT("Using tick timer."));
}
#ifdef UNICODE
free(tz1);
free(tz2);
}
}
#endif
}
#ifdef WIN32
if (wrapperData->isDebugging) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_DEBUG, TEXT("Current User: %s Domain: %s"), (wrapperData->userName ? wrapperData->userName : TEXT("N/A")), (wrapperData->domainName ? wrapperData->domainName : TEXT("N/A")));
szOS = calloc(OSBUFSIZE, sizeof(TCHAR));
if (szOS) {
if (GetOSDisplayString(&szOS)) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_DEBUG, TEXT("Operating System ID: %s"), szOS);
}
free(szOS);
}
}
#endif
/* Should we dump the environment variables?
* If the the user specifically wants the environment, show it as the status log level, otherwise include it in debug output if enabled. */
if (getBooleanProperty(properties, TEXT("wrapper.environment.dump"), FALSE)) {
dumpEnvironment(LEVEL_INFO);
} else if (getBooleanProperty(properties, TEXT("wrapper.debug"), FALSE)) {
dumpEnvironment(LEVEL_DEBUG);
}
#ifdef _DEBUG
/* Multi-line logging tests. */
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT("----- Should be 5 lines -----"));
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT("\nLINE2:\n\nLINE4:\n"));
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT("----- Next is one line ------"));
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT(""));
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT("----- Next is two lines -----"));
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT("\n"));
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT("----- Next is two lines -----"));
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT("ABC\nDEF"));
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT("-----------------------------"));
#endif
#ifdef WRAPPER_FILE_DEBUG
wrapperFileTests();
#endif
return 0;
}
int wrapperRunCommon(const TCHAR *runMode) {
int exitCode;
/* Setup the wrapperData structure. */
wrapperSetWrapperState(WRAPPER_WSTATE_STARTING);
wrapperSetJavaState(WRAPPER_JSTATE_DOWN_CLEAN, 0, -1);
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT("--> Wrapper Started as %s"), runMode);
/* Initialize the wrapper */
exitCode = wrapperInitializeRun();
if (exitCode == 0) {
if (!wrapperRunCommonInner()) {
/* Enter main event loop */
wrapperEventLoop();
/* Clean up any open sockets. */
wrapperProtocolClose();
protocolStopServer();
exitCode = wrapperData->exitCode;
} else {
exitCode = 1;
}
}
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT("<-- Wrapper Stopped"));
return exitCode;
}
/**
* Launch the wrapper as a console application.
*/
int wrapperRunConsole() {
return wrapperRunCommon(TEXT("Console"));
}
/**
* Launch the wrapper as a service application.
*/
int wrapperRunService() {
return wrapperRunCommon(
#ifdef WIN32
TEXT("Service")
#else
TEXT("Daemon")
#endif
);
}
/**
* Used to ask the state engine to shut down the JVM and Wrapper.
*
* @param exitCode Exit code to use when shutting down.
* @param force True to force the Wrapper to shutdown even if some configuration
* had previously asked that the JVM be restarted. This will reset
* any existing restart requests, but it will still be possible for
* later actions to request a restart.
*/
void wrapperStopProcess(int exitCode, int force) {
/* If we are are not aready shutting down, then do so. */
if ((wrapperData->wState == WRAPPER_WSTATE_STOPPING) ||
(wrapperData->wState == WRAPPER_WSTATE_STOPPED)) {
if (wrapperData->isDebugging) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_DEBUG,
TEXT("wrapperStopProcess(%d, %s) called while stopping. (IGNORED)"), exitCode, (force ? TEXT("TRUE") : TEXT("FALSE")));
}
} else {
if (wrapperData->isDebugging) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_DEBUG,
TEXT("wrapperStopProcess(%d, %s) called."), exitCode, (force ? TEXT("TRUE") : TEXT("FALSE")));
}
/* If it has not already been set, set the exit request flag. */
if (wrapperData->exitRequested ||
(wrapperData->jState == WRAPPER_JSTATE_DOWN_CLEAN) ||
(wrapperData->jState == WRAPPER_JSTATE_STOP) ||
(wrapperData->jState == WRAPPER_JSTATE_STOPPING) ||
(wrapperData->jState == WRAPPER_JSTATE_STOPPED) ||
(wrapperData->jState == WRAPPER_JSTATE_KILLING) ||
(wrapperData->jState == WRAPPER_JSTATE_KILLED) ||
(wrapperData->jState == WRAPPER_JSTATE_KILL) ||
(wrapperData->jState == WRAPPER_JSTATE_DOWN_CHECK) ||
(wrapperData->jState == WRAPPER_JSTATE_DOWN_FLUSH)) {
/* JVM is already down or going down. */
} else {
wrapperData->exitRequested = TRUE;
}
wrapperData->exitCode = exitCode;
if (force) {
/* Make sure that further restarts are disabled. */
wrapperData->restartRequested = WRAPPER_RESTART_REQUESTED_NO;
/* Do not call wrapperSetWrapperState(WRAPPER_WSTATE_STOPPING) here.
* It will be called by the wrappereventloop.c.jStateDown once the
* the JVM is completely down. Calling it here will make it
* impossible to trap and restart based on exit codes or other
* Wrapper configurations. */
if (wrapperData->isDebugging) {
if ((wrapperData->restartRequested == WRAPPER_RESTART_REQUESTED_AUTOMATIC) || (wrapperData->restartRequested == WRAPPER_RESTART_REQUESTED_CONFIGURED)) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_DEBUG, TEXT(" Overriding request to restart JVM."));
}
}
} else {
/* Do not call wrapperSetWrapperState(WRAPPER_WSTATE_STOPPING) here.
* It will be called by the wrappereventloop.c.jStateDown once the
* the JVM is completely down. Calling it here will make it
* impossible to trap and restart based on exit codes. */
if (wrapperData->isDebugging) {
if ((wrapperData->restartRequested == WRAPPER_RESTART_REQUESTED_AUTOMATIC) || (wrapperData->restartRequested == WRAPPER_RESTART_REQUESTED_CONFIGURED)) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_DEBUG, TEXT(" Stop ignored. Continuing to restart JVM."));
}
}
}
}
}
/**
* Used to ask the state engine to shut down the JVM. This are always intentional restart requests.
*/
void wrapperRestartProcess() {
/* If it has not already been set, set the restart request flag in the wrapper data. */
if (wrapperData->exitRequested || wrapperData->restartRequested ||
(wrapperData->jState == WRAPPER_JSTATE_DOWN_CLEAN) ||
(wrapperData->jState == WRAPPER_JSTATE_STOP) ||
(wrapperData->jState == WRAPPER_JSTATE_STOPPING) ||
(wrapperData->jState == WRAPPER_JSTATE_STOPPED) ||
(wrapperData->jState == WRAPPER_JSTATE_KILLING) ||
(wrapperData->jState == WRAPPER_JSTATE_KILL) ||
(wrapperData->jState == WRAPPER_JSTATE_DOWN_CHECK) ||
(wrapperData->jState == WRAPPER_JSTATE_DOWN_FLUSH) ||
(wrapperData->jState == WRAPPER_JSTATE_LAUNCH_DELAY)) { /* Down but not yet restarted. */
if (wrapperData->isDebugging) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_DEBUG,
TEXT("wrapperRestartProcess() called. (IGNORED)"));
}
} else {
if (wrapperData->isDebugging) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_DEBUG,
TEXT("wrapperRestartProcess() called."));
}
wrapperData->exitRequested = TRUE;
wrapperData->restartRequested = WRAPPER_RESTART_REQUESTED_CONFIGURED;
}
}
/**
* Used to ask the state engine to pause the JVM.
*
* @param actionSourceCode Tracks where the action originated.
*/
void wrapperPauseProcess(int actionSourceCode) {
TCHAR msgBuffer[10];
if (!wrapperData->pausable) {
if (wrapperData->isDebugging) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_DEBUG, TEXT(
"wrapperPauseProcess() called but wrapper.pausable is FALSE. (IGNORED)"));
}
return;
}
if ((wrapperData->wState == WRAPPER_WSTATE_STOPPING) ||
(wrapperData->wState == WRAPPER_WSTATE_STOPPED)) {
/* If we are already shutting down, then ignore and continue to do so. */
if (wrapperData->isDebugging) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_DEBUG, TEXT(
"wrapperPauseProcess() called while stopping. (IGNORED)"));
}
} else if (wrapperData->wState == WRAPPER_WSTATE_PAUSING) {
/* If we are currently being paused, then ignore and continue to do so. */
if (wrapperData->isDebugging) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_DEBUG, TEXT(
"wrapperPauseProcess() called while pausing. (IGNORED)"));
}
} else if (wrapperData->wState == WRAPPER_WSTATE_PAUSED) {
/* If we are currently paused, then ignore and continue to do so. */
if (wrapperData->isDebugging) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_DEBUG, TEXT(
"wrapperPauseProcess() called while paused. (IGNORED)"));
}
} else {
if (wrapperData->isDebugging) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_DEBUG, TEXT(
"wrapperPauseProcess() called."));
}
wrapperSetWrapperState(WRAPPER_WSTATE_PAUSING);
if (!wrapperData->pausableStopJVM) {
/* Notify the Java process. */
_sntprintf(msgBuffer, 10, TEXT("%d"), actionSourceCode);
wrapperProtocolFunction(WRAPPER_MSG_PAUSE, msgBuffer);
}
}
}
/**
* Used to ask the state engine to resume a paused the JVM.
*
* @param actionSourceCode Tracks where the action originated.
*/
void wrapperResumeProcess(int actionSourceCode) {
TCHAR msgBuffer[10];
if ((wrapperData->wState == WRAPPER_WSTATE_STOPPING) ||
(wrapperData->wState == WRAPPER_WSTATE_STOPPED)) {
/* If we are already shutting down, then ignore and continue to do so. */
if (wrapperData->isDebugging) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_DEBUG, TEXT(
"wrapperResumeProcess() called while stopping. (IGNORED)"));
}
} else if (wrapperData->wState == WRAPPER_WSTATE_STARTING) {
/* If we are currently being started, then ignore and continue to do so. */
if (wrapperData->isDebugging) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_DEBUG, TEXT(
"wrapperResumeProcess() called while starting. (IGNORED)"));
}
} else if (wrapperData->wState == WRAPPER_WSTATE_STARTED) {
/* If we are currently started, then ignore and continue to do so. */
if (wrapperData->isDebugging) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_DEBUG, TEXT(
"wrapperResumeProcess() called while started. (IGNORED)"));
}
} else if (wrapperData->wState == WRAPPER_WSTATE_RESUMING) {
/* If we are currently being continued, then ignore and continue to do so. */
if (wrapperData->isDebugging) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_DEBUG, TEXT(
"wrapperResumeProcess() called while resuming. (IGNORED)"));
}
} else {
if (wrapperData->isDebugging) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_DEBUG, TEXT(
"wrapperResumeProcess() called."));
}
/* If we were configured to stop the JVM then we want to reset its failed
* invocation count as the current stoppage was expected. */
if (wrapperData->pausableStopJVM) {
wrapperData->failedInvocationCount = 0;
}
wrapperSetWrapperState(WRAPPER_WSTATE_RESUMING);
if (!wrapperData->pausableStopJVM) {
/* Notify the Java process. */
_sntprintf(msgBuffer, 10, TEXT("%d"), actionSourceCode);
wrapperProtocolFunction(WRAPPER_MSG_RESUME, msgBuffer);
}
}
}
/**
* Sends a command off to the JVM asking it to perform a garbage collection sweep.
*
* @param actionSourceCode Tracks where the action originated.
*/
void wrapperRequestJVMGC(int actionSourceCode) {
TCHAR msgBuffer[10];
/* Notify the Java process. */
_sntprintf(msgBuffer, 10, TEXT("%d"), actionSourceCode);
wrapperProtocolFunction(WRAPPER_MSG_GC, msgBuffer);
}
/**
* Loops over and strips all double quotes from prop and places the
* stripped version into propStripped.
*
* The exception is double quotes that are preceeded by a backslash
* in this case the backslash is stripped.
*
* If two backslashes are found in a row, then the first escapes the
* second and the second is removed.
*/
static size_t wrapperStripQuotesInner(const TCHAR *prop, size_t propLen, TCHAR *propStripped) {
size_t len;
int i, j;
len = propLen;
j = 0;
for (i = 0; i < (int)len; i++) {
if ((prop[i] == TEXT('\\')) && (i < (int)len - 1)) {
if (prop[i + 1] == TEXT('\\')) {
/* Double backslash. Keep the first, and skip the second. */
propStripped[j] = prop[i];
j++;
i++;
} else if (prop[i + 1] == TEXT('\"')) {
/* Escaped quote. Keep the quote. */
propStripped[j] = prop[i + 1];
j++;
i++;
} else {
/* Include the backslash as normal. */
propStripped[j] = prop[i];
j++;
}
} else if (prop[i] == TEXT('\"')) {
/* Quote. Skip it. */
} else {
propStripped[j] = prop[i];
j++;
}
}
return j;
}
void wrapperStripQuotes(const TCHAR *prop, TCHAR *propStripped) {
size_t len;
len = wrapperStripQuotesInner(prop, _tcslen(prop), propStripped);
propStripped[len] = TEXT('\0');
}
/*
* Corrects a windows path in place by replacing all '/' characters with '\'
* on Windows versions.
*
* filename - Filename to be modified. Could be null.
*/
void correctWindowsPath(TCHAR *filename) {
#ifdef WIN32
TCHAR *c;
if (filename) {
c = (TCHAR *)filename;
while((c = _tcschr(c, TEXT('/'))) != NULL) {
c[0] = TEXT('\\');
}
}
#endif
}
/**
* Adds quotes around the specified string in such a way that everything is
* escaped correctly. If the bufferSize is not large enough then the
* required size will be returned. 0 is returned if successful.
*/
size_t wrapperQuoteValue(const TCHAR* value, TCHAR *buffer, size_t bufferSize) {
size_t len = _tcslen(value);
size_t in = 0;
size_t out = 0;
size_t in2;
int escape;
/* Initial quote. */
if (out < bufferSize) {
buffer[out] = TEXT('"');
}
out++;
/* Copy over characters of value. */
while ((in < len) && (value[in] != TEXT('\0'))) {
escape = FALSE;
if (value[in] == TEXT('\\')) {
/* All '\' characters in a row prior to a '"' or the end of the string need to be
* escaped */
in2 = in + 1;
while ((in2 < len) && (value[in2] == TEXT('\\'))) {
in2++;
}
escape = ((in2 >= len) || (value[in2] == TEXT('"')));
} else if (value[in] == TEXT('"')) {
escape = TRUE;
}
if (escape) {
/* Needs to be escaped. */
if (out < bufferSize) {
buffer[out] = TEXT('\\');
}
out++;
}
if (out < bufferSize) {
buffer[out] = value[in];
}
out++;
in++;
}
/* Trailing quote. */
if (out < bufferSize) {
buffer[out] = TEXT('"');
}
out++;
/* Null terminate. */
if (out < bufferSize) {
buffer[out] = TEXT('\0');
}
out++;
if (out <= bufferSize) {
return 0;
} else {
return out;
}
}
/**
* Checks the quotes in the value and displays an error if there are any problems.
* This can be useful to help users debug quote problems.
*/
int wrapperCheckQuotes(const TCHAR *value, const TCHAR *propName) {
size_t len = _tcslen(value);
size_t in = 0;
size_t in2 = 0;
int inQuote = FALSE;
int escaped;
while (in < len) {
if (value[in] == TEXT('"')) {
/* Decide whether or not this '"' is escaped. */
in2 = in - 1;
escaped = FALSE;
while (value[in2] == TEXT('\\')) {
escaped = !escaped;
if (in2 > 0) {
in2--;
} else {
break;
}
}
if (!escaped) {
inQuote = !inQuote;
}
} else if (inQuote) {
/* Quoted text. */
} else {
/* Unquoted. white space is bad. */
if (value[in] == TEXT(' ')) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_ERROR,
TEXT("The value of property '%s', '%s' contains unquoted spaces and will most likely result in an invalid java command line."),
propName, value);
return 1;
}
}
in++;
}
if (inQuote) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_ERROR,
TEXT("The value of property '%s', '%s' contains an unterminated quote and will most likely result in an invalid java command line."),
propName, value);
return 1;
}
return 0;
}
#ifndef WIN32
int checkIfExecutable(const TCHAR *filename) {
int result;
#if defined(WIN32) && !defined(WIN64)
struct _stat64i32 statInfo;
#else
struct stat statInfo;
#endif
result = _tstat(filename, &statInfo);
if (result < 0) {
return 0;
}
if (!S_ISREG(statInfo.st_mode)) {
return 0;
}
if (statInfo.st_uid == geteuid()) {
return statInfo.st_mode & S_IXUSR;
}
if (statInfo.st_gid == getegid()) {
return statInfo.st_mode & S_IXGRP;
}
return statInfo.st_mode & S_IXOTH;
}
#endif
int checkIfBinary(const TCHAR *filename) {
FILE* f;
unsigned char head[5];
int r;
f = _tfopen(filename, TEXT("rb"));
if (!f) { /*couldnt find the java command... wrapper will moan later*/
return 1;
} else {
r = (int)fread( head,1, 4, f);
if (r != 4)
{
fclose(f);
return 0;
}
fclose(f);
head[4] = '\0';
if (wrapperData->isDebugging) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_DEBUG, TEXT("Magic number for file %s: 0x%02x%02x%02x%02x"), filename, head[0], head[1], head[2], head[3]);
}
#if defined(LINUX) || defined(FREEBSD) || defined(SOLARIS)
if (head[1] == 'E' && head[2] == 'L' && head[3] == 'F') {
return 1; /*ELF */
#elif defined(AIX)
/* http://en.wikipedia.org/wiki/XCOFF */
if (head[0] == 0x01 && head[1] == 0xf7 && head[2] == 0x00) { /* 0x01f700NN */
return 1; /*xcoff 64*/
} else if (head[0] == 0x01 && head[1] == 0xdf && head[2] == 0x00) { /* 0x01df00NN */
return 1; /*xcoff 32*/
#elif defined(MACOSX)
if (head[0] == 0xca && head[1] == 0xfe && head[2] == 0xba && head[3] == 0xbe) { /* 0xcafebabe */
return 1; /*MACOS Universal binary*/
} else if (head[0] == 0xcf && head[1] == 0xfa && head[2] == 0xed && head[3] == 0xfe) { /* 0xcffaedfe */
return 1; /*MACOS x86_64 binary*/
} else if (head[0] == 0xce && head[1] == 0xfa && head[2] == 0xed && head[3] == 0xfe) { /* 0xcefaedfe */
return 1; /*MACOS i386 binary*/
} else if (head[0] == 0xfe && head[1] == 0xed && head[2] == 0xfa && head[3] == 0xce) { /* 0xfeedface */
return 1; /*MACOS ppc, ppc64 binary*/
#elif defined(HPUX)
if (head[0] == 0x02 && head[1] == 0x10 && head[2] == 0x01 && head[3] == 0x08) { /* 0x02100108 PA-RISC 1.1 */
return 1; /*HP UX PA RISC 32*/
} else if (head[0] == 0x02 && head[1] == 0x14 && head[2] == 0x01 && head[3] == 0x07) { /* 0x02140107 PA-RISC 2.0 */
return 1; /*HP UX PA RISC 32*/
} else if (head[1] == 'E' && head[2] == 'L' && head[3] == 'F') {
return 1; /*ELF */
#elif defined(WIN32)
if (head[0] == 'M' && head[1] == 'Z') {
return 1; /* MS */
#else
if (FALSE) {
#error I dont know what to do for this host type. (in checkIfBinary())
#endif
} else {
return 0;
}
}
}
#ifndef WIN32
TCHAR* findPathOf(const TCHAR *exe, const TCHAR *name) {
TCHAR *searchPath;
TCHAR *beg, *end;
int stop, found;
TCHAR pth[PATH_MAX + 1];
TCHAR *ret;
TCHAR resolvedPath[PATH_MAX + 1];
if (exe[0] == TEXT('/')) {
/* This is an absolute reference. */
if (_trealpath(exe, resolvedPath)) {
_tcsncpy(pth, resolvedPath, PATH_MAX + 1);
if (checkIfExecutable(pth)) {
ret = malloc((_tcslen(pth) + 1) * sizeof(TCHAR));
if (!ret) {
outOfMemory(TEXT("FPO"), 1);
return NULL;
}
_tcsncpy(ret, pth, _tcslen(pth) + 1);
if (wrapperData->isDebugging) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_DEBUG, TEXT("Resolved the real path of %s as an absolute reference: %s"), name, ret);
}
return ret;
}
} else {
if (wrapperData->isDebugging) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_DEBUG, TEXT("Unable to resolve the real path of %s as an absolute reference: %s (Problem at: %s)"), name, exe, resolvedPath);
}
}
return NULL;
}
/* This is a non-absolute reference. See if it is a relative reference. */
if (_trealpath(exe, resolvedPath)) {
/* Resolved. See if the file exists. */
_tcsncpy(pth, resolvedPath, PATH_MAX + 1);
if (checkIfExecutable(pth)) {
ret = malloc((_tcslen(pth) + 1) * sizeof(TCHAR));
if (!ret) {
outOfMemory(TEXT("FPO"), 2);
return NULL;
}
_tcsncpy(ret, pth, _tcslen(pth) + 1);
if (wrapperData->isDebugging) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_DEBUG, TEXT("Resolved the real path of %s as a relative reference: %s"), name, ret);
}
return ret;
}
} else {
if (wrapperData->isDebugging) {
/* Some platforms (MACOSX) will return the point that was the problem, it seems to work
* on some other platforms but is documented as undefined. To be safe and keep things
* in sync, don't use it. */
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_DEBUG, TEXT("Unable to resolve the real path of %s as a relative reference: %s"), name, exe);
}
}
/* The file was not a direct relative reference. If and only if it does not contain any relative path components, we can search the PATH. */
if (_tcschr(exe, TEXT('/')) == NULL) {
searchPath = _tgetenv(TEXT("PATH"));
if (searchPath && (_tcslen(searchPath) <= 0)) {
#if !defined(WIN32) && defined(UNICODE)
free(searchPath);
#endif
searchPath = NULL;
}
if (searchPath) {
if (wrapperData->isDebugging) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_DEBUG, TEXT("Attempt to locate %s on system PATH: %s"), name, exe);
}
beg = searchPath;
stop = 0; found = 0;
do {
end = _tcschr(beg, TEXT(':'));
if (end == NULL) {
/* This is the last element in the PATH, so we want the whole thing. */
stop = 1;
_tcsncpy(pth, beg, PATH_MAX + 1);
} else {
/* Copy the single path entry. */
_tcsncpy(pth, beg, end - beg);
pth[end - beg] = TEXT('\0');
}
if (pth[_tcslen(pth) - 1] != TEXT('/')) {
_tcsncat(pth, TEXT("/"), PATH_MAX + 1);
}
_tcsncat(pth, exe, PATH_MAX + 1);
/* The file can exist on the path, but via a symbolic link, so we need to expand it. Ignore errors here. */
#ifdef _DEBUG
if (wrapperData->isDebugging) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_DEBUG, TEXT(" Check PATH entry: %s"), pth);
}
#endif
if (_trealpath(pth, resolvedPath) != NULL) {
/* Copy over the result. */
_tcsncpy(pth, resolvedPath, PATH_MAX + 1);
found = checkIfExecutable(pth);
}
if (!stop) {
beg = end + 1;
}
} while (!stop && !found);
#if !defined(WIN32) && defined(UNICODE)
free(searchPath);
#endif
if (found) {
ret = malloc((_tcslen(pth) + 1) * sizeof(TCHAR));
if (!ret) {
outOfMemory(TEXT("FPO"), 3);
return NULL;
}
_tcsncpy(ret, pth, _tcslen(pth) + 1);
if (wrapperData->isDebugging) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_DEBUG, TEXT("Resolved the real path of %s from system PATH: %s"), name, ret);
}
return ret;
} else {
if (wrapperData->isDebugging) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_DEBUG, TEXT("Unable to resolve the real path of %s on the system PATH: %s"), name, exe);
}
}
}
}
/* Still did not find the file. So it must not exist. */
return NULL;
}
#endif
/**
* Checks to see if the speicified executable is a regular binary. This will continue
* in either case, but a warning will be logged if the binary is invalid.
*
* @param para The binary to check. On UNIX, the para memory may be freed and reallocated by this call.
*/
void checkIfRegularExe(TCHAR** para) {
TCHAR* path;
#ifdef WIN32
int len, start;
#endif
#ifdef WIN32
if (_tcschr(*para, TEXT('\"')) != NULL){
start = 1;
len = (int)_tcslen(*para) - 2;
} else {
start = 0;
len = (int)_tcslen(*para);
}
path = malloc(sizeof(TCHAR) * (len + 1));
if (!path){
outOfMemory(TEXT("CIRE"), 1);
} else {
_tcsncpy(path, (*para) + start, len);
path[len] = TEXT('\0');
#else
int replacePath;
path = findPathOf(*para, TEXT("wrapper.java.command"));
if (!path) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_WARN, TEXT("The configured wrapper.java.command could not be found, attempting to launch anyway: %s"), *para);
} else {
replacePath = getBooleanProperty(properties, TEXT("wrapper.java.command.resolve"), TRUE);
if (replacePath == TRUE) {
free(*para);
*para = malloc((_tcslen(path) + 1) * sizeof(TCHAR));
if (!(*para)) {
outOfMemory(TEXT("CIRE"), 2);
free(path);
return;
}
_tcsncpy(*para, path, _tcslen(path) + 1);
}
#endif
if (!checkIfBinary(path)) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_WARN, TEXT("The value of wrapper.java.command does not appear to be a java binary."));
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_WARN, TEXT("The use of scripts is not supported. Trying to continue, but some features may not work correctly.."));
}
free(path);
}
}
/**
* Builds up the java command section of the Java command line.
*
* @return The final index into the strings array, or -1 if there were any problems.
*/
int wrapperBuildJavaCommandArrayJavaCommand(TCHAR **strings, int addQuotes, int detectDebugJVM, int index) {
const TCHAR *prop;
TCHAR *c;
#ifdef WIN32
TCHAR cpPath[512];
int found;
#endif
if (strings) {
prop = getStringProperty(properties, TEXT("wrapper.java.command"), TEXT("java"));
#ifdef WIN32
found = 0;
if (_tcscmp(prop, TEXT("")) == 0) {
/* If the java command is an empty string, we want to look for the
* the java command in the windows registry. */
if (wrapperGetJavaHomeFromWindowsRegistry(cpPath)) {
if (wrapperData->isDebugging) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_DEBUG,
TEXT("Loaded java home from registry: %s"), cpPath);
}
addProperty(properties, NULL, 0, TEXT("set.WRAPPER_JAVA_HOME"), cpPath, TRUE, FALSE, FALSE, TRUE);
_tcsncat(cpPath, TEXT("\\bin\\java.exe"), 512);
if (wrapperData->isDebugging) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_DEBUG,
TEXT("Found Java Runtime Environment home directory in system registry."));
}
found = 1;
} else {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_FATAL,
TEXT("The Java Runtime Environment home directory could not be located in the system registry."));
found = 0;
return -1;
}
} else {
/* To avoid problems on Windows XP systems, the '/' characters must
* be replaced by '\' characters in the specified path.
* prop is supposed to be constant, but allow this change as it is
* the actual value that we want. */
correctWindowsPath((TCHAR *)prop);
/* If the full path to the java command was not specified, then we
* need to try and resolve it here to avoid problems later when
* calling CreateProcess. CreateProcess will look in the windows
* system directory before searching the PATH. This can lead to
* the wrong JVM being run. */
_sntprintf(cpPath, 512, TEXT("%s"), prop);
if ((PathFindOnPath((TCHAR*)cpPath, (TCHAR**)wrapperGetSystemPath())) && (!PathIsDirectory(cpPath))) {
/*printf("Found %s on path.\n", cpPath); */
found = 1;
} else {
/*printf("Could not find %s on path.\n", cpPath); */
/* Try adding .exe to the end */
_sntprintf(cpPath, 512, TEXT("%s.exe"), prop);
if ((PathFindOnPath(cpPath, wrapperGetSystemPath())) && (!PathIsDirectory(cpPath))) {
/*printf("Found %s on path.\n", cpPath); */
found = 1;
} else {
/*printf("Could not find %s on path.\n", cpPath); */
}
}
}
if (found) {
strings[index] = malloc(sizeof(TCHAR) * (_tcslen(cpPath) + 2 + 1));
if (!strings[index]) {
outOfMemory(TEXT("WBJCAJC"), 1);
return -1;
}
if (addQuotes) {
_sntprintf(strings[index], _tcslen(cpPath) + 2 + 1, TEXT("\"%s\""), cpPath);
} else {
_sntprintf(strings[index], _tcslen(cpPath) + 2 + 1, TEXT("%s"), cpPath);
}
} else {
strings[index] = malloc(sizeof(TCHAR) * (_tcslen(prop) + 2 + 1));
if (!strings[index]) {
outOfMemory(TEXT("WBJCAJC"), 2);
return -1;
}
if (addQuotes) {
_sntprintf(strings[index], _tcslen(prop) + 2 + 1, TEXT("\"%s\""), prop);
} else {
_sntprintf(strings[index], _tcslen(prop) + 2 + 1, TEXT("%s"), prop);
}
}
if (addQuotes) {
wrapperCheckQuotes(strings[index], TEXT("wrapper.java.command"));
}
#else /* UNIX */
strings[index] = malloc(sizeof(TCHAR) * (_tcslen(prop) + 2 + 1));
if (!strings[index]) {
outOfMemory(TEXT("WBJCAJC"), 3);
return -1;
}
if (addQuotes) {
_sntprintf(strings[index], _tcslen(prop) + 2 + 1, TEXT("\"%s\""), prop);
} else {
_sntprintf(strings[index], _tcslen(prop) + 2 + 1, TEXT("%s"), prop);
}
#endif
checkIfRegularExe(&strings[index]);
if (detectDebugJVM) {
c = _tcsstr(strings[index], TEXT("jdb"));
if (c && ((unsigned int)(c - strings[index]) == _tcslen(strings[index]) - 3 - 1)) {
/* Ends with "jdb". The jdb debugger is being used directly. go into debug JVM mode. */
wrapperData->debugJVM = TRUE;
} else {
c = _tcsstr(strings[index], TEXT("jdb.exe"));
if (c && ((unsigned int)(c - strings[index]) == _tcslen(strings[index]) - 7 - 1)) {
/* Ends with "jdb". The jdb debugger is being used directly. go into debug JVM mode. */
wrapperData->debugJVM = TRUE;
}
}
}
}
index++;
return index;
}
/**
* Builds up the additional section of the Java command line.
*
* @return The final index into the strings array, or -1 if there were any problems.
*/
int wrapperBuildJavaCommandArrayJavaAdditional(TCHAR **strings, int addQuotes, int detectDebugJVM, int index) {
const TCHAR *prop;
int i;
size_t len;
TCHAR paramBuffer2[128];
int quotable;
int defaultStripQuote;
int stripQuote;
TCHAR *propStripped;
TCHAR **propertyNames;
TCHAR **propertyValues;
long unsigned int *propertyIndices;
if (getStringProperties(properties, TEXT("wrapper.java.additional."), TEXT(""), wrapperData->ignoreSequenceGaps, FALSE, &propertyNames, &propertyValues, &propertyIndices)) {
/* Failed */
return -1;
}
defaultStripQuote = getBooleanProperty(properties, TEXT("wrapper.java.additional.default.stripquotes"), FALSE);
i = 0;
while (propertyNames[i]) {
prop = propertyValues[i];
if (prop) {
if (_tcslen(prop) > 0) {
/* All additional parameters must begin with a - or they will be interpretted
* as the being the main class name by Java. */
if (!((_tcsstr(prop, TEXT("-")) == prop) || (_tcsstr(prop, TEXT("\"-")) == prop))) {
/* Only log the message on the second pass. */
if (strings) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_WARN,
TEXT("The value of property '%s', '%s' is not a valid argument to the JVM. Skipping."),
propertyNames[i], prop);
}
} else {
if (strings) {
/* is quotable also changes the value of the property!
therefore prop can potentially point to free'd memory*/
quotable = isQuotableProperty(properties, propertyNames[i]);
prop = getStringProperty(properties, propertyNames[i], NULL);
propertyValues[i] = (TCHAR*) prop;
if (prop == NULL) {
freeStringProperties(propertyNames, propertyValues, propertyIndices);
return -1;
}
_sntprintf(paramBuffer2, 128, TEXT("wrapper.java.additional.%lu.stripquotes"), propertyIndices[i]);
if (addQuotes) {
stripQuote = FALSE;
} else {
stripQuote = getBooleanProperty(properties, paramBuffer2, defaultStripQuote);
}
if (stripQuote) {
propStripped = malloc(sizeof(TCHAR) * (_tcslen(prop) + 1));
if (!propStripped) {
freeStringProperties(propertyNames, propertyValues, propertyIndices);
outOfMemory(TEXT("WBJCAJA"), 2);
return -1;
}
wrapperStripQuotes(prop, propStripped);
} else {
propStripped = (TCHAR *)prop;
}
if (addQuotes && quotable && _tcschr(propStripped, TEXT(' '))) {
len = wrapperQuoteValue(propStripped, NULL, 0);
strings[index] = malloc(sizeof(TCHAR) * len);
if (!strings[index]) {
outOfMemory(TEXT("WBJCAJA"), 3);
freeStringProperties(propertyNames, propertyValues, propertyIndices);
if (stripQuote) {
free(propStripped);
}
return -1;
}
wrapperQuoteValue(propStripped, strings[index], len);
} else {
strings[index] = malloc(sizeof(TCHAR) * (_tcslen(propStripped) + 1));
if (!strings[index]) {
outOfMemory(TEXT("WBJCAJA"), 4);
freeStringProperties(propertyNames, propertyValues, propertyIndices);
if (stripQuote) {
free(propStripped);
}
return -1;
}
_sntprintf(strings[index], _tcslen(propStripped) + 1, TEXT("%s"), propStripped);
}
if (addQuotes) {
wrapperCheckQuotes(strings[index], propertyNames[i]);
}
if (stripQuote) {
free(propStripped);
propStripped = NULL;
}
/* Set if this paremeter enables debugging. */
if (detectDebugJVM) {
if (_tcsstr(strings[index], TEXT("-Xdebug")) == strings[index]) {
wrapperData->debugJVM = TRUE;
}
}
}
index++;
}
}
i++;
}
}
freeStringProperties(propertyNames, propertyValues, propertyIndices);
return index;
}
/**
* Java command line callback.
*/
static int loadParameterFileCallbackParam_AddArg(LoadParameterFileCallbackParam *param, TCHAR *arg, size_t argLen)
{
TCHAR str[MAX_PROPERTY_VALUE_LENGTH];
TCHAR *s;
size_t len;
#ifdef _DEBUG
memcpy(str, arg, sizeof(TCHAR) * argLen);
str[argLen] = TEXT('\0');
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_NOTICE, TEXT(" :> %s"), str);
#endif
if (param->isJVMParam == TRUE) {
/* As in wrapperBuildJavaCommandArrayJavaAdditional(), skip an
argument which does not begin with '-'. */
if ((arg[0] != TEXT('-')) && !((arg[0] == TEXT('"')) && (arg[1] == TEXT('-')))) {
if (param->strings) {
memcpy(str, arg, sizeof(TCHAR) * argLen);
str[argLen] = TEXT('\0');
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_WARN,
TEXT("The value '%s' is not a valid argument to the JVM. Skipping."), str);
}
return TRUE;
}
}
if (param->strings) {
if (!param->stripQuote) {
s = arg;
len = argLen;
} else {
len = wrapperStripQuotesInner(arg, argLen, str);
s = str;
}
param->strings[param->index] = malloc(sizeof(TCHAR) * (len + 1));
if (!param->strings[param->index]) {
return FALSE;
}
memcpy(param->strings[param->index], s, sizeof(TCHAR) * len);
param->strings[param->index][len] = TEXT('\0');
}
param->index++;
return TRUE;
}
static int loadParameterFileCallback(void *callbackParam, const TCHAR *fileName, int lineNumber, TCHAR *config, int debugProperties)
{
LoadParameterFileCallbackParam *param = (LoadParameterFileCallbackParam *)callbackParam;
TCHAR *tail_bound;
TCHAR *arg;
TCHAR *s;
int InDelim = FALSE;
int InQuotes = FALSE;
int Escaped = FALSE;
#ifdef _DEBUG
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_NOTICE, TEXT(" : %s"), config);
#endif
/* Assume that the line `config' has no white spaces at its
beginning and end. */
assert(config && _tcslen(config) > 0);
assert(config[0] != TEXT(' ') && config[_tcslen(config) - 1] != TEXT(' '));
tail_bound = config + _tcslen(config) + 1;
for (arg = s = config; s < tail_bound; s++) {
switch (*s) {
case TEXT('\0'):
if (!loadParameterFileCallbackParam_AddArg(param, arg, s - arg)) {
outOfMemory(TEXT("LJAC"), 1);
return FALSE;
}
break;
case TEXT(' '):
Escaped = FALSE;
if (!InDelim && !InQuotes) {
InDelim = TRUE;
if (!loadParameterFileCallbackParam_AddArg(param, arg, s - arg)) {
outOfMemory(TEXT("LJAC"), 2);
return FALSE;
}
}
break;
case TEXT('"'):
if (!Escaped) {
InQuotes = !InQuotes;
}
Escaped = FALSE;
if (InDelim) {
InDelim = FALSE;
arg = s;
}
break;
case TEXT('\\'):
Escaped = !Escaped;
if (InDelim) {
InDelim = FALSE;
arg = s;
}
break;
default:
Escaped = FALSE;
if (InDelim) {
InDelim = FALSE;
arg = s;
}
break;
}
}
return TRUE;
}
/**
* Builds up the additional section of the Java command line.
*
* @return The final index into the strings array, or -1 if there were any problems.
*/
int wrapperLoadParameterFile(TCHAR **strings, int addQuotes, int detectDebugJVM, int index, TCHAR *parameterName, int isJVMParameter) {
const TCHAR *parameterFilePath;
LoadParameterFileCallbackParam callbackParam;
ConfigFileReader reader;
int readResult;
TCHAR prop[256];
parameterFilePath = getFileSafeStringProperty(properties, parameterName, TEXT(""));
#ifdef _DEBUG
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_NOTICE,
TEXT("%s=%s"), parameterName, parameterFilePath ? parameterFilePath : TEXT(""));
#endif
if (_tcslen(parameterFilePath) == 0) {
return index;
}
if (addQuotes) {
callbackParam.stripQuote = FALSE;
} else {
_sntprintf(prop, 256, TEXT("%s.stripquotes"), parameterName);
callbackParam.stripQuote = getBooleanProperty(properties, prop, FALSE);
}
callbackParam.strings = strings;
callbackParam.index = index;
callbackParam.isJVMParam = isJVMParameter;
configFileReader_Initialize(&reader, loadParameterFileCallback, &callbackParam, FALSE);
readResult = configFileReader_Read(&reader, parameterFilePath, TRUE, 0, NULL, 0);
switch (readResult) {
case CONFIG_FILE_READER_SUCCESS:
return callbackParam.index;
case CONFIG_FILE_READER_FAIL:
case CONFIG_FILE_READER_HARD_FAIL:
return -1;
default:
_tprintf(TEXT("Unexpected read error %d\n"), readResult);
return index;
};
}
/**
* Builds up the library path section of the Java command line.
*
* @return The final index into the strings array, or -1 if there were any problems.
*/
int wrapperBuildJavaCommandArrayLibraryPath(TCHAR **strings, int addQuotes, int index) {
const TCHAR *prop;
int i, j;
size_t len2;
size_t cpLen, cpLenAlloc;
TCHAR *tmpString;
TCHAR *systemPath;
TCHAR **propertyNames;
TCHAR **propertyValues;
long unsigned int *propertyIndices;
if (strings) {
if (wrapperData->libraryPathAppendPath) {
/* We are going to want to append the full system path to
* whatever library path is generated. */
#ifdef WIN32
systemPath = _tgetenv(TEXT("PATH"));
#else
systemPath = _tgetenv(TEXT("LD_LIBRARY_PATH"));
#endif
if (systemPath) {
/* If we are going to add our own quotes then we need to make sure that the system
* PATH doesn't contain any of its own. Windows allows users to do this... */
if (addQuotes) {
i = 0;
j = 0;
do {
if (systemPath[i] != TEXT('"') ) {
systemPath[j] = systemPath[i];
j++;
}
i++;
} while (systemPath[j] != TEXT('\0'));
}
}
} else {
systemPath = NULL;
}
prop = getStringProperty(properties, TEXT("wrapper.java.library.path"), NULL);
if (prop) {
/* An old style library path was specified.
* If quotes are being added, check the last character before the
* closing quote. If it is a backslash then Windows will use it to
* escape the quote. To make things work correctly, we need to add
* another backslash first so it will result in a single backslash
* before the quote. */
if (systemPath) {
strings[index] = malloc(sizeof(TCHAR) * (22 + _tcslen(prop) + 1 + _tcslen(systemPath) + 1 + 1));
if (!strings[index]) {
outOfMemory(TEXT("WBJCALP"), 1);
#if !defined(WIN32) && defined(UNICODE)
free(systemPath);
#endif
return -1;
}
if (addQuotes) {
if ((_tcslen(systemPath) > 1) && (systemPath[_tcslen(systemPath) - 1] == TEXT('\\'))) {
_sntprintf(strings[index], 22 + _tcslen(prop) + 1 + _tcslen(systemPath) + 1 + 1, TEXT("-Djava.library.path=\"%s%c%s\\\""), prop, wrapperClasspathSeparator, systemPath);
} else {
_sntprintf(strings[index], 22 + _tcslen(prop) + 1 + _tcslen(systemPath) + 1 + 1, TEXT("-Djava.library.path=\"%s%c%s\""), prop, wrapperClasspathSeparator, systemPath);
}
} else {
_sntprintf(strings[index], 22 + _tcslen(prop) + 1 + _tcslen(systemPath) + 1 + 1, TEXT("-Djava.library.path=%s%c%s"), prop, wrapperClasspathSeparator, systemPath);
}
} else {
strings[index] = malloc(sizeof(TCHAR) * (22 + _tcslen(prop) + 1 + 1));
if (!strings[index]) {
outOfMemory(TEXT("WBJCALP"), 2);
return -1;
}
if (addQuotes) {
if ((_tcslen(prop) > 1) && (prop[_tcslen(prop) - 1] == TEXT('\\'))) {
_sntprintf(strings[index], 22 + _tcslen(prop) + 1 + 1, TEXT("-Djava.library.path=\"%s\\\""), prop);
} else {
_sntprintf(strings[index], 22 + _tcslen(prop) + 1 + 1, TEXT("-Djava.library.path=\"%s\""), prop);
}
} else {
_sntprintf(strings[index], 22 + _tcslen(prop) + 1 + 1, TEXT("-Djava.library.path=%s"), prop);
}
}
if (addQuotes) {
wrapperCheckQuotes(strings[index], TEXT("wrapper.java.library.path"));
}
} else {
/* Look for a multiline library path. */
cpLen = 0;
cpLenAlloc = 1024;
strings[index] = malloc(sizeof(TCHAR) * cpLenAlloc);
if (!strings[index]) {
outOfMemory(TEXT("WBJCALP"), 3);
#if !defined(WIN32) && defined(UNICODE)
if (systemPath) {
free(systemPath);
}
#endif
return -1;
}
/* Start with the property value. */
_sntprintf(&(strings[index][cpLen]), cpLenAlloc, TEXT("-Djava.library.path="));
cpLen += 20;
/* Add an open quote to the library path */
if (addQuotes) {
_sntprintf(&(strings[index][cpLen]), cpLenAlloc, TEXT("\""));
cpLen++;
}
/* Loop over the library path entries adding each one */
if (getStringProperties(properties, TEXT("wrapper.java.library.path."), TEXT(""), wrapperData->ignoreSequenceGaps, FALSE, &propertyNames, &propertyValues, &propertyIndices)) {
/* Failed */
#if !defined(WIN32) && defined(UNICODE)
if (systemPath) {
free(systemPath);
}
#endif
return -1;
}
i = 0;
j = 0;
while (propertyNames[i]) {
prop = propertyValues[i];
if (prop) {
len2 = _tcslen(prop);
if (len2 > 0) {
/* Is there room for the entry? */
while (cpLen + len2 + 3 > cpLenAlloc) {
/* Resize the buffer */
tmpString = strings[index];
cpLenAlloc += 1024;
strings[index] = malloc(sizeof(TCHAR) * cpLenAlloc);
if (!strings[index]) {
outOfMemory(TEXT("WBJCALP"), 4);
#if !defined(WIN32) && defined(UNICODE)
if (systemPath) {
free(systemPath);
}
#endif
return -1;
}
_sntprintf(strings[index], cpLenAlloc, TEXT("%s"), tmpString);
free(tmpString);
tmpString = NULL;
}
if (j > 0) {
strings[index][cpLen++] = wrapperClasspathSeparator; /* separator */
}
_sntprintf(&(strings[index][cpLen]), cpLenAlloc, TEXT("%s"), prop);
cpLen += len2;
j++;
}
i++;
}
}
freeStringProperties(propertyNames, propertyValues, propertyIndices);
if (systemPath) {
/* We need to append the system path. */
len2 = _tcslen(systemPath);
if (len2 > 0) {
/* Is there room for the entry? */
while (cpLen + len2 + 3 > cpLenAlloc) {
/* Resize the buffer */
tmpString = strings[index];
cpLenAlloc += 1024;
strings[index] = malloc(sizeof(TCHAR) * cpLenAlloc);
if (!strings[index]) {
outOfMemory(TEXT("WBJCALP"), 5);
#if !defined(WIN32) && defined(UNICODE)
free(systemPath);
#endif
return -1;
}
_sntprintf(strings[index], cpLenAlloc, TEXT("%s"), tmpString);
free(tmpString);
tmpString = NULL;
}
if (j > 0) {
strings[index][cpLen++] = wrapperClasspathSeparator; /* separator */
}
_sntprintf(&(strings[index][cpLen]), cpLenAlloc, TEXT("%s"), systemPath);
cpLen += len2;
j++;
}
}
if (j == 0) {
/* No library path, use default. always room */
_sntprintf(&(strings[index][cpLen++]), cpLenAlloc, TEXT("./"));
}
/* Add ending quote. If the previous character is a backslash then
* Windows will use it to escape the quote. To make things work
* correctly, we need to add another backslash first so it will
* result in a single backslash before the quote. */
if (addQuotes) {
if (strings[index][cpLen - 1] == TEXT('\\')) {
_sntprintf(&(strings[index][cpLen]), cpLenAlloc, TEXT("\\"));
cpLen++;
}
_sntprintf(&(strings[index][cpLen]), cpLenAlloc, TEXT("\""));
cpLen++;
}
if (addQuotes) {
wrapperCheckQuotes(strings[index], TEXT("wrapper.java.library.path."));
}
}
#if !defined(WIN32) && defined(UNICODE)
if (systemPath) {
free(systemPath);
}
#endif
}
index++;
return index;
}
/**
* Builds up the java classpath.
*
* @return 0 if successful, or -1 if there were any problems.
*/
int wrapperBuildJavaClasspath(TCHAR **classpath) {
const TCHAR *prop;
TCHAR *propStripped;
TCHAR *propBaseDir;
int i, j;
size_t cpLen, cpLenAlloc;
size_t len2;
TCHAR *tmpString;
#if defined(WIN32) && !defined(WIN64)
struct _stat64i32 statBuffer;
#else
struct stat statBuffer;
#endif
TCHAR **propertyNames;
TCHAR **propertyValues;
long unsigned int *propertyIndices;
TCHAR **files;
int cnt;
/* Build a classpath */
cpLen = 0;
cpLenAlloc = 1024;
*classpath = malloc(sizeof(TCHAR) * cpLenAlloc);
if (!*classpath) {
outOfMemory(TEXT("WBJCP"), 1);
return -1;
}
/* Loop over the classpath entries adding each one. */
if (getStringProperties(properties, TEXT("wrapper.java.classpath."), TEXT(""), wrapperData->ignoreSequenceGaps, FALSE, &propertyNames, &propertyValues, &propertyIndices)) {
/* Failed */
return -1;
}
i = 0;
j = 0;
while (propertyNames[i]) {
prop = propertyValues[i];
/* Does this contain any quotes? */
if (_tcschr(prop, TEXT('"'))) {
propStripped = malloc(sizeof(TCHAR) * (_tcslen(prop) + 1));
if (!propStripped) {
outOfMemory(TEXT("WBJCP"), 2);
freeStringProperties(propertyNames, propertyValues, propertyIndices);
return -1;
}
wrapperStripQuotes(prop, propStripped);
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_DEBUG, TEXT(
"Classpath element, %s, should not contain quotes: %s, stripping and continuing: %s"), propertyNames[i], prop, propStripped);
} else {
propStripped = (TCHAR *)prop;
}
len2 = _tcslen(propStripped);
if (len2 > 0) {
/* Does this contain wildcards? */
if ((_tcsrchr(propStripped, TEXT('*')) != NULL) || (_tcschr(propStripped, TEXT('?')) != NULL)) {
/* Need to do a wildcard search */
files = wrapperFileGetFiles(propStripped, WRAPPER_FILE_SORT_MODE_NAMES_ASC);
if (!files) {
/* Failed */
if (propStripped != prop) {
free(propStripped);
}
freeStringProperties(propertyNames, propertyValues, propertyIndices);
return -1;
}
/* Loop over the files. */
cnt = 0;
while (files[cnt]) {
len2 = _tcslen(files[cnt]);
/* Is there room for the entry? */
if (cpLen + len2 + 3 > cpLenAlloc) {
/* Resize the buffer */
tmpString = *classpath;
cpLenAlloc += len2 + 3;
*classpath = malloc(sizeof(TCHAR) * cpLenAlloc);
if (!*classpath) {
if (propStripped != prop) {
free(propStripped);
}
wrapperFileFreeFiles(files);
freeStringProperties(propertyNames, propertyValues, propertyIndices);
outOfMemory(TEXT("WBJCP"), 2);
return -1;
}
if (j > 0) {
_sntprintf(*classpath, cpLenAlloc, TEXT("%s"), tmpString);
}
free(tmpString);
tmpString = NULL;
}
if (j > 0) {
(*classpath)[cpLen++] = wrapperClasspathSeparator; /* separator */
}
_sntprintf(&((*classpath)[cpLen]), cpLenAlloc, TEXT("%s"), files[cnt]);
cpLen += len2;
j++;
cnt++;
}
wrapperFileFreeFiles(files);
} else {
/* This classpath entry does not contain any wildcards. */
/* If the path element is a directory then we want to strip the trailing slash if it exists. */
propBaseDir = (TCHAR*)propStripped;
if ((propStripped[_tcslen(propStripped) - 1] == TEXT('/')) || (propStripped[_tcslen(propStripped) - 1] == TEXT('\\'))) {
propBaseDir = malloc(sizeof(TCHAR) * _tcslen(propStripped));
if (!propBaseDir) {
outOfMemory(TEXT("WBJCP"), 3);
if (propStripped != prop) {
free(propStripped);
}
freeStringProperties(propertyNames, propertyValues, propertyIndices);
return -1;
}
_tcsncpy(propBaseDir, propStripped, _tcslen(propStripped) - 1);
propBaseDir[_tcslen(propStripped) - 1] = TEXT('\0');
}
/* See if it exists so we can display a debug warning if it does not. */
if (_tstat(propBaseDir, &statBuffer)) {
/* Encountered an error of some kind. */
if ((errno == ENOENT) || (errno == 3)) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_DEBUG, TEXT(
"Classpath element, %s, does not exist: %s"), propertyNames[i], propStripped);
} else {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_ERROR, TEXT(
"Unable to get information of classpath element: %s (%s)"),
propStripped, getLastErrorText());
}
} else {
/* Got the stat info. */
}
/* If we allocated the propBaseDir buffer then free it up. */
if (propBaseDir != propStripped) {
free(propBaseDir);
}
propBaseDir = NULL;
/* Is there room for the entry? */
if (cpLen + len2 + 3 > cpLenAlloc) {
/* Resize the buffer */
tmpString = *classpath;
cpLenAlloc += len2 + 3;
*classpath = malloc(sizeof(TCHAR) * cpLenAlloc);
if (!*classpath) {
outOfMemory(TEXT("WBJCP"), 4);
if (propStripped != prop) {
free(propStripped);
}
freeStringProperties(propertyNames, propertyValues, propertyIndices);
return -1;
}
if (j > 0) {
_sntprintf(*classpath, cpLenAlloc, TEXT("%s"), tmpString);
}
free(tmpString);
tmpString = NULL;
}
if (j > 0) {
(*classpath)[cpLen++] = wrapperClasspathSeparator; /* separator */
}
_sntprintf(&((*classpath)[cpLen]), cpLenAlloc - cpLen, TEXT("%s"), propStripped);
cpLen += len2;
j++;
}
}
/* If we allocated the propStripped buffer then free it up. */
if (propStripped != prop) {
free(propStripped);
}
propStripped = NULL;
i++;
}
freeStringProperties(propertyNames, propertyValues, propertyIndices);
if (j == 0) {
/* No classpath, use default. always room */
_sntprintf(&(*classpath[cpLen++]), cpLenAlloc, TEXT("./"));
}
return 0;
}
/**
* Builds up the java classpath section of the Java command line.
*
* @return The final index into the strings array, or -1 if there were any problems.
*/
int wrapperBuildJavaCommandArrayClasspath(TCHAR **strings, int addQuotes, int index, const TCHAR *classpath) {
size_t len;
size_t cpLen;
/* Store the classpath */
if (strings) {
strings[index] = malloc(sizeof(TCHAR) * (10 + 1));
if (!strings[index]) {
outOfMemory(TEXT("WBJCAC"), 1);
return -1;
}
_sntprintf(strings[index], 10 + 1, TEXT("-classpath"));
}
index++;
if (strings) {
cpLen = 0;
len = _tcslen(classpath);
strings[index] = malloc(sizeof(TCHAR) * (len + 4));
if (!strings[index]) {
outOfMemory(TEXT("WBJCAC"), 2);
return -1;
}
/* Add an open quote the classpath */
if (addQuotes) {
_sntprintf(&(strings[index][cpLen]), len + 4, TEXT("\""));
cpLen++;
}
_sntprintf(&(strings[index][cpLen]), len + 4, TEXT("%s"), classpath);
cpLen += len;
/* Add ending quote. If the previous character is a backslash then
* Windows will use it to escape the quote. To make things work
* correctly, we need to add another backslash first so it will
* result in a single backslash before the quote. */
if (addQuotes) {
if (strings[index][cpLen - 1] == TEXT('\\')) {
_sntprintf(&(strings[index][cpLen]), len + 4, TEXT("\\"));
cpLen++;
}
_sntprintf(&(strings[index][cpLen]), len + 4, TEXT("\""));
cpLen++;
}
if (addQuotes) {
wrapperCheckQuotes(strings[index], TEXT("wrapper.java.classpath."));
}
}
index++;
return index;
}
/**
* Builds up the app parameters section of the Java command line.
*
* @return The final index into the strings array, or -1 if there were any problems.
*/
int wrapperBuildJavaCommandArrayAppParameters(TCHAR **strings, int addQuotes, int index, int thisIsTestWrapper) {
const TCHAR *prop;
int i;
int quotable;
TCHAR *propStripped;
int defaultStripQuote;
int stripQuote;
TCHAR paramBuffer2[128];
size_t len;
TCHAR **propertyNames;
TCHAR **propertyValues;
long unsigned int *propertyIndices;
if (getStringProperties(properties, TEXT("wrapper.app.parameter."), TEXT(""), wrapperData->ignoreSequenceGaps, FALSE, &propertyNames, &propertyValues, &propertyIndices)) {
/* Failed */
return -1;
}
defaultStripQuote = getBooleanProperty(properties, TEXT("wrapper.app.parameter.default.stripquotes"), FALSE);
i = 0;
while (propertyNames[i]) {
prop = propertyValues[i];
if (_tcslen(prop) > 0) {
if (thisIsTestWrapper && (i == 1) && ((_tcscmp(prop, TEXT("{{TestWrapperBat}}")) == 0) || (_tcscmp(prop, TEXT("{{TestWrapperSh}}")) == 0))) {
/* This is the TestWrapper dummy parameter. Simply skip over it so it doesn't get put into the command line. */
} else {
if (strings) {
quotable = isQuotableProperty(properties, propertyNames[i]);
_sntprintf(paramBuffer2, 128, TEXT("wrapper.app.parameter.%lu.stripquotes"), propertyIndices[i]);
if (addQuotes) {
stripQuote = FALSE;
} else {
stripQuote = getBooleanProperty(properties, paramBuffer2, defaultStripQuote);
}
if (stripQuote) {
propStripped = malloc(sizeof(TCHAR) * (_tcslen(prop) + 1));
if (!propStripped) {
outOfMemory(TEXT("WBJCAAP"), 1);
freeStringProperties(propertyNames, propertyValues, propertyIndices);
return -1;
}
wrapperStripQuotes(prop, propStripped);
} else {
propStripped = (TCHAR *)prop;
}
if (addQuotes && quotable && _tcschr(propStripped, TEXT(' '))) {
len = wrapperQuoteValue(propStripped, NULL, 0);
strings[index] = malloc(sizeof(TCHAR) * len);
if (!strings[index]) {
outOfMemory(TEXT("WBJCAAP"), 2);
if (stripQuote) {
free(propStripped);
}
freeStringProperties(propertyNames, propertyValues, propertyIndices);
return -1;
}
wrapperQuoteValue(propStripped, strings[index], len);
} else {
strings[index] = malloc(sizeof(TCHAR) * (_tcslen(propStripped) + 1));
if (!strings[index]) {
if (stripQuote) {
free(propStripped);
}
freeStringProperties(propertyNames, propertyValues, propertyIndices);
outOfMemory(TEXT("WBJCAAP"), 3);
return -1;
}
_sntprintf(strings[index], _tcslen(propStripped) + 1, TEXT("%s"), propStripped);
}
if (addQuotes) {
wrapperCheckQuotes(strings[index], propertyNames[i]);
}
if (stripQuote) {
free(propStripped);
propStripped = NULL;
}
}
index++;
}
}
i++;
}
freeStringProperties(propertyNames, propertyValues, propertyIndices);
/* precede command line parameters */
if (wrapperData->javaArgValueCount > 0) {
for (i = 0; i < wrapperData->javaArgValueCount; i++) {
if (strings) {
if (addQuotes && _tcschr(wrapperData->javaArgValues[i], TEXT(' '))) {
len = wrapperQuoteValue(wrapperData->javaArgValues[i], NULL, 0);
strings[index] = malloc(sizeof(TCHAR) * len);
if (!strings[index]) {
outOfMemory(TEXT("WBJCAAP"), 4);
return -1;
}
wrapperQuoteValue(wrapperData->javaArgValues[i], strings[index], len);
} else {
strings[index] = malloc(sizeof(TCHAR) * (_tcslen(wrapperData->javaArgValues[i]) + 1));
if (!strings[index]) {
outOfMemory(TEXT("WBJCAAP"), 5);
return -1;
}
_sntprintf(strings[index], _tcslen(wrapperData->javaArgValues[i]) + 1, TEXT("%s"), wrapperData->javaArgValues[i]);
}
}
index++;
}
}
return index;
}
/**
* Loops over and stores all necessary commands into an array which
* can be used to launch a process.
* This method will only count the elements if stringsPtr is NULL.
*
* Note - Next Out Of Memory is #47
*
* @return The final index into the strings array, or -1 if there were any problems.
*/
int wrapperBuildJavaCommandArrayInner(TCHAR **strings, int addQuotes, const TCHAR *classpath) {
int index;
int detectDebugJVM;
const TCHAR *prop;
int initMemory = 0;
int maxMemory;
int thisIsTestWrapper;
setLogPropertyWarnings(properties, strings != NULL);
index = 0;
detectDebugJVM = getBooleanProperty(properties, TEXT("wrapper.java.detect_debug_jvm"), TRUE);
/* Java commnd */
if ((index = wrapperBuildJavaCommandArrayJavaCommand(strings, addQuotes, detectDebugJVM, index)) < 0) {
return -1;
}
/* See if the auto bits parameter is set. Ignored by all but the following platforms. */
#if /*defined(WIN32) || defined(LINUX) ||*/ defined(HPUX) || defined(MACOSX) || defined(SOLARIS) || defined(FREEBSD)
if (getBooleanProperty(properties,
/*#ifdef WIN32
TEXT("wrapper.java.additional.auto_bits.windows"),
#elif defined(LINUX)
TEXT("wrapper.java.additional.auto_bits.linux"),
*/
#if defined(HPUX)
TEXT("wrapper.java.additional.auto_bits.hpux"),
#elif defined(SOLARIS)
TEXT("wrapper.java.additional.auto_bits.solaris"),
#elif defined(FREEBSD)
TEXT("wrapper.java.additional.auto_bits.freebsd"),
#elif defined(MACOSX)
TEXT("wrapper.java.additional.auto_bits.macosx"),
#endif
getBooleanProperty(properties, TEXT("wrapper.java.additional.auto_bits"), FALSE))) {
if (strings) {
strings[index] = malloc(sizeof(TCHAR) * 5);
if (!strings[index]) {
outOfMemory(TEXT("WBJCAI"), 46);
return -1;
}
_sntprintf(strings[index], 5, TEXT("-d%s"), wrapperBits);
}
index++;
}
#endif
/* Store additional java parameters */
if ((index = wrapperBuildJavaCommandArrayJavaAdditional(strings, addQuotes, detectDebugJVM, index)) < 0) {
return -1;
}
/* Store additional java parameters specified in the parameter file */
if ((index = wrapperLoadParameterFile(strings, addQuotes, detectDebugJVM, index, TEXT("wrapper.java.additional_file"), TRUE)) < 0) {
return -1;
}
/* Initial JVM memory */
initMemory = getIntProperty(properties, TEXT("wrapper.java.initmemory"), 0);
if (initMemory > 0) {
if (strings) {
initMemory = __max(initMemory, 1); /* 1 <= n */
strings[index] = malloc(sizeof(TCHAR) * (5 + 10 + 1)); /* Allow up to 10 digits. */
if (!strings[index]) {
outOfMemory(TEXT("WBJCAI"), 8);
return -1;
}
_sntprintf(strings[index], 5 + 10 + 1, TEXT("-Xms%dm"), initMemory);
}
index++;
} else {
/* Set the initMemory so the checks in the maxMemory section below will work correctly. */
initMemory = 3;
}
/* Maximum JVM memory */
maxMemory = getIntProperty(properties, TEXT("wrapper.java.maxmemory"), 0);
if (maxMemory > 0) {
if (strings) {
maxMemory = __max(maxMemory, initMemory); /* initMemory <= n */
strings[index] = malloc(sizeof(TCHAR) * (5 + 10 + 1)); /* Allow up to 10 digits. */
if (!strings[index]) {
outOfMemory(TEXT("WBJCAI"), 10);
return -1;
}
_sntprintf(strings[index], 5 + 10 + 1, TEXT("-Xmx%dm"), maxMemory);
}
index++;
}
/* Library Path */
if ((index = wrapperBuildJavaCommandArrayLibraryPath(strings, addQuotes, index)) < 0) {
return -1;
}
/* Classpath */
if (!wrapperData->environmentClasspath) {
if ((index = wrapperBuildJavaCommandArrayClasspath(strings, addQuotes, index, classpath)) < 0) {
return -1;
}
}
/* Store the Wrapper key */
if (strings) {
strings[index] = malloc(sizeof(TCHAR) * (16 + _tcslen(wrapperData->key) + 1));
if (!strings[index]) {
outOfMemory(TEXT("WBJCAI"), 24);
return -1;
}
if (addQuotes) {
_sntprintf(strings[index], 16 + _tcslen(wrapperData->key) + 1, TEXT("-Dwrapper.key=\"%s\""), wrapperData->key);
} else {
_sntprintf(strings[index], 16 + _tcslen(wrapperData->key) + 1, TEXT("-Dwrapper.key=%s"), wrapperData->key);
}
}
index++;
/* Store the backend connection information. */
if (wrapperData->backendType == WRAPPER_BACKEND_TYPE_PIPE) {
if (strings) {
strings[index] = malloc(sizeof(TCHAR) * (22 + 1));
if (!strings[index]) {
outOfMemory(TEXT("WBJCAI"), 25);
return -1;
}
_sntprintf(strings[index], 22 + 1, TEXT("-Dwrapper.backend=pipe"));
}
index++;
} else {
/* Store the Wrapper server port */
if (strings) {
strings[index] = malloc(sizeof(TCHAR) * (15 + 5 + 1)); /* Port up to 5 characters */
if (!strings[index]) {
outOfMemory(TEXT("WBJCAI"), 26);
return -1;
}
_sntprintf(strings[index], 15 + 5 + 1, TEXT("-Dwrapper.port=%d"), (int)wrapperData->actualPort);
}
index++;
}
/* Store the Wrapper jvm min and max ports. */
if (wrapperData->backendType == WRAPPER_BACKEND_TYPE_SOCKET) {
if (wrapperData->portAddress != NULL) {
if (strings) {
strings[index] = malloc(sizeof(TCHAR) * (_tcslen(TEXT("-Dwrapper.port.address=")) + _tcslen(wrapperData->portAddress) + 1));
if (!strings[index]) {
outOfMemory(TEXT("WBJCAI"), 27);
return -1;
}
_sntprintf(strings[index], _tcslen(TEXT("-Dwrapper.port.address=")) + _tcslen(wrapperData->portAddress) + 1, TEXT("-Dwrapper.port.address=%s"), wrapperData->portAddress);
}
index++;
}
if (wrapperData->jvmPort >= 0) {
if (strings) {
strings[index] = malloc(sizeof(TCHAR) * (19 + 5 + 1)); /* Port up to 5 characters */
if (!strings[index]) {
outOfMemory(TEXT("WBJCAI"), 28);
return -1;
}
_sntprintf(strings[index], 19 + 5 + 1, TEXT("-Dwrapper.jvm.port=%d"), (int)wrapperData->jvmPort);
}
index++;
}
if (strings) {
strings[index] = malloc(sizeof(TCHAR) * (23 + 5 + 1)); /* Port up to 5 characters */
if (!strings[index]) {
outOfMemory(TEXT("WBJCAI"), 29);
return -1;
}
_sntprintf(strings[index], 23 + 5 + 1, TEXT("-Dwrapper.jvm.port.min=%d"), (int)wrapperData->jvmPortMin);
}
index++;
if (strings) {
strings[index] = malloc(sizeof(TCHAR) * (23 + 5 + 1)); /* Port up to 5 characters */
if (!strings[index]) {
outOfMemory(TEXT("WBJCAI"), 30);
return -1;
}
_sntprintf(strings[index], 23 + 5 + 1, TEXT("-Dwrapper.jvm.port.max=%d"), (int)wrapperData->jvmPortMax);
}
index++;
}
/* Store the Wrapper debug flag */
if (wrapperData->isDebugging) {
if (strings) {
strings[index] = malloc(sizeof(TCHAR) * (22 + 1));
if (!strings[index]) {
outOfMemory(TEXT("WBJCAI"), 31);
return -1;
}
if (addQuotes) {
_sntprintf(strings[index], 22 + 1, TEXT("-Dwrapper.debug=\"TRUE\""));
} else {
_sntprintf(strings[index], 22 + 1, TEXT("-Dwrapper.debug=TRUE"));
}
}
index++;
}
/* Store the Wrapper disable console input flag. */
if (getBooleanProperty(properties, TEXT("wrapper.disable_console_input"),
#ifdef WIN32
FALSE
#else
wrapperData->daemonize /* We want to disable console input by default when daemonized. */
#endif
)) {
if (strings) {
strings[index] = malloc(sizeof(TCHAR) * (38 + 1));
if (!strings[index]) {
outOfMemory(TEXT("WBJCAI"), 32);
return -1;
}
if (addQuotes) {
_sntprintf(strings[index], 38 + 1, TEXT("-Dwrapper.disable_console_input=\"TRUE\""));
} else {
_sntprintf(strings[index], 38 + 1, TEXT("-Dwrapper.disable_console_input=TRUE"));
}
}
index++;
}
/* Store the Wrapper listener force stop flag. */
if (getBooleanProperty(properties, TEXT("wrapper.listener.force_stop"), FALSE)) {
if (strings) {
strings[index] = malloc(sizeof(TCHAR) * (38 + 1));
if (!strings[index]) {
outOfMemory(TEXT("WBJCAI"), 33);
return -1;
}
if (addQuotes) {
_sntprintf(strings[index], 38 + 1, TEXT("-Dwrapper.listener.force_stop=\"TRUE\""));
} else {
_sntprintf(strings[index], 38 + 1, TEXT("-Dwrapper.listener.force_stop=TRUE"));
}
}
index++;
}
/* Store the Wrapper PID */
if (strings) {
strings[index] = malloc(sizeof(TCHAR) * (24 + 1)); /* Pid up to 10 characters */
if (!strings[index]) {
outOfMemory(TEXT("WBJCAI"), 34);
return -1;
}
#if defined(SOLARIS) && (!defined(_LP64))
_sntprintf(strings[index], 24 + 1, TEXT("-Dwrapper.pid=%ld"), wrapperData->wrapperPID);
#else
_sntprintf(strings[index], 24 + 1, TEXT("-Dwrapper.pid=%d"), wrapperData->wrapperPID);
#endif
}
index++;
/* Store a flag telling the JVM to use the system clock. */
if (wrapperData->useSystemTime) {
if (strings) {
strings[index] = malloc(sizeof(TCHAR) * (32 + 1));
if (!strings[index]) {
outOfMemory(TEXT("WBJCAI"), 35);
return -1;
}
if (addQuotes) {
_sntprintf(strings[index], 32 + 1, TEXT("-Dwrapper.use_system_time=\"TRUE\""));
} else {
_sntprintf(strings[index], 32 + 1, TEXT("-Dwrapper.use_system_time=TRUE"));
}
}
index++;
} else {
/* Only pass the timer fast and slow thresholds to the JVM if they are not default.
* These are only used if the system time is not being used. */
if (wrapperData->timerFastThreshold != WRAPPER_TIMER_FAST_THRESHOLD) {
if (strings) {
strings[index] = malloc(sizeof(TCHAR) * (43 + 1)); /* Allow for 10 digits */
if (!strings[index]) {
outOfMemory(TEXT("WBJCAI"), 36);
return -1;
}
if (addQuotes) {
_sntprintf(strings[index], 43 + 1, TEXT("-Dwrapper.timer_fast_threshold=\"%d\""), wrapperData->timerFastThreshold * WRAPPER_TICK_MS / 1000);
} else {
_sntprintf(strings[index], 43 + 1, TEXT("-Dwrapper.timer_fast_threshold=%d"), wrapperData->timerFastThreshold * WRAPPER_TICK_MS / 1000);
}
}
index++;
}
if (wrapperData->timerSlowThreshold != WRAPPER_TIMER_SLOW_THRESHOLD) {
if (strings) {
strings[index] = malloc(sizeof(TCHAR) * (43 + 1)); /* Allow for 10 digits */
if (!strings[index]) {
outOfMemory(TEXT("WBJCAI"), 37);
return -1;
}
if (addQuotes) {
_sntprintf(strings[index], 43 + 1, TEXT("-Dwrapper.timer_slow_threshold=\"%d\""), wrapperData->timerSlowThreshold * WRAPPER_TICK_MS / 1000);
} else {
_sntprintf(strings[index], 43 + 1, TEXT("-Dwrapper.timer_slow_threshold=%d"), wrapperData->timerSlowThreshold * WRAPPER_TICK_MS / 1000);
}
}
index++;
}
}
/* Always write the version of the wrapper binary as a property. The
* WrapperManager class uses it to verify that the version matches. */
if (strings) {
strings[index] = malloc(sizeof(TCHAR) * (20 + _tcslen(wrapperVersion) + 1));
if (!strings[index]) {
outOfMemory(TEXT("WBJCAI"), 37);
return -1;
}
if (addQuotes) {
_sntprintf(strings[index], 20 + _tcslen(wrapperVersion) + 1, TEXT("-Dwrapper.version=\"%s\""), wrapperVersion);
} else {
_sntprintf(strings[index], 20 + _tcslen(wrapperVersion) + 1, TEXT("-Dwrapper.version=%s"), wrapperVersion);
}
}
index++;
/* Store the base name of the native library. */
if (strings) {
strings[index] = malloc(sizeof(TCHAR) * (27 + _tcslen(wrapperData->nativeLibrary) + 1));
if (!strings[index]) {
outOfMemory(TEXT("WBJCAI"), 38);
return -1;
}
if (addQuotes) {
_sntprintf(strings[index], 27 + _tcslen(wrapperData->nativeLibrary) + 1, TEXT("-Dwrapper.native_library=\"%s\""), wrapperData->nativeLibrary);
} else {
_sntprintf(strings[index], 27 + _tcslen(wrapperData->nativeLibrary) + 1, TEXT("-Dwrapper.native_library=%s"), wrapperData->nativeLibrary);
}
}
index++;
/* Store the arch name of the wrapper. */
if (strings) {
strings[index] = malloc(sizeof(TCHAR) * (17 + _tcslen(wrapperArch) + 1));
if (!strings[index]) {
outOfMemory(TEXT("WBJCAI"), 39);
return -1;
}
if (addQuotes) {
_sntprintf(strings[index], 17 + _tcslen(wrapperArch) + 1, TEXT("-Dwrapper.arch=\"%s\""), wrapperArch);
} else {
_sntprintf(strings[index], 17 + _tcslen(wrapperArch) + 1, TEXT("-Dwrapper.arch=%s"), wrapperArch);
}
}
index++;
/* Store the ignore signals flag if configured to do so */
if (wrapperData->ignoreSignals & WRAPPER_IGNORE_SIGNALS_JAVA) {
if (strings) {
strings[index] = malloc(sizeof(TCHAR) * (31 + 1));
if (!strings[index]) {
outOfMemory(TEXT("WBJCAI"), 40);
return -1;
}
if (addQuotes) {
_sntprintf(strings[index], 31 + 1, TEXT("-Dwrapper.ignore_signals=\"TRUE\""));
} else {
_sntprintf(strings[index], 31 + 1, TEXT("-Dwrapper.ignore_signals=TRUE"));
}
}
index++;
}
/* If this is being run as a service, add a service flag. */
if (!wrapperData->isConsole) {
if (strings) {
strings[index] = malloc(sizeof(TCHAR) * (24 + 1));
if (!strings[index]) {
outOfMemory(TEXT("WBJCAI"), 41);
return -1;
}
if (addQuotes) {
_sntprintf(strings[index], 24 + 1, TEXT("-Dwrapper.service=\"TRUE\""));
} else {
_sntprintf(strings[index], 24 + 1, TEXT("-Dwrapper.service=TRUE"));
}
}
index++;
}
/* Store the Disable Tests flag */
if (wrapperData->isTestsDisabled) {
if (strings) {
strings[index] = malloc(sizeof(TCHAR) * (30 + 1));
if (!strings[index]) {
outOfMemory(TEXT("WBJCAI"), 42);
return -1;
}
if (addQuotes) {
_sntprintf(strings[index], 30 + 1, TEXT("-Dwrapper.disable_tests=\"TRUE\""));
} else {
_sntprintf(strings[index], 30 + 1, TEXT("-Dwrapper.disable_tests=TRUE"));
}
}
index++;
}
/* Store the Disable Shutdown Hook flag */
if (wrapperData->isShutdownHookDisabled) {
if (strings) {
strings[index] = malloc(sizeof(TCHAR) * (38 + 1));
if (!strings[index]) {
outOfMemory(TEXT("WBJCAI"), 43);
return -1;
}
if (addQuotes) {
_sntprintf(strings[index], 38 + 1, TEXT("-Dwrapper.disable_shutdown_hook=\"TRUE\""));
} else {
_sntprintf(strings[index], 38 + 1, TEXT("-Dwrapper.disable_shutdown_hook=TRUE"));
}
}
index++;
}
/* Store the CPU Timeout value */
if (strings) {
/* Just to be safe, allow 20 characters for the timeout value */
strings[index] = malloc(sizeof(TCHAR) * (24 + 20 + 1));
if (!strings[index]) {
outOfMemory(TEXT("WBJCAI"), 44);
return -1;
}
if (addQuotes) {
_sntprintf(strings[index], 24 + 20 + 1, TEXT("-Dwrapper.cpu.timeout=\"%d\""), wrapperData->cpuTimeout);
} else {
_sntprintf(strings[index], 24 + 20 + 1, TEXT("-Dwrapper.cpu.timeout=%d"), wrapperData->cpuTimeout);
}
}
index++;
if ((prop = getStringProperty(properties, TEXT("wrapper.java.outfile"), NULL))) {
if (strings) {
strings[index] = malloc(sizeof(TCHAR) * (25 + _tcslen(prop) + 1));
if (!strings[index]) {
outOfMemory(TEXT("WBJCAI"), 46);
return -1;
}
if (addQuotes) {
_sntprintf(strings[index], 25 + _tcslen(prop) + 1, TEXT("-Dwrapper.java.outfile=\"%s\""), prop);
} else {
_sntprintf(strings[index], 25 + _tcslen(prop) + 1, TEXT("-Dwrapper.java.outfile=%s"), prop);
}
}
index++;
}
if ((prop = getStringProperty(properties, TEXT("wrapper.java.errfile"), NULL))) {
if (strings) {
strings[index] = malloc(sizeof(TCHAR) * (25 + _tcslen(prop) + 1));
if (!strings[index]) {
outOfMemory(TEXT("WBJCAI"), 47);
return -1;
}
if (addQuotes) {
_sntprintf(strings[index], 25 + _tcslen(prop) + 1, TEXT("-Dwrapper.java.errfile=\"%s\""), prop);
} else {
_sntprintf(strings[index], 25 + _tcslen(prop) + 1, TEXT("-Dwrapper.java.errfile=%s"), prop);
}
}
index++;
}
/* Store the Wrapper JVM ID. (Get here before incremented) */
if (strings) {
strings[index] = malloc(sizeof(TCHAR) * (16 + 5 + 1)); /* jvmid up to 5 characters */
if (!strings[index]) {
outOfMemory(TEXT("WBJCAI"), 48);
return -1;
}
_sntprintf(strings[index], 16 + 5 + 1, TEXT("-Dwrapper.jvmid=%d"), (wrapperData->jvmRestarts + 1));
}
index++;
/* If this JVM will be detached after startup, it needs to know that. */
if (wrapperData->detachStarted) {
if (strings) {
strings[index] = malloc(sizeof(TCHAR) * (30 + 1));
if (!strings[index]) {
outOfMemory(TEXT("WBJCAI"), 51);
return -1;
}
if (addQuotes) {
_sntprintf(strings[index], 30 + 1, TEXT("-Dwrapper.detachStarted=\"TRUE\""));
} else {
_sntprintf(strings[index], 30 + 1, TEXT("-Dwrapper.detachStarted=TRUE"));
}
}
index++;
}
/* Store the main class */
thisIsTestWrapper = FALSE;
prop = getStringProperty(properties, TEXT("wrapper.java.mainclass"), TEXT("Main"));
if (_tcscmp(prop, TEXT("org.tanukisoftware.wrapper.test.Main")) == 0) {
thisIsTestWrapper = TRUE;
} else {
thisIsTestWrapper = FALSE;
}
if (strings) {
strings[index] = malloc(sizeof(TCHAR) * (_tcslen(prop) + 1));
if (!strings[index]) {
outOfMemory(TEXT("WBJCAI"), 52);
return -1;
}
_sntprintf(strings[index], _tcslen(prop) + 1, TEXT("%s"), prop);
}
index++;
/* Store any application parameters */
if ((index = wrapperBuildJavaCommandArrayAppParameters(strings, addQuotes, index, thisIsTestWrapper)) < 0) {
return -1;
}
if ((index = wrapperLoadParameterFile(strings, addQuotes, detectDebugJVM, index, TEXT("wrapper.app.parameter_file"), FALSE)) < 0) {
return -1;
}
return index;
}
/**
* command is a pointer to a pointer of an array of character strings.
* length is the number of strings in the above array.
*
* @return TRUE if there were any problems.
*/
int wrapperBuildJavaCommandArray(TCHAR ***stringsPtr, int *length, int addQuotes, const TCHAR *classpath) {
int reqLen;
/* Reset the flag stating that the JVM is a debug JVM. */
wrapperData->debugJVM = FALSE;
wrapperData->debugJVMTimeoutNotified = FALSE;
/* Find out how long the array needs to be first. */
reqLen = wrapperBuildJavaCommandArrayInner(NULL, addQuotes, classpath);
if (reqLen < 0) {
return TRUE;
}
*length = reqLen;
/* Allocate the correct amount of memory */
*stringsPtr = malloc((*length) * sizeof **stringsPtr );
if (!(*stringsPtr)) {
outOfMemory(TEXT("WBJCA"), 1);
return TRUE;
}
/* Now actually fill in the strings */
reqLen = wrapperBuildJavaCommandArrayInner(*stringsPtr, addQuotes, classpath);
if (reqLen < 0) {
return TRUE;
}
if (wrapperData->debugJVM) {
if ((wrapperData->startupTimeout > 0) || (wrapperData->pingTimeout > 0) ||
(wrapperData->shutdownTimeout > 0) || (wrapperData->jvmExitTimeout > 0)) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_WARN,
TEXT("---------------------------------------------------------------------") );
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_WARN,
TEXT(
"The JVM is being launched with a debugger enabled and could possibly\nbe suspended. To avoid unwanted shutdowns, timeouts will be\ndisabled, removing the ability to detect and restart frozen JVMs."));
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_WARN,
TEXT("---------------------------------------------------------------------") );
}
}
return FALSE;
}
void wrapperFreeJavaCommandArray(TCHAR **strings, int length) {
int i;
if (strings != NULL) {
/* Loop over and free each of the strings in the array */
for (i = 0; i < length; i++) {
if (strings[i] != NULL) {
free(strings[i]);
strings[i] = NULL;
}
}
free(strings);
strings = NULL;
}
}
/**
* Called when the Wrapper detects that the JVM process has exited.
* Contains code common to all platforms.
*/
void wrapperJVMProcessExited(TICKS nowTicks, int exitCode) {
int setState = TRUE;
if (exitCode == 0) {
/* The JVM exit code was 0, so leave any current exit code as is. */
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_DEBUG,
TEXT("JVM process exited with a code of %d, leaving the wrapper exit code set to %d."),
exitCode, wrapperData->exitCode);
} else if (wrapperData->exitCode == 0) {
/* Update the wrapper exitCode. */
wrapperData->exitCode = exitCode;
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_DEBUG,
TEXT("JVM process exited with a code of %d, setting the wrapper exit code to %d."),
exitCode, wrapperData->exitCode);
} else {
/* The wrapper exit code was already non-zero, so leave it as is. */
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_DEBUG,
TEXT("JVM process exited with a code of %d, however the wrapper exit code was already %d."),
exitCode, wrapperData->exitCode);
}
switch(wrapperData->jState) {
case WRAPPER_JSTATE_DOWN_CLEAN:
case WRAPPER_JSTATE_DOWN_CHECK:
case WRAPPER_JSTATE_DOWN_FLUSH:
/* Shouldn't be called in this state. But just in case. */
if (wrapperData->isDebugging) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_DEBUG,
TEXT("JVM already down."));
}
setState = FALSE;
break;
case WRAPPER_JSTATE_LAUNCH_DELAY:
/* We got a message that the JVM process died when we already thought is was down.
* Most likely this was caused by a SIGCHLD signal. We are already in the expected
* state so go ahead and ignore it. Do NOT go back to DOWN or the restart flag
* and all restart counts will have be lost */
if (wrapperData->isDebugging) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_DEBUG,
TEXT("Received a message that the JVM is down when in the LAUNCH(DELAY) state."));
}
setState = FALSE;
break;
case WRAPPER_JSTATE_RESTART:
/* We got a message that the JVM process died when we already thought is was down.
* Most likely this was caused by a SIGCHLD signal. We are already in the expected
* state so go ahead and ignore it. Do NOT go back to DOWN or the restart flag
* and all restart counts will have be lost */
if (wrapperData->isDebugging) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_DEBUG,
TEXT("Received a message that the JVM is down when in the RESTART state."));
}
setState = FALSE;
break;
case WRAPPER_JSTATE_LAUNCH:
/* We got a message that the JVM process died when we already thought is was down.
* Most likely this was caused by a SIGCHLD signal. We are already in the expected
* state so go ahead and ignore it. Do NOT go back to DOWN or the restart flag
* and all restart counts will have be lost.
* This can happen if the Java process dies Immediately after it is launched. It
* is very rare if Java is launched, but can happen if the configuration is set to
* launch something else. */
if (wrapperData->isDebugging) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_DEBUG,
TEXT("Received a message that the JVM is down when in the LAUNCH state."));
}
setState = FALSE;
break;
case WRAPPER_JSTATE_LAUNCHING:
wrapperData->restartRequested = WRAPPER_RESTART_REQUESTED_AUTOMATIC;
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_ERROR,
TEXT("JVM exited while loading the application."));
break;
case WRAPPER_JSTATE_LAUNCHED:
/* Shouldn't be called in this state, but just in case. */
wrapperData->restartRequested = WRAPPER_RESTART_REQUESTED_AUTOMATIC;
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_ERROR,
TEXT("JVM exited before starting the application."));
break;
case WRAPPER_JSTATE_STARTING:
wrapperData->restartRequested = WRAPPER_RESTART_REQUESTED_AUTOMATIC;
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_ERROR,
TEXT("JVM exited while starting the application."));
break;
case WRAPPER_JSTATE_STARTED:
wrapperData->restartRequested = WRAPPER_RESTART_REQUESTED_AUTOMATIC;
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_ERROR,
TEXT("JVM exited unexpectedly."));
break;
case WRAPPER_JSTATE_STOP:
case WRAPPER_JSTATE_STOPPING:
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_WARN,
TEXT("JVM exited unexpectedly while stopping the application."));
break;
case WRAPPER_JSTATE_STOPPED:
if (wrapperData->isDebugging) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_DEBUG,
TEXT("JVM exited normally."));
}
break;
case WRAPPER_JSTATE_KILLING:
case WRAPPER_JSTATE_KILL:
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_INFO,
TEXT("JVM exited on its own while waiting to kill the application."));
break;
case WRAPPER_JSTATE_KILLED:
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS,
TEXT("JVM exited after being requested to terminate."));
break;
default:
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_WARN,
TEXT("Unexpected jState=%d in wrapperJVMProcessExited."), wrapperData->jState);
break;
}
wrapperJVMDownCleanup(setState);
}
void wrapperBuildKey() {
int i;
size_t kcNum;
size_t num;
static int seeded = FALSE;
/* Seed the randomizer */
if (!seeded) {
srand((unsigned)time(NULL));
seeded = TRUE;
}
/* Start by generating a key */
num = _tcslen(keyChars);
for (i = 0; i < 16; i++) {
/* The way rand works, this will sometimes equal num, which is too big.
* This is rare so just round those cases down. */
/* Some platforms use very large RAND_MAX values that cause overflow problems in our math */
if (RAND_MAX > 0x10000) {
kcNum = (size_t)((rand() >> 8) * num / (RAND_MAX >> 8));
} else {
kcNum = (size_t)(rand() * num / RAND_MAX);
}
if (kcNum >= num) {
kcNum = num - 1;
}
wrapperData->key[i] = keyChars[kcNum];
}
wrapperData->key[16] = TEXT('\0');
/*
printf(" Key=%s Len=%lu\n", wrapperData->key, _tcslen(wrapperData->key));
*/
}
#ifdef WIN32
/* The ABOVE and BELOW normal priority class constants are not defined in MFVC 6.0 headers. */
#ifndef ABOVE_NORMAL_PRIORITY_CLASS
#define ABOVE_NORMAL_PRIORITY_CLASS 0x00008000
#endif
#ifndef BELOW_NORMAL_PRIORITY_CLASS
#define BELOW_NORMAL_PRIORITY_CLASS 0x00004000
#endif
/**
* Return FALSE if successful, TRUE if there were problems.
*/
int wrapperBuildNTServiceInfo() {
TCHAR *work;
const TCHAR *priority;
size_t len;
size_t valLen;
size_t workLen;
int i;
TCHAR **propertyNames;
TCHAR **propertyValues;
long unsigned int *propertyIndices;
if (!wrapperData->configured) {
/* Load the service load order group */
updateStringValue(&wrapperData->ntServiceLoadOrderGroup, getStringProperty(properties, TEXT("wrapper.ntservice.load_order_group"), TEXT("")));
if (getStringProperties(properties, TEXT("wrapper.ntservice.dependency."), TEXT(""), wrapperData->ignoreSequenceGaps, FALSE, &propertyNames, &propertyValues, &propertyIndices)) {
/* Failed */
return TRUE;
}
/* Build the dependency list. Decide how large the list needs to be */
len = 0;
i = 0;
while (propertyNames[i]) {
valLen = _tcslen(propertyValues[i]);
if (valLen > 0) {
len += valLen + 1;
}
i++;
}
/* List must end with a double '\0'. If the list is not empty then it will end with 3. But that is fine. */
len += 2;
/* Actually build the buffer */
if (wrapperData->ntServiceDependencies) {
/** This is a reload, so free up the old data. */
free(wrapperData->ntServiceDependencies);
wrapperData->ntServiceDependencies = NULL;
}
work = wrapperData->ntServiceDependencies = malloc(sizeof(TCHAR) * len);
if (!work) {
outOfMemory(TEXT("WBNTSI"), 1);
return TRUE;
}
workLen = len;
/* Now actually build up the list. Each value is separated with a '\0'. */
i = 0;
while (propertyNames[i]) {
valLen = _tcslen(propertyValues[i]);
if (valLen > 0) {
_tcsncpy(work, propertyValues[i], workLen);
work += valLen + 1;
workLen -= valLen + 1;
}
i++;
}
/* Add two more nulls to the end of the list. */
work[0] = TEXT('\0');
work[1] = TEXT('\0');
/* Memory allocated in work is stored in wrapperData. The memory should not be released here. */
work = NULL;
freeStringProperties(propertyNames, propertyValues, propertyIndices);
/* Set the service start type */
if (strcmpIgnoreCase(getStringProperty(properties, TEXT("wrapper.ntservice.starttype"), TEXT("DEMAND_START")), TEXT("AUTO_START")) == 0) {
wrapperData->ntServiceStartType = SERVICE_AUTO_START;
} else {
wrapperData->ntServiceStartType = SERVICE_DEMAND_START;
}
/* Set the service priority class */
priority = getStringProperty(properties, TEXT("wrapper.ntservice.process_priority"), TEXT("NORMAL"));
if ( (strcmpIgnoreCase(priority, TEXT("LOW")) == 0) || (strcmpIgnoreCase(priority, TEXT("IDLE")) == 0) ) {
wrapperData->ntServicePriorityClass = IDLE_PRIORITY_CLASS;
} else if (strcmpIgnoreCase(priority, TEXT("HIGH")) == 0) {
wrapperData->ntServicePriorityClass = HIGH_PRIORITY_CLASS;
} else if (strcmpIgnoreCase(priority, TEXT("REALTIME")) == 0) {
wrapperData->ntServicePriorityClass = REALTIME_PRIORITY_CLASS;
} else if (strcmpIgnoreCase(priority, TEXT("ABOVE_NORMAL")) == 0) {
wrapperData->ntServicePriorityClass = ABOVE_NORMAL_PRIORITY_CLASS;
} else if (strcmpIgnoreCase(priority, TEXT("BELOW_NORMAL")) == 0) {
wrapperData->ntServicePriorityClass = BELOW_NORMAL_PRIORITY_CLASS;
} else {
wrapperData->ntServicePriorityClass = NORMAL_PRIORITY_CLASS;
}
/* Account name */
updateStringValue(&wrapperData->ntServiceAccount, getStringProperty(properties, TEXT("wrapper.ntservice.account"), NULL));
if (wrapperData->ntServiceAccount && (_tcslen(wrapperData->ntServiceAccount) <= 0)) {
wrapperData->ntServiceAccount = NULL;
}
/* Account password */
wrapperData->ntServicePrompt = getBooleanProperty(properties, TEXT("wrapper.ntservice.account.prompt"), FALSE);
if (wrapperData->ntServicePrompt == TRUE) {
wrapperData->ntServicePasswordPrompt = TRUE;
} else {
wrapperData->ntServicePasswordPrompt = getBooleanProperty(properties, TEXT("wrapper.ntservice.password.prompt"), FALSE);
}
wrapperData->ntServicePasswordPromptMask = getBooleanProperty(properties, TEXT("wrapper.ntservice.password.prompt.mask"), TRUE);
updateStringValue(&wrapperData->ntServicePassword, getStringProperty(properties, TEXT("wrapper.ntservice.password"), NULL));
if ( wrapperData->ntServicePassword && ( _tcslen( wrapperData->ntServicePassword ) <= 0 ) ) {
wrapperData->ntServicePassword = NULL;
}
if (!wrapperData->ntServiceAccount) {
/* If there is not account name, then the password must not be set. */
wrapperData->ntServicePassword = NULL;
}
/* Interactive */
wrapperData->ntServiceInteractive = getBooleanProperty(properties, TEXT("wrapper.ntservice.interactive"), FALSE);
/* The interactive flag can not be set if an account is also set. */
if (wrapperData->ntServiceAccount && wrapperData->ntServiceInteractive) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_WARN,
TEXT("Ignoring the wrapper.ntservice.interactive property because it can not be set when wrapper.ntservice.account is also set."));
wrapperData->ntServiceInteractive = FALSE;
}
/* Display a Console Window. */
wrapperData->ntAllocConsole = getBooleanProperty(properties, TEXT("wrapper.ntservice.console"), FALSE);
/* Set the default hide wrapper console flag to the inverse of the alloc console flag. */
wrapperData->ntHideWrapperConsole = !wrapperData->ntAllocConsole;
/* Hide the JVM Console Window. */
wrapperData->ntHideJVMConsole = getBooleanProperty(properties, TEXT("wrapper.ntservice.hide_console"), TRUE);
/* Make sure that a console is always generated to support thread dumps */
wrapperData->generateConsole = getBooleanProperty(properties, TEXT("wrapper.ntservice.generate_console"), TRUE);
}
/* Set the single invocation flag. */
wrapperData->isSingleInvocation = getBooleanProperty(properties, TEXT("wrapper.single_invocation"), FALSE);
wrapperData->threadDumpControlCode = getIntProperty(properties, TEXT("wrapper.thread_dump_control_code"), 255);
if (wrapperData->threadDumpControlCode <= 0) {
/* Disabled */
} else if ((wrapperData->threadDumpControlCode < 128) || (wrapperData->threadDumpControlCode > 255)) {
wrapperData->threadDumpControlCode = 255;
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_WARN,
TEXT("Ignoring the wrapper.thread_dump_control_code property because it must be in the range 128-255 or 0."));
}
return FALSE;
}
#endif
int validateTimeout(const TCHAR* propertyName, int value) {
int okValue;
if (value <= 0) {
okValue = 0;
} else if (value > WRAPPER_TIMEOUT_MAX) {
okValue = WRAPPER_TIMEOUT_MAX;
} else {
okValue = value;
}
if (okValue != value) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_WARN,
TEXT("The value of %s must be in the range 1 to %d seconds (%d days), or 0 to disable. Changing to %d."),
propertyName, WRAPPER_TIMEOUT_MAX, WRAPPER_TIMEOUT_MAX / 86400, okValue);
}
return okValue;
}
void wrapperLoadHostName() {
char hostName[80];
TCHAR* hostName2;
#ifdef UNICODE
int len;
#endif
if (gethostname(hostName, sizeof(hostName))) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_WARN, TEXT("Unable to obtain host name. %s"),
getLastErrorText());
} else {
#ifdef UNICODE
#ifdef WIN32
len = MultiByteToWideChar(CP_OEMCP, 0, hostName, -1, NULL, 0);
hostName2 = malloc((len + 1) * sizeof(LPWSTR));
if (!hostName2) {
outOfMemory(TEXT("LHN"), 1);
return;
}
MultiByteToWideChar(CP_OEMCP,0, hostName, -1, hostName2, len + 1);
#else
len = mbstowcs(NULL, hostName, 0) + 1;
hostName2 = malloc(len * sizeof(TCHAR));
if (!hostName2) {
outOfMemory(TEXT("LHN"), 2);
return;
}
mbstowcs(hostName2, hostName, len);
#endif
#else
/* No conversion needed. Do an extra malloc here to keep the code simple below. */
len = _tcslen(hostName) + 1;
hostName2 = malloc(len * sizeof(TCHAR));
if (!hostName2) {
outOfMemory(TEXT("LHN"), 3);
return;
}
_tcsncpy(hostName2, hostName, len);
#endif
wrapperData->hostName = malloc(sizeof(TCHAR) * (_tcslen(hostName2) + 1));
if (!wrapperData->hostName) {
outOfMemory(TEXT("LHN"), 2);
free(hostName2);
return;
}
_tcsncpy(wrapperData->hostName, hostName2, _tcslen(hostName2) + 1);
free(hostName2);
}
}
/**
* Resolves an action name into an actionId.
*
* @param actionName Action to be resolved. (Contents of buffer will be converted to upper case.)
* @param propertyName The name of the property where the action name originated.
* @param logErrors TRUE if errors should be logged.
*
* @return The action Id, or 0 if it was unknown.
*/
int getActionForName(TCHAR *actionName, const TCHAR *propertyName, int logErrors) {
size_t len;
size_t i;
int action;
/* We need the actionName in upper case. */
len = _tcslen(actionName);
for (i = 0; i < len; i++) {
actionName[i] = _totupper(actionName[i]);
}
if (_tcscmp(actionName, TEXT("RESTART")) == 0) {
action = ACTION_RESTART;
} else if (_tcscmp(actionName, TEXT("SHUTDOWN")) == 0) {
action = ACTION_SHUTDOWN;
} else if (_tcscmp(actionName, TEXT("DUMP")) == 0) {
action = ACTION_DUMP;
} else if (_tcscmp(actionName, TEXT("NONE")) == 0) {
action = ACTION_NONE;
} else if (_tcscmp(actionName, TEXT("DEBUG")) == 0) {
action = ACTION_DEBUG;
} else if (_tcscmp(actionName, TEXT("SUCCESS")) == 0) {
action = ACTION_SUCCESS;
} else if (_tcscmp(actionName, TEXT("GC")) == 0) {
action = ACTION_GC;
} else if (_tcscmp(actionName, TEXT("PAUSE")) == 0) {
if (logErrors) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_WARN, TEXT("Pause actions require the Standard Edition. Ignoring action '%s' in the %s property."), actionName, propertyName);
}
action = 0;
} else if (_tcscmp(actionName, TEXT("RESUME")) == 0) {
if (logErrors) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_WARN, TEXT("Resume actions require the Standard Edition. Ignoring action '%s' in the %s property."), actionName, propertyName);
}
action = 0;
} else if (_tcsstr(actionName, TEXT("USER_")) == actionName) {
if (logErrors) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_WARN, TEXT("User actions require the Professional Edition. Ignoring action '%s' in the %s property."), actionName, propertyName);
}
action = 0;
} else {
if (logErrors) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_WARN, TEXT("Encountered an unknown action '%s' in the %s property. Skipping."), actionName, propertyName);
}
action = 0;
}
return action;
}
/**
* Parses a list of actions for an action property.
*
* @param actionNameList A space separated list of action names.
* @param propertyName The name of the property where the action name originated.
*
* @return an array of integer action ids, or NULL if there were any problems.
*/
int *wrapperGetActionListForNames(const TCHAR *actionNameList, const TCHAR *propertyName) {
size_t len;
TCHAR *workBuffer;
TCHAR *token;
int actionCount;
int action;
int *actionList = NULL;
#if defined(UNICODE) && !defined(WIN32)
TCHAR *state;
#endif
#if _DEBUG
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_INFO, TEXT("wrapperGetActionListForNames(%s, %s)"), actionNameList, propertyName);
#endif
/* First get a count of the number of valid actions. */
len = _tcslen(actionNameList);
workBuffer = malloc(sizeof(TCHAR) * (len + 1));
if (!workBuffer) {
outOfMemory(TEXT("GALFN"), 1);
} else {
actionCount = 0;
_tcsncpy(workBuffer, actionNameList, len + 1);
token = _tcstok(workBuffer, TEXT(" ,")
#if defined(UNICODE) && !defined(WIN32)
, &state
#endif
);
while (token != NULL) {
action = getActionForName(token, propertyName, TRUE);
if (action == 0) {
/* Unknown action */
} else {
actionCount++;
}
#if _DEBUG
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_INFO, TEXT(" action='%s' -> %d"), token, action);
#endif
token = _tcstok(NULL, TEXT(" ,")
#if defined(UNICODE) && !defined(WIN32)
, &state
#endif
);
}
/* Add ACTION_LIST_END */
actionCount++;
/* Create the action list to return. */
actionList = malloc(sizeof(int) * actionCount);
if (!actionList) {
outOfMemory(TEXT("GALFN"), 2);
} else {
/* Now actually pull out the actions */
actionCount = 0;
_tcsncpy(workBuffer, actionNameList, len + 1);
token = _tcstok(workBuffer, TEXT(" ,")
#if defined(UNICODE) && !defined(WIN32)
, &state
#endif
);
while (token != NULL) {
action = getActionForName(token, propertyName, FALSE);
if (action == 0) {
/* Unknown action */
} else {
actionList[actionCount] = action;
actionCount++;
}
token = _tcstok(NULL, TEXT(" ,")
#if defined(UNICODE) && !defined(WIN32)
, &state
#endif
);
}
/* Add ACTION_LIST_END */
actionList[actionCount] = ACTION_LIST_END;
actionCount++;
/* actionList returned, so don't free it. */
}
free(workBuffer);
}
return actionList;
}
/**
* Loads in the configuration triggers.
*
* @return Returns FALSE if successful, TRUE if there were any problems.
*/
int loadConfigurationTriggers() {
const TCHAR *prop;
TCHAR propName[256];
int i;
TCHAR **propertyNames;
TCHAR **propertyValues;
long unsigned int *propertyIndices;
#ifdef _DEBUG
int j;
#endif
/* To support reloading, we need to free up any previously loaded filters. */
if (wrapperData->outputFilterCount > 0) {
for (i = 0; i < wrapperData->outputFilterCount; i++) {
free(wrapperData->outputFilters[i]);
wrapperData->outputFilters[i] = NULL;
}
free(wrapperData->outputFilters);
wrapperData->outputFilters = NULL;
if (wrapperData->outputFilterActionLists) {
for (i = 0; i < wrapperData->outputFilterCount; i++) {
free(wrapperData->outputFilterActionLists[i]);
wrapperData->outputFilterActionLists[i] = NULL;
}
free(wrapperData->outputFilterActionLists);
wrapperData->outputFilterActionLists = NULL;
}
/* Individual messages are references to property values and are not malloced. */
free(wrapperData->outputFilterMessages);
wrapperData->outputFilterMessages = NULL;
free(wrapperData->outputFilterAllowWildFlags);
wrapperData->outputFilterAllowWildFlags = NULL;
free(wrapperData->outputFilterMinLens);
wrapperData->outputFilterMinLens = NULL;
}
wrapperData->outputFilterCount = 0;
if (getStringProperties(properties, TEXT("wrapper.filter.trigger."), TEXT(""), wrapperData->ignoreSequenceGaps, FALSE, &propertyNames, &propertyValues, &propertyIndices)) {
/* Failed */
return TRUE;
}
/* Loop over the properties and count how many triggers there are. */
i = 0;
while (propertyNames[i]) {
wrapperData->outputFilterCount++;
i++;
}
#if defined(MACOSX)
wrapperData->outputFilterCount++;
i++;
#endif
/* Now that a count is known, allocate memory to hold the filters and actions and load them in. */
if (wrapperData->outputFilterCount > 0) {
wrapperData->outputFilters = malloc(sizeof(TCHAR *) * wrapperData->outputFilterCount);
if (!wrapperData->outputFilters) {
outOfMemory(TEXT("LC"), 1);
return TRUE;
}
memset(wrapperData->outputFilters, 0, sizeof(TCHAR *) * wrapperData->outputFilterCount);
wrapperData->outputFilterActionLists = malloc(sizeof(int*) * wrapperData->outputFilterCount);
if (!wrapperData->outputFilterActionLists) {
outOfMemory(TEXT("LC"), 2);
return TRUE;
}
memset(wrapperData->outputFilterActionLists, 0, sizeof(int*) * wrapperData->outputFilterCount);
wrapperData->outputFilterMessages = malloc(sizeof(TCHAR *) * wrapperData->outputFilterCount);
if (!wrapperData->outputFilterMessages) {
outOfMemory(TEXT("LC"), 3);
return TRUE;
}
wrapperData->outputFilterAllowWildFlags = malloc(sizeof(int) * wrapperData->outputFilterCount);
if (!wrapperData->outputFilterAllowWildFlags) {
outOfMemory(TEXT("LC"), 4);
return TRUE;
}
memset(wrapperData->outputFilterAllowWildFlags, 0, sizeof(int) * wrapperData->outputFilterCount);
wrapperData->outputFilterMinLens = malloc(sizeof(size_t) * wrapperData->outputFilterCount);
if (!wrapperData->outputFilterMinLens) {
outOfMemory(TEXT("LC"), 5);
return TRUE;
}
memset(wrapperData->outputFilterMinLens, 0, sizeof(size_t) * wrapperData->outputFilterCount);
i = 0;
while (propertyNames[i]) {
prop = propertyValues[i];
wrapperData->outputFilters[i] = malloc(sizeof(TCHAR) * (_tcslen(prop) + 1));
if (!wrapperData->outputFilters[i]) {
outOfMemory(TEXT("LC"), 3);
return TRUE;
}
_tcsncpy(wrapperData->outputFilters[i], prop, _tcslen(prop) + 1);
/* Get the action */
_sntprintf(propName, 256, TEXT("wrapper.filter.action.%lu"), propertyIndices[i]);
prop = getStringProperty(properties, propName, TEXT("RESTART"));
wrapperData->outputFilterActionLists[i] = wrapperGetActionListForNames(prop, propName);
/* Get the message */
_sntprintf(propName, 256, TEXT("wrapper.filter.message.%lu"), propertyIndices[i]);
prop = getStringProperty(properties, propName, NULL);
wrapperData->outputFilterMessages[i] = (TCHAR *)prop;
/* Get the wildcard flags. */
_sntprintf(propName, 256, TEXT("wrapper.filter.allow_wildcards.%lu"), propertyIndices[i]);
wrapperData->outputFilterAllowWildFlags[i] = getBooleanProperty(properties, propName, FALSE);
if (wrapperData->outputFilterAllowWildFlags[i]) {
/* Calculate the minimum text length. */
wrapperData->outputFilterMinLens[i] = wrapperGetMinimumTextLengthForPattern(wrapperData->outputFilters[i]);
}
#ifdef _DEBUG
_tprintf(TEXT("filter #%lu, actions=("), propertyIndices[i]);
if (wrapperData->outputFilterActionLists[i]) {
j = 0;
while (wrapperData->outputFilterActionLists[i][j]) {
if (j > 0) {
_tprintf(TEXT(","));
}
_tprintf(TEXT("%d"), wrapperData->outputFilterActionLists[i][j]);
j++;
}
}
_tprintf(TEXT("), filter='%s'\n"), wrapperData->outputFilters[i]);
#endif
i++;
}
#if defined(MACOSX)
wrapperData->outputFilters[i] = malloc(sizeof(TCHAR) * (_tcslen(TRIGGER_ADVICE_NIL_SERVER) + 1));
if (!wrapperData->outputFilters[i]) {
outOfMemory(TEXT("LC"), 4);
return TRUE;
}
_tcsncpy(wrapperData->outputFilters[i], TRIGGER_ADVICE_NIL_SERVER, _tcslen(TRIGGER_ADVICE_NIL_SERVER) + 1);
wrapperData->outputFilterActionLists[i] = malloc(sizeof(int) * 2);
if (!wrapperData->outputFilters[i]) {
outOfMemory(TEXT("LC"), 5);
return TRUE;
}
wrapperData->outputFilterActionLists[i][0] = ACTION_ADVICE_NIL_SERVER;
wrapperData->outputFilterActionLists[i][1] = ACTION_LIST_END;
wrapperData->outputFilterMessages[i] = NULL;
wrapperData->outputFilterAllowWildFlags[i] = FALSE;
wrapperData->outputFilterMinLens[i] = 0;
i++;
#endif
}
freeStringProperties(propertyNames, propertyValues, propertyIndices);
return FALSE;
}
int getBackendTypeForName(const TCHAR *typeName) {
if (strcmpIgnoreCase(typeName, TEXT("SOCKET")) == 0) {
return WRAPPER_BACKEND_TYPE_SOCKET;
} else if (strcmpIgnoreCase(typeName, TEXT("PIPE")) == 0) {
return WRAPPER_BACKEND_TYPE_PIPE;
} else {
return WRAPPER_BACKEND_TYPE_UNKNOWN;
}
}
/**
* Return FALSE if successful, TRUE if there were problems.
*/
int loadConfiguration() {
TCHAR propName[256];
const TCHAR* val;
int startupDelay;
wrapperLoadLoggingProperties(FALSE);
/* Decide on the backend type to use. */
wrapperData->backendType = getBackendTypeForName(getStringProperty(properties, TEXT("wrapper.backend.type"), TEXT("SOCKET")));
if (wrapperData->backendType == WRAPPER_BACKEND_TYPE_UNKNOWN) {
wrapperData->backendType = WRAPPER_BACKEND_TYPE_SOCKET;
}
/* Decide whether the classpath should be passed via the environment. */
wrapperData->environmentClasspath = getBooleanProperty(properties, TEXT("wrapper.java.classpath.use_environment"), FALSE);
/* Decide how sequence gaps should be handled before any other properties are loaded. */
wrapperData->ignoreSequenceGaps = getBooleanProperty(properties, TEXT("wrapper.ignore_sequence_gaps"), FALSE);
/* Make sure that the configured log file directory is accessible. */
checkLogfileDir();
/* To make configuration reloading work correctly with changes to the log file,
* it needs to be closed here. */
closeLogfile();
/* Maintain the logger just in case we wrote any queued errors. */
maintainLogger();
/* Because the first call could cause errors as well, do it again to clear them out.
* This is only a one-time thing on startup as we test the new logfile configuration. */
maintainLogger();
/* Initialize some values not loaded */
wrapperData->exitCode = 0;
updateStringValue(&wrapperData->portAddress, getStringProperty(properties, TEXT("wrapper.port.address"), NULL));
/* Get the port. The int will wrap within the 0-65535 valid range, so no need to test the value. */
wrapperData->port = getIntProperty(properties, TEXT("wrapper.port"), 0);
wrapperData->portMin = getIntProperty(properties, TEXT("wrapper.port.min"), 32000);
if ((wrapperData->portMin < 1) || (wrapperData->portMin > 65535)) {
wrapperData->portMin = 32000;
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_WARN,
TEXT("%s must be in the range %d to %d. Changing to %d."), TEXT("wrapper.port.min"), 1, 65535, wrapperData->portMin);
}
wrapperData->portMax = getIntProperty(properties, TEXT("wrapper.port.max"), 32999);
if ((wrapperData->portMax < 1) || (wrapperData->portMax > 65535)) {
wrapperData->portMax = __min(wrapperData->portMin + 999, 65535);
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_WARN,
TEXT("%s must be in the range %d to %d. Changing to %d."), TEXT("wrapper.port.max"), 1, 65535, wrapperData->portMax);
} else if (wrapperData->portMax < wrapperData->portMin) {
wrapperData->portMax = __min(wrapperData->portMin + 999, 65535);
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_WARN,
TEXT("%s must be greater than or equal to %s. Changing to %d."), TEXT("wrapper.port.max"), TEXT("wrapper.port.min"), wrapperData->portMax);
}
/* Get the port for the JVM side of the socket. */
wrapperData->jvmPort = getIntProperty(properties, TEXT("wrapper.jvm.port"), -1);
if (wrapperData->jvmPort > 0) {
if (wrapperData->jvmPort == wrapperData->port) {
wrapperData->jvmPort = -1;
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_WARN,
TEXT("wrapper.jvm.port must not equal wrapper.port. Changing to the default."));
}
}
wrapperData->jvmPortMin = getIntProperty(properties, TEXT("wrapper.jvm.port.min"), 31000);
if ((wrapperData->jvmPortMin < 1) || (wrapperData->jvmPortMin > 65535)) {
wrapperData->jvmPortMin = 31000;
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_WARN,
TEXT("%s must be in the range %d to %d. Changing to %d."), TEXT("wrapper.jvm.port.min"), 1, 65535, wrapperData->jvmPortMin);
}
wrapperData->jvmPortMax = getIntProperty(properties, TEXT("wrapper.jvm.port.max"), 31999);
if ((wrapperData->jvmPortMax < 1) || (wrapperData->jvmPortMax > 65535)) {
wrapperData->jvmPortMax = __min(wrapperData->jvmPortMin + 999, 65535);
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_WARN,
TEXT("%s must be in the range %d to %d. Changing to %d."), TEXT("wrapper.jvm.port.max"), 1, 65535, wrapperData->jvmPortMax);
} else if (wrapperData->jvmPortMax < wrapperData->jvmPortMin) {
wrapperData->jvmPortMax = __min(wrapperData->jvmPortMin + 999, 65535);
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_WARN,
TEXT("%s must be greater than or equal to %s. Changing to %d."), TEXT("wrapper.jvm.port.max"), TEXT("wrapper.jvm.port.min"), wrapperData->jvmPortMax);
}
wrapperData->printJVMVersion = getBooleanProperty(properties, TEXT("wrapper.java.version.output"), FALSE);
/* Get the wrapper command log level. */
wrapperData->commandLogLevel = getLogLevelForName(
getStringProperty(properties, TEXT("wrapper.java.command.loglevel"), TEXT("DEBUG")));
/* Should we detach the JVM on startup. */
if (wrapperData->isConsole) {
wrapperData->detachStarted = getBooleanProperty(properties, TEXT("wrapper.jvm_detach_started"), FALSE);
}
/* Get the adviser status */
wrapperData->isAdviserEnabled = getBooleanProperty(properties, TEXT("wrapper.adviser"), TRUE);
/* The adviser is always enabled if debug is enabled. */
if (wrapperData->isDebugging) {
wrapperData->isAdviserEnabled = TRUE;
}
/* Get the use system time flag. */
if (!wrapperData->configured) {
wrapperData->useSystemTime = getBooleanProperty(properties, TEXT("wrapper.use_system_time"), FALSE);
}
if (!wrapperData->configured) {
wrapperData->logBufferGrowth = getBooleanProperty(properties, TEXT("wrapper.log_buffer_growth"), FALSE);
setLogBufferGrowth(wrapperData->logBufferGrowth);
}
#ifdef WIN32
/* Get the use javaio buffer size. */
if (!wrapperData->configured) {
wrapperData->javaIOBufferSize = getIntProperty(properties, TEXT("wrapper.javaio.buffer_size"), WRAPPER_JAVAIO_BUFFER_SIZE_DEFAULT);
if (wrapperData->javaIOBufferSize == WRAPPER_JAVAIO_BUFFER_SIZE_SYSTEM_DEFAULT) {
/* Ok. System default buffer size. */
} else if (wrapperData->javaIOBufferSize < WRAPPER_JAVAIO_BUFFER_SIZE_MIN) {
wrapperData->javaIOBufferSize = WRAPPER_JAVAIO_BUFFER_SIZE_MIN;
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_WARN,
TEXT("%s must be in the range %d to %d or %d. Changing to %d."), TEXT("wrapper.javaio.buffer_size"), WRAPPER_JAVAIO_BUFFER_SIZE_MIN, WRAPPER_JAVAIO_BUFFER_SIZE_MAX, WRAPPER_JAVAIO_BUFFER_SIZE_SYSTEM_DEFAULT, wrapperData->javaIOBufferSize);
} else if (wrapperData->javaIOBufferSize > WRAPPER_JAVAIO_BUFFER_SIZE_MAX) {
wrapperData->javaIOBufferSize = WRAPPER_JAVAIO_BUFFER_SIZE_MAX;
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_WARN,
TEXT("%s must be in the range %d to %d or %d. Changing to %d."), TEXT("wrapper.javaio.buffer_size"), WRAPPER_JAVAIO_BUFFER_SIZE_MIN, WRAPPER_JAVAIO_BUFFER_SIZE_MAX, WRAPPER_JAVAIO_BUFFER_SIZE_SYSTEM_DEFAULT, wrapperData->javaIOBufferSize);
}
}
#endif
/* Get the use javaio thread flag. */
if (!wrapperData->configured) {
wrapperData->useJavaIOThread = getBooleanProperty(properties, TEXT("wrapper.javaio.use_thread"), getBooleanProperty(properties, TEXT("wrapper.use_javaio_thread"), FALSE));
}
/* Decide whether or not a mutex should be used to protect the tick timer. */
if (!wrapperData->configured) {
wrapperData->useTickMutex = getBooleanProperty(properties, TEXT("wrapper.use_tick_mutex"), FALSE);
}
/* Get the timer thresholds. Properties are in seconds, but internally we use ticks. */
wrapperData->timerFastThreshold = getIntProperty(properties, TEXT("wrapper.timer_fast_threshold"), WRAPPER_TIMER_FAST_THRESHOLD * WRAPPER_TICK_MS / 1000) * 1000 / WRAPPER_TICK_MS;
wrapperData->timerSlowThreshold = getIntProperty(properties, TEXT("wrapper.timer_slow_threshold"), WRAPPER_TIMER_SLOW_THRESHOLD * WRAPPER_TICK_MS / 1000) * 1000 / WRAPPER_TICK_MS;
/* Load the name of the native library to be loaded. */
wrapperData->nativeLibrary = getStringProperty(properties, TEXT("wrapper.native_library"), TEXT("wrapper"));
/* Get the append PATH to library path flag. */
wrapperData->libraryPathAppendPath = getBooleanProperty(properties, TEXT("wrapper.java.library.path.append_system_path"), FALSE);
/* Get the state output status. */
wrapperData->isStateOutputEnabled = getBooleanProperty(properties, TEXT("wrapper.state_output"), FALSE);
/* Get the tick output status. */
wrapperData->isTickOutputEnabled = getBooleanProperty(properties, TEXT("wrapper.tick_output"), FALSE);
/* Get the loop debug output status. */
wrapperData->isLoopOutputEnabled = getBooleanProperty(properties, TEXT("wrapper.loop_output"), FALSE);
/* Get the sleep debug output status. */
wrapperData->isSleepOutputEnabled = getBooleanProperty(properties, TEXT("wrapper.sleep_output"), FALSE);
/* Get the memory output status. */
wrapperData->isMemoryOutputEnabled = getBooleanProperty(properties, TEXT("wrapper.memory_output"), FALSE);
wrapperData->memoryOutputInterval = getIntProperty(properties, TEXT("wrapper.memory_output.interval"), 1);
/* Get the cpu output status. */
wrapperData->isCPUOutputEnabled = getBooleanProperty(properties, TEXT("wrapper.cpu_output"), FALSE);
wrapperData->cpuOutputInterval = getIntProperty(properties, TEXT("wrapper.cpu_output.interval"), 1);
/* Get the pageFault output status. */
if (!wrapperData->configured) {
wrapperData->isPageFaultOutputEnabled = getBooleanProperty(properties, TEXT("wrapper.pagefault_output"), FALSE);
wrapperData->pageFaultOutputInterval = getIntProperty(properties, TEXT("wrapper.pagefault_output.interval"), 1);
}
/* Get the disable tests flag. */
wrapperData->isTestsDisabled = getBooleanProperty(properties, TEXT("wrapper.disable_tests"), FALSE);
/* Get the shutdown hook status */
wrapperData->isShutdownHookDisabled = getBooleanProperty(properties, TEXT("wrapper.disable_shutdown_hook"), FALSE);
/* Get the forced shutdown flag status. */
wrapperData->isForcedShutdownDisabled = getBooleanProperty(properties, TEXT("wrapper.disable_forced_shutdown"), FALSE);
/* Get the startup delay. */
startupDelay = getIntProperty(properties, TEXT("wrapper.startup.delay"), 0);
wrapperData->startupDelayConsole = getIntProperty(properties, TEXT("wrapper.startup.delay.console"), startupDelay);
if (wrapperData->startupDelayConsole < 0) {
wrapperData->startupDelayConsole = 0;
}
wrapperData->startupDelayService = getIntProperty(properties, TEXT("wrapper.startup.delay.service"), startupDelay);
if (wrapperData->startupDelayService < 0) {
wrapperData->startupDelayService = 0;
}
/* Get the restart delay. */
wrapperData->restartDelay = getIntProperty(properties, TEXT("wrapper.restart.delay"), 5);
if (wrapperData->restartDelay < 0) {
wrapperData->restartDelay = 0;
}
/* Get the flag which decides whether or not configuration should be reloaded on JVM restart. */
wrapperData->restartReloadConf = getBooleanProperty(properties, TEXT("wrapper.restart.reload_configuration"), FALSE);
/* Get the disable restart flag */
wrapperData->isRestartDisabled = getBooleanProperty(properties, TEXT("wrapper.disable_restarts"), FALSE);
wrapperData->isAutoRestartDisabled = getBooleanProperty(properties, TEXT("wrapper.disable_restarts.automatic"), wrapperData->isRestartDisabled);
/* Get the timeout settings */
wrapperData->cpuTimeout = getIntProperty(properties, TEXT("wrapper.cpu.timeout"), 10);
wrapperData->startupTimeout = getIntProperty(properties, TEXT("wrapper.startup.timeout"), 30);
wrapperData->pingTimeout = getIntProperty(properties, TEXT("wrapper.ping.timeout"), 30);
if (wrapperData->pingActionList) {
free(wrapperData->pingActionList);
}
wrapperData->pingActionList = wrapperGetActionListForNames(getStringProperty(properties, TEXT("wrapper.ping.timeout.action"), TEXT("RESTART")), TEXT("wrapper.ping.timeout.action"));
wrapperData->pingAlertThreshold = getIntProperty(properties, TEXT("wrapper.ping.alert.threshold"), __max(1, wrapperData->pingTimeout / 4));
wrapperData->pingAlertLogLevel = getLogLevelForName(getStringProperty(properties, TEXT("wrapper.ping.alert.loglevel"), TEXT("STATUS")));
wrapperData->pingInterval = getIntProperty(properties, TEXT("wrapper.ping.interval"), 5);
wrapperData->pingIntervalLogged = getIntProperty(properties, TEXT("wrapper.ping.interval.logged"), 1);
wrapperData->shutdownTimeout = getIntProperty(properties, TEXT("wrapper.shutdown.timeout"), 30);
wrapperData->jvmExitTimeout = getIntProperty(properties, TEXT("wrapper.jvm_exit.timeout"), 15);
wrapperData->jvmCleanupTimeout = getIntProperty(properties, TEXT("wrapper.jvm_cleanup.timeout"), 10);
wrapperData->jvmTerminateTimeout = getIntProperty(properties, TEXT("wrapper.jvm_terminate.timeout"), 10);
wrapperData->cpuTimeout = validateTimeout(TEXT("wrapper.cpu.timeout"), wrapperData->cpuTimeout);
wrapperData->startupTimeout = validateTimeout(TEXT("wrapper.startup.timeout"), wrapperData->startupTimeout);
wrapperData->pingTimeout = validateTimeout(TEXT("wrapper.ping.timeout"), wrapperData->pingTimeout);
wrapperData->shutdownTimeout = validateTimeout(TEXT("wrapper.shutdown.timeout"), wrapperData->shutdownTimeout);
wrapperData->jvmExitTimeout = validateTimeout(TEXT("wrapper.jvm_exit.timeout"), wrapperData->jvmExitTimeout);
wrapperData->jvmTerminateTimeout = validateTimeout(TEXT("wrapper.jvm_terminate.timeout"), wrapperData->jvmTerminateTimeout);
wrapperData->jvmCleanupTimeout = validateTimeout(TEXT("wrapper.jvm_cleanup.timeout"), wrapperData->jvmCleanupTimeout);
if (wrapperData->pingInterval < 1) {
wrapperData->pingInterval = 1;
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_WARN,
TEXT("The value of %s must be at least %d second(s). Changing to %d."), TEXT("wrapper.ping.interval"), 1, wrapperData->pingInterval);
} else if (wrapperData->pingInterval > 3600) {
wrapperData->pingInterval = 3600;
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_WARN,
TEXT("wrapper.ping.interval must be less than or equal to 1 hour (3600 seconds). Changing to 3600."));
}
if (wrapperData->pingIntervalLogged < 1) {
wrapperData->pingIntervalLogged = 1;
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_WARN,
TEXT("The value of %s must be at least %d second(s). Changing to %d."), TEXT("wrapper.ping.interval.logged"), 1, wrapperData->pingIntervalLogged);
} else if (wrapperData->pingIntervalLogged > 86400) {
wrapperData->pingIntervalLogged = 86400;
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_WARN,
TEXT("wrapper.ping.interval.logged must be less than or equal to 1 day (86400 seconds). Changing to 86400."));
}
if ((wrapperData->pingTimeout > 0) && (wrapperData->pingTimeout < wrapperData->pingInterval + 5)) {
wrapperData->pingTimeout = wrapperData->pingInterval + 5;
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_WARN,
TEXT("wrapper.ping.timeout must be at least 5 seconds longer than wrapper.ping.interval. Changing to %d."), wrapperData->pingTimeout);
}
if (wrapperData->pingAlertThreshold <= 0) {
/* Ping Alerts disabled. */
wrapperData->pingAlertThreshold = 0;
} else if ((wrapperData->pingTimeout > 0) && (wrapperData->pingAlertThreshold > wrapperData->pingTimeout)) {
wrapperData->pingAlertThreshold = wrapperData->pingTimeout;
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_WARN,
TEXT("wrapper.ping.alert.threshold must be less than or equal to the value of wrapper.ping.timeout (%d seconds). Changing to %d."),
wrapperData->pingInterval, wrapperData->pingTimeout);
}
if (wrapperData->cpuTimeout > 0) {
/* Make sure that the timeouts are all longer than the cpu timeout. */
if ((wrapperData->startupTimeout > 0) && (wrapperData->startupTimeout < wrapperData->cpuTimeout)) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_WARN,
TEXT("CPU timeout detection may not operate correctly during startup because wrapper.cpu.timeout is not smaller than wrapper.startup.timeout."));
}
if ((wrapperData->pingTimeout > 0) && (wrapperData->pingTimeout < wrapperData->cpuTimeout)) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_WARN,
TEXT("CPU timeout detection may not operate correctly because wrapper.cpu.timeout is not smaller than wrapper.ping.timeout."));
}
if ((wrapperData->shutdownTimeout > 0) && (wrapperData->shutdownTimeout < wrapperData->cpuTimeout)) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_WARN,
TEXT("CPU timeout detection may not operate correctly during shutdown because wrapper.cpu.timeout is not smaller than wrapper.shutdown.timeout."));
}
/* jvmExit timeout can be shorter than the cpu timeout. */
}
/* Load properties controlling the number times the JVM can be restarted. */
wrapperData->maxFailedInvocations = getIntProperty(properties, TEXT("wrapper.max_failed_invocations"), 5);
wrapperData->successfulInvocationTime = getIntProperty(properties, TEXT("wrapper.successful_invocation_time"), 300);
if (wrapperData->maxFailedInvocations < 1) {
wrapperData->maxFailedInvocations = 1;
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_ERROR,
TEXT("The value of %s must be at least %d second(s). Changing to %d."), TEXT("wrapper.max_failed_invocations"), 1, wrapperData->maxFailedInvocations);
}
/* TRUE if the JVM should be asked to dump its state when it fails to halt on request. */
wrapperData->requestThreadDumpOnFailedJVMExit = getBooleanProperty(properties, TEXT("wrapper.request_thread_dump_on_failed_jvm_exit"), FALSE);
wrapperData->requestThreadDumpOnFailedJVMExitDelay = getIntProperty(properties, TEXT("wrapper.request_thread_dump_on_failed_jvm_exit.delay"), 5);
if (wrapperData->requestThreadDumpOnFailedJVMExitDelay < 1) {
wrapperData->requestThreadDumpOnFailedJVMExitDelay = 1;
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_ERROR,
TEXT("The value of %s must be at least %d second(s). Changing to %d."), TEXT("wrapper.request_thread_dump_on_failed_jvm_exit.delay"), 1, wrapperData->requestThreadDumpOnFailedJVMExitDelay);
}
/* Load the output filters. */
if (loadConfigurationTriggers()) {
return TRUE;
}
/** Get the pid files if any. May be NULL */
if (!wrapperData->configured) {
updateStringValue(&wrapperData->pidFilename, getFileSafeStringProperty(properties, TEXT("wrapper.pidfile"), NULL));
correctWindowsPath(wrapperData->pidFilename);
}
wrapperData->pidFileStrict = getBooleanProperty(properties, TEXT("wrapper.pidfile.strict"), FALSE);
updateStringValue(&wrapperData->javaPidFilename, getFileSafeStringProperty(properties, TEXT("wrapper.java.pidfile"), NULL));
correctWindowsPath(wrapperData->javaPidFilename);
/** Get the lock file if any. May be NULL */
if (!wrapperData->configured) {
updateStringValue(&wrapperData->lockFilename, getFileSafeStringProperty(properties, TEXT("wrapper.lockfile"), NULL));
correctWindowsPath(wrapperData->lockFilename);
}
/** Get the java id file. May be NULL */
updateStringValue(&wrapperData->javaIdFilename, getFileSafeStringProperty(properties, TEXT("wrapper.java.idfile"), NULL));
correctWindowsPath(wrapperData->javaIdFilename);
/** Get the status files if any. May be NULL */
if (!wrapperData->configured) {
updateStringValue(&wrapperData->statusFilename, getFileSafeStringProperty(properties, TEXT("wrapper.statusfile"), NULL));
correctWindowsPath(wrapperData->statusFilename);
}
updateStringValue(&wrapperData->javaStatusFilename, getFileSafeStringProperty(properties, TEXT("wrapper.java.statusfile"), NULL));
correctWindowsPath(wrapperData->javaStatusFilename);
/** Get the command file if any. May be NULL */
updateStringValue(&wrapperData->commandFilename, getFileSafeStringProperty(properties, TEXT("wrapper.commandfile"), NULL));
correctWindowsPath(wrapperData->commandFilename);
wrapperData->commandFileTests = getBooleanProperty(properties, TEXT("wrapper.commandfile.enable_tests"), FALSE);
/** Get the interval at which the command file will be polled. */
wrapperData->commandPollInterval = propIntMin(propIntMax(getIntProperty(properties, TEXT("wrapper.command.poll_interval"), 5), 1), 3600);
/** Get the anchor file if any. May be NULL */
if (!wrapperData->configured) {
updateStringValue(&wrapperData->anchorFilename, getFileSafeStringProperty(properties, TEXT("wrapper.anchorfile"), NULL));
correctWindowsPath(wrapperData->anchorFilename);
}
/** Get the interval at which the anchor file will be polled. */
wrapperData->anchorPollInterval = propIntMin(propIntMax(getIntProperty(properties, TEXT("wrapper.anchor.poll_interval"), 5), 1), 3600);
/** Flag controlling whether or not system signals should be ignored. */
val = getStringProperty(properties, TEXT("wrapper.ignore_signals"), TEXT("FALSE"));
if ( ( strcmpIgnoreCase( val, TEXT("TRUE") ) == 0 ) || ( strcmpIgnoreCase( val, TEXT("BOTH") ) == 0 ) ) {
wrapperData->ignoreSignals = WRAPPER_IGNORE_SIGNALS_WRAPPER + WRAPPER_IGNORE_SIGNALS_JAVA;
} else if ( strcmpIgnoreCase( val, TEXT("WRAPPER") ) == 0 ) {
wrapperData->ignoreSignals = WRAPPER_IGNORE_SIGNALS_WRAPPER;
} else if ( strcmpIgnoreCase( val, TEXT("JAVA") ) == 0 ) {
wrapperData->ignoreSignals = WRAPPER_IGNORE_SIGNALS_JAVA;
} else {
wrapperData->ignoreSignals = 0;
}
/* Obtain the Console Title. */
_sntprintf(propName, 256, TEXT("wrapper.console.title.%s"), wrapperOS);
updateStringValue(&wrapperData->consoleTitle, getStringProperty(properties, propName, getStringProperty(properties, TEXT("wrapper.console.title"), NULL)));
/* Load the service name (Used to be windows specific so use those properties if set.) */
updateStringValue(&wrapperData->serviceName, getStringProperty(properties, TEXT("wrapper.name"), getStringProperty(properties, TEXT("wrapper.ntservice.name"), TEXT("wrapper"))));
/* Load the service display name (Used to be windows specific so use those properties if set.) */
updateStringValue(&wrapperData->serviceDisplayName, getStringProperty(properties, TEXT("wrapper.displayname"), getStringProperty(properties, TEXT("wrapper.ntservice.displayname"), wrapperData->serviceName)));
/* Load the service description, default to display name (Used to be windows specific so use those properties if set.) */
updateStringValue(&wrapperData->serviceDescription, getStringProperty(properties, TEXT("wrapper.description"), getStringProperty(properties, TEXT("wrapper.ntservice.description"), wrapperData->serviceDisplayName)));
/* Pausable */
wrapperData->pausable = getBooleanProperty(properties, TEXT("wrapper.pausable"), getBooleanProperty(properties, TEXT("wrapper.ntservice.pausable"), FALSE));
wrapperData->pausableStopJVM = getBooleanProperty(properties, TEXT("wrapper.pausable.stop_jvm"), getBooleanProperty(properties, TEXT("wrapper.ntservice.pausable.stop_jvm"), TRUE));
if (!wrapperData->configured) {
wrapperData->initiallyPaused = getBooleanProperty(properties, TEXT("wrapper.pause_on_startup"), FALSE);
}
#ifdef WIN32
wrapperData->ignoreUserLogoffs = getBooleanProperty(properties, TEXT("wrapper.ignore_user_logoffs"), FALSE);
/* Configure the NT service information */
if (wrapperBuildNTServiceInfo()) {
return TRUE;
}
if (wrapperData->generateConsole) {
if (!wrapperData->ntAllocConsole) {
/* We need to allocate a console in order for the thread dumps to work
* when running as a service. But the user did not request that a
* console be visible so we want to hide it. */
wrapperData->ntAllocConsole = TRUE;
wrapperData->ntHideWrapperConsole = TRUE;
}
}
#ifdef WIN32
if ((!strcmpIgnoreCase(wrapperData->argCommand, TEXT("s")) || !strcmpIgnoreCase(wrapperData->argCommand, TEXT("-service")))
&& (!wrapperData->ntAllocConsole || wrapperData->ntHideWrapperConsole)) {
#else
if (!wrapperData->isConsole) {
#endif
/* The console is not visible, so we shouldn't waste time logging to it. */
setConsoleLogLevelInt(LEVEL_NONE);
}
#else /* UNIX */
/* Configure the Unix daemon information */
if (wrapperBuildUnixDaemonInfo()) {
return TRUE;
}
#endif
if (_tcscmp(wrapperVersionRoot, getStringProperty(properties, TEXT("wrapper.script.version"), wrapperVersionRoot)) != 0) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_WARN,
TEXT("The version of the script (%s) doesn't match the version of this Wrapper (%s). This might cause some problems"),
getStringProperty(properties, TEXT("wrapper.script.version"), wrapperVersionRoot), wrapperVersionRoot);
}
wrapperData->configured = TRUE;
return FALSE;
}
/**
* Requests a lock on the tick mutex.
*
* @return TRUE if there were any problems, FALSE if successful.
*/
int wrapperLockTickMutex() {
#ifdef WIN32
switch (WaitForSingleObject(tickMutexHandle, INFINITE)) {
case WAIT_ABANDONED:
_tprintf(TEXT("Tick was abandoned.\n"));
return TRUE;
case WAIT_FAILED:
_tprintf(TEXT("Tick wait failed.\n"));
return TRUE;
case WAIT_TIMEOUT:
_tprintf(TEXT("Tick wait timed out.\n"));
return TRUE;
default:
/* Ok */
break;
}
#else
if (pthread_mutex_lock(&tickMutex)) {
_tprintf(TEXT("Failed to lock the Tick mutex. %s\n"), getLastErrorText());
return TRUE;
}
#endif
return FALSE;
}
/**
* Releases a lock on the tick mutex.
*
* @return TRUE if there were any problems, FALSE if successful.
*/
int wrapperReleaseTickMutex() {
#ifdef WIN32
if (!ReleaseMutex(tickMutexHandle)) {
_tprintf(TEXT("Failed to release tick mutex. %s\n"), getLastErrorText());
return TRUE;
}
#else
if (pthread_mutex_unlock(&tickMutex)) {
_tprintf(TEXT("Failed to unlock the tick mutex. %s\n"), getLastErrorText());
return TRUE;
}
#endif
return FALSE;
}
/**
* Calculates a tick count using the system time.
*
* We normally need 64 bits to do this calculation. Play some games to get
* the correct values with 32 bit variables.
*/
TICKS wrapperGetSystemTicks() {
struct timeb timeBuffer;
DWORD high, low;
TICKS sum;
#ifdef _DEBUG
TICKS assertSum;
#endif
wrapperGetCurrentTime(&timeBuffer);
/* Break in half. */
high = (DWORD)(timeBuffer.time >> 16) & 0xffff;
low = (DWORD)(timeBuffer.time & 0xffff);
/* Work on each half. */
high = high * 1000 / WRAPPER_TICK_MS;
low = (low * 1000 + timeBuffer.millitm) / WRAPPER_TICK_MS;
/* Now combine them in such a way that the correct bits are truncated. */
high = high + ((low >> 16) & 0xffff);
sum = (TICKS)(((high & 0xffff) << 16) + (low & 0xffff));
/* Check the result. */
#ifdef _DEBUG
#ifdef WIN32
assertSum = (TICKS)((timeBuffer.time * 1000UI64 + timeBuffer.millitm) / WRAPPER_TICK_MS);
#else
/* This will produce the following warning on some compilers:
* warning: ANSI C forbids long long integer constants
* Is there another way to do this? */
assertSum = (TICKS)((timeBuffer.time * 1000ULL + timeBuffer.millitm) / WRAPPER_TICK_MS);
#endif
if (assertSum != sum) {
_tprintf(TEXT("wrapperGetSystemTicks() resulted in %08x rather than %08x\n"), sum, assertSum);
}
#endif
return sum;
}
/**
* Returns difference in seconds between the start and end ticks. This function
* handles cases where the tick counter has wrapped between when the start
* and end tick counts were taken. See the wrapperGetTicks() function.
*
* This can be done safely in 32 bits
*/
int wrapperGetTickAgeSeconds(TICKS start, TICKS end) {
/*
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT(" wrapperGetTickAgeSeconds(%08x, %08x) -> %08x"), start, end, (int)((end - start) * WRAPPER_TICK_MS) / 1000);
*/
/* Simply subtracting the values will always work even if end has wrapped
* due to overflow.
* 0x00000001 - 0xffffffff = 0x00000002 = 2
* 0xffffffff - 0x00000001 = 0xfffffffe = -2
*/
return (int)((end - start) * WRAPPER_TICK_MS) / 1000;
}
/**
* Returns difference in ticks between the start and end ticks. This function
* handles cases where the tick counter has wrapped between when the start
* and end tick counts were taken. See the wrapperGetTicks() function.
*
* This can be done safely in 32 bits
*/
int wrapperGetTickAgeTicks(TICKS start, TICKS end) {
/*
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT(" wrapperGetTickAgeSeconds(%08x, %08x) -> %08x"), start, end, (int)(end - start));
*/
/* Simply subtracting the values will always work even if end has wrapped
* due to overflow.
* 0x00000001 - 0xffffffff = 0x00000002 = 2
* 0xffffffff - 0x00000001 = 0xfffffffe = -2
*/
return (int)(end - start);
}
/**
* Returns TRUE if the specified tick timeout has expired relative to the
* specified tick count.
*/
int wrapperTickExpired(TICKS nowTicks, TICKS timeoutTicks) {
/* Convert to a signed value. */
int age = nowTicks - timeoutTicks;
if (age >= 0) {
return TRUE;
} else {
return FALSE;
}
}
/**
* Returns a tick count that is the specified number of seconds later than
* the base tick count.
*
* This calculation will work as long as the number of seconds is not large
* enough to require more than 32 bits when multiplied by 1000.
*/
TICKS wrapperAddToTicks(TICKS start, int seconds) {
/*
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT(" wrapperAddToTicks(%08x, %08x) -> %08x"), start, seconds, start + (seconds * 1000 / WRAPPER_TICK_MS));
*/
return start + (seconds * 1000 / WRAPPER_TICK_MS);
}
/**
* Do some sanity checks on the tick timer math.
*/
int wrapperTickAssertions() {
int result = FALSE;
TICKS ticks1, ticks2, ticksR, ticksE;
int value1, valueR, valueE;
/** wrapperGetTickAgeTicks test. */
ticks1 = 0xfffffffe;
ticks2 = 0xffffffff;
valueE = 1;
valueR = wrapperGetTickAgeTicks(ticks1, ticks2);
if (valueR != valueE) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_FATAL, TEXT("Assert Failed: wrapperGetTickAgeTicks(%08x, %08x) == %0d != %0d"), ticks1, ticks2, valueR, valueE);
result = TRUE;
}
ticks1 = 0xffffffff;
ticks2 = 0xfffffffe;
valueE = -1;
valueR = wrapperGetTickAgeTicks(ticks1, ticks2);
if (valueR != valueE) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_FATAL, TEXT("Assert Failed: wrapperGetTickAgeTicks(%08x, %08x) == %0d != %0d"), ticks1, ticks2, valueR, valueE);
result = TRUE;
}
ticks1 = 0xffffffff;
ticks2 = 0x00000000;
valueE = 1;
valueR = wrapperGetTickAgeTicks(ticks1, ticks2);
if (valueR != valueE) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_FATAL, TEXT("Assert Failed: wrapperGetTickAgeTicks(%08x, %08x) == %0d != %0d"), ticks1, ticks2, valueR, valueE);
result = TRUE;
}
ticks1 = 0x00000000;
ticks2 = 0xffffffff;
valueE = -1;
valueR = wrapperGetTickAgeTicks(ticks1, ticks2);
if (valueR != valueE) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_FATAL, TEXT("Assert Failed: wrapperGetTickAgeTicks(%08x, %08x) == %0d != %0d"), ticks1, ticks2, valueR, valueE);
result = TRUE;
}
/** wrapperGetTickAgeSeconds test. */
ticks1 = 0xfffffff0;
ticks2 = 0xffffffff;
valueE = 1;
valueR = wrapperGetTickAgeSeconds(ticks1, ticks2);
if (valueR != valueE) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_FATAL, TEXT("Assert Failed: wrapperGetTickAgeSeconds(%08x, %08x) == %0d != %0d"), ticks1, ticks2, valueR, valueE);
result = TRUE;
}
ticks1 = 0xffffffff;
ticks2 = 0x0000000f;
valueE = 1;
valueR = wrapperGetTickAgeSeconds(ticks1, ticks2);
if (valueR != valueE) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_FATAL, TEXT("Assert Failed: wrapperGetTickAgeSeconds(%08x, %08x) == %0d != %0d"), ticks1, ticks2, valueR, valueE);
result = TRUE;
}
ticks1 = 0x0000000f;
ticks2 = 0xffffffff;
valueE = -1;
valueR = wrapperGetTickAgeSeconds(ticks1, ticks2);
if (valueR != valueE) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_FATAL, TEXT("Assert Failed: wrapperGetTickAgeSeconds(%08x, %08x) == %0d != %0d"), ticks1, ticks2, valueR, valueE);
result = TRUE;
}
/** wrapperTickExpired test. */
ticks1 = 0xfffffffe;
ticks2 = 0xffffffff;
valueE = FALSE;
valueR = wrapperTickExpired(ticks1, ticks2);
if (valueR != valueE) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_FATAL, TEXT("Assert Failed: wrapperTickExpired(%08x, %08x) == %0d != %0d"), ticks1, ticks2, valueR, valueE);
result = TRUE;
}
ticks1 = 0xffffffff;
ticks2 = 0xffffffff;
valueE = TRUE;
valueR = wrapperTickExpired(ticks1, ticks2);
if (valueR != valueE) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_FATAL, TEXT("Assert Failed: wrapperTickExpired(%08x, %08x) == %0d != %0d"), ticks1, ticks2, valueR, valueE);
result = TRUE;
}
ticks1 = 0xffffffff;
ticks2 = 0x00000001;
valueE = FALSE;
valueR = wrapperTickExpired(ticks1, ticks2);
if (valueR != valueE) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_FATAL, TEXT("Assert Failed: wrapperTickExpired(%08x, %08x) == %0d != %0d"), ticks1, ticks2, valueR, valueE);
result = TRUE;
}
ticks1 = 0x00000001;
ticks2 = 0xffffffff;
valueE = TRUE;
valueR = wrapperTickExpired(ticks1, ticks2);
if (valueR != valueE) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_FATAL, TEXT("Assert Failed: wrapperTickExpired(%08x, %08x) == %0d != %0d"), ticks1, ticks2, valueR, valueE);
result = TRUE;
}
/** wrapperAddToTicks test. */
ticks1 = 0xffffffff;
value1 = 1;
ticksE = 0x00000009;
ticksR = wrapperAddToTicks(ticks1, value1);
if (ticksR != ticksE) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_FATAL, TEXT("Assert Failed: wrapperAddToTicks(%08x, %d) == %08x != %08x"), ticks1, value1, ticksR, ticksE);
result = TRUE;
}
return result;
}
/**
* Sets the working directory of the Wrapper to the specified directory.
* The directory can be relative or absolute.
* If there are any problems then a non-zero value will be returned.
*
* @param dir Directory to change to.
* @param logErrors TRUE if errors should be logged.
*/
int wrapperSetWorkingDir(const TCHAR* dir, int logErrors) {
int showOutput = wrapperData->configured;
if (_tchdir(dir)) {
if ( logErrors )
{
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_FATAL,
TEXT("Unable to set working directory to: %s (%s)"), dir, getLastErrorText());
}
return TRUE;
}
/* This function is sometimes called before the configuration is loaded. */
#ifdef _DEBUG
showOutput = TRUE;
#endif
if (showOutput) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_DEBUG, TEXT("Working directory set to: %s"), dir);
}
/* Set a variable to the location of the binary. */
setEnv(TEXT("WRAPPER_WORKING_DIR"), dir, ENV_SOURCE_WRAPPER);
return FALSE;
}
/******************************************************************************
* Protocol callback functions
*****************************************************************************/
void wrapperLogSignaled(int logLevel, TCHAR *msg) {
/* */
if (wrapperData->isDebugging) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_DEBUG, TEXT("Got a log message from JVM: %s"), msg);
}
/* */
log_printf(wrapperData->jvmRestarts, logLevel, msg);
}
void wrapperKeyRegistered(TCHAR *key) {
/* Allow for a large integer + \0 */
TCHAR buffer[11];
if (wrapperData->isDebugging) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_DEBUG, TEXT("Got key from JVM: %s"), key);
}
switch (wrapperData->jState) {
case WRAPPER_JSTATE_LAUNCHING:
/* We now know that the Java side wrapper code has started and
* registered with a key. We still need to verify that it is
* the correct key however. */
if (_tcscmp(key, wrapperData->key) == 0) {
/* This is the correct key. */
/* We now know that the Java side wrapper code has started. */
wrapperSetJavaState(WRAPPER_JSTATE_LAUNCHED, 0, -1);
/* Send the low log level to the JVM so that it can control output via the log method. */
_sntprintf(buffer, 11, TEXT("%d"), getLowLogLevel());
wrapperProtocolFunction(WRAPPER_MSG_LOW_LOG_LEVEL, buffer);
/* Send the log file name. */
sendLogFileName();
/* Send the properties. */
sendProperties();
} else {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_ERROR, TEXT("Received a connection request with an incorrect key. Waiting for another connection."));
/* This was the wrong key. Send a response. */
wrapperProtocolFunction(WRAPPER_MSG_BADKEY, TEXT("Incorrect key. Connection rejected."));
/* Close the current connection. Assume that the real JVM
* is still out there trying to connect. So don't change
* the state. If for some reason, this was the correct
* JVM, but the key was wrong. then this state will time
* out and recover. */
wrapperProtocolClose();
}
break;
case WRAPPER_JSTATE_STOP:
/* We got a key registration. This means that the JVM thinks it was
* being launched but the Wrapper is trying to stop. This state
* will clean up correctly. */
break;
case WRAPPER_JSTATE_STOPPING:
/* We got a key registration. This means that the JVM thinks it was
* being launched but the Wrapper is trying to stop. Now that the
* connection to the JVM has been opened, tell it to stop cleanly. */
wrapperSetJavaState(WRAPPER_JSTATE_STOP, 0, -1);
break;
default:
/* We got a key registration that we were not expecting. Ignore it. */
break;
}
}
/**
* Called when a ping is first determined to be slower than the wrapper.ping.alert.threshold.
* This will happen before it has actually been responded to.
*/
void wrapperPingSlow() {
}
/**
* Called when a ping is responded to, but was slower than the wrapper.ping.alert.threshold.
*
* @param tickAge The number of seconds it took to respond.
*/
void wrapperPingRespondedSlow(int tickAge) {
log_printf(WRAPPER_SOURCE_WRAPPER, wrapperData->pingAlertLogLevel, TEXT("Pinging the JVM took %d seconds to respond."), tickAge);
}
/**
* Called when a ping response is received.
*
* @param pingSendTicks Time in ticks when the ping was originally sent.
* @param queueWarnings TRUE if warnings about the queue should be logged, FALSE if the ping response did not contain a time.
*/
void wrapperPingResponded(TICKS pingSendTicks, int queueWarnings) {
TICKS nowTicks;
int tickAge;
PPendingPing pendingPing;
int pingSearchDone;
#ifdef DEBUG_PING_QUEUE
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT(" PING QUEUE Ping Response (tick %08x)"), pingSendTicks);
#endif
/* We want to purge the ping from the PendingPing list. */
do {
pendingPing = wrapperData->firstPendingPing;
if (pendingPing != NULL) {
tickAge = wrapperGetTickAgeTicks(pingSendTicks, pendingPing->sentTicks);
#ifdef DEBUG_PING_QUEUE
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT(" PING QUEUE First Queued Ping (tick %08x, age %d)"), pendingPing->sentTicks, tickAge);
#endif
if (tickAge > 0) { /* pendingPing->sentTicks > pingSendTicks */
/* We received a ping response that is earlier than the one we were expecting.
* If the pendingPingQueue has overflown then we will stop writing to it. Don't long warning messages when in this state as they would be confusing and are expected.
* Leave this one in the queue for later. */
if (queueWarnings) {
if ((!wrapperData->pendingPingQueueOverflow) && (!wrapperData->pendingPingQueueOverflowEmptied)) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_ERROR, TEXT("Received an unexpected ping response, sent at tick %08x. First expected ping was sent at tick %08x."), pingSendTicks, pendingPing->sentTicks);
} else {
#ifdef DEBUG_PING_QUEUE
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT(" PING QUEUE Silently skipping unexpected ping response. (tick %08x) (First tick %08x)"), pingSendTicks, pendingPing->sentTicks);
#endif
}
}
pendingPing = NULL;
pingSearchDone = TRUE;
} else {
if (tickAge < 0) {
/* This PendingPing object was sent before the PING that we received. This means that we somehow lost a ping. */
if (queueWarnings) {
if ((!wrapperData->pendingPingQueueOverflow) && (!wrapperData->pendingPingQueueOverflowEmptied)) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_ERROR, TEXT("Lost a ping response, sent at tick %08x."), pendingPing->sentTicks);
} else {
#ifdef DEBUG_PING_QUEUE
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT(" PING QUEUE Silently skipping lost ping response. (tick %08x)"), pendingPing->sentTicks);
#endif
}
}
pingSearchDone = FALSE;
} else {
/* This PendingPing object is for this PING event. */
pingSearchDone = TRUE;
#ifdef DEBUG_PING_QUEUE
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT(" PING QUEUE Expected Ping Response. (tick %08x)"), pendingPing->sentTicks);
#endif
/* When the emptied flag is set, we know that we are recovering from an overflow.
* That flag is reset on the first expected PendingPing found in the queue. */
if (wrapperData->pendingPingQueueOverflowEmptied) {
wrapperData->pendingPingQueueOverflowEmptied = FALSE;
#ifdef DEBUG_PING_QUEUE
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT(" PING QUEUE Emptied Set flag reset."));
#endif
}
}
/* Detach the PendingPing from the queue. */
if (pendingPing->nextPendingPing != NULL) {
/* This was the first PendingPing of several in the queue. */
wrapperData->pendingPingCount--;
if (wrapperData->firstUnwarnedPendingPing == wrapperData->firstPendingPing) {
wrapperData->firstUnwarnedPendingPing = pendingPing->nextPendingPing;
}
wrapperData->firstPendingPing = pendingPing->nextPendingPing;
pendingPing->nextPendingPing = NULL;
#ifdef DEBUG_PING_QUEUE
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT("--- PING QUEUE Size: %d"), wrapperData->pendingPingCount);
#endif
} else {
/* This was the only PendingPing in the queue. */
wrapperData->pendingPingCount = 0;
wrapperData->firstUnwarnedPendingPing = NULL;
wrapperData->firstPendingPing = NULL;
wrapperData->lastPendingPing = NULL;
#ifdef DEBUG_PING_QUEUE
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT("--- PING QUEUE Empty.") );
#endif
if (wrapperData->pendingPingQueueOverflow) {
wrapperData->pendingPingQueueOverflowEmptied = TRUE;
wrapperData->pendingPingQueueOverflow = FALSE;
#ifdef DEBUG_PING_QUEUE
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT(" PING QUEUE Reset Overflow, Emptied Set.") );
#endif
}
}
/* Free up the pendingPing object. */
if (pendingPing != NULL) {
free(pendingPing);
pendingPing = NULL;
}
}
} else {
/* Got a ping response when the queue was empty. */
if (queueWarnings) {
if ((!wrapperData->pendingPingQueueOverflow) && (!wrapperData->pendingPingQueueOverflowEmptied)) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_ERROR, TEXT("Received an unexpected ping response, sent at tick %08x."), pingSendTicks);
} else {
#ifdef DEBUG_PING_QUEUE
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT(" PING QUEUE Silently skipping unexpected ping response. (tick %08x) (Empty)"), pingSendTicks);
#endif
}
}
pingSearchDone = TRUE;
}
} while (!pingSearchDone);
/* Depending on the current JVM state, do something. */
switch (wrapperData->jState) {
case WRAPPER_JSTATE_STARTED:
/* We got a response to a ping. */
nowTicks = wrapperGetTicks();
/* Figure out how long it took for us to get this ping response in seconds. */
tickAge = wrapperGetTickAgeSeconds(pingSendTicks, nowTicks);
/* If we took longer than the threshold then we want to log a message. */
if ((wrapperData->pingAlertThreshold > 0) && (tickAge >= wrapperData->pingAlertThreshold)) {
wrapperPingRespondedSlow(tickAge);
}
/* Allow 5 + more seconds before the JVM is considered to be dead. */
if (wrapperData->pingTimeout > 0) {
wrapperUpdateJavaStateTimeout(nowTicks, 5 + wrapperData->pingTimeout);
} else {
wrapperUpdateJavaStateTimeout(nowTicks, -1);
}
break;
default:
/* We got a ping response that we were not expecting. Ignore it. */
break;
}
}
void wrapperPingTimeoutResponded() {
wrapperProcessActionList(wrapperData->pingActionList, TEXT("JVM appears hung: Timed out waiting for signal from JVM."),
WRAPPER_ACTION_SOURCE_CODE_PING_TIMEOUT, TRUE, 1);
}
void wrapperStopRequested(int exitCode) {
if (wrapperData->isDebugging) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_DEBUG,
TEXT("JVM requested a shutdown. (%d)"), exitCode);
}
/* Get things stopping on this end. Ask the JVM to stop again in case the
* user code on the Java side is not written correctly. */
wrapperStopProcess(exitCode, FALSE);
}
void wrapperRestartRequested() {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT("JVM requested a restart."));
/* Make a note of the fact that we received this restart packet. */
wrapperData->restartPacketReceived = TRUE;
wrapperRestartProcess();
}
/**
* If the current state of the JVM is STOPPING then this message is used to
* extend the time that the wrapper will wait for a STOPPED message before
* giving up on the JVM and killing it.
*/
void wrapperStopPendingSignaled(int waitHint) {
if (wrapperData->isDebugging) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_DEBUG, TEXT("JVM signaled a stop pending with waitHint of %d millis."), waitHint);
}
if (wrapperData->jState == WRAPPER_JSTATE_STARTED) {
/* Change the state to STOPPING */
wrapperSetJavaState(WRAPPER_JSTATE_STOPPING, 0, -1);
/* Don't need to set the timeout here because it will be set below. */
}
if (wrapperData->jState == WRAPPER_JSTATE_STOPPING) {
if (waitHint < 0) {
waitHint = 0;
}
wrapperUpdateJavaStateTimeout(wrapperGetTicks(), (int)ceil(waitHint / 1000.0));
}
}
/**
* The wrapper received a signal from the JVM that it has completed the stop
* process. If the state of the JVM is STOPPING, then change the state to
* STOPPED. It is possible to get this request after the Wrapper has given up
* waiting for the JVM. In this case, the message is ignored.
*/
void wrapperStoppedSignaled() {
if (wrapperData->isDebugging) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_DEBUG, TEXT("JVM signaled that it was stopped."));
}
/* If the restart mode is already set and it is WRAPPER_RESTART_REQUESTED_AUTOMATIC but we
* have not yet received a RESTART packet, this means that state engine got confused because
* of an unexpected delay. The fact that the STOPPED packet arived but not the RESTART packet
* means that the application did not intend for the restart to take place.
* Reset the restart and let the Wrapper exit. */
if ((wrapperData->restartRequested == WRAPPER_RESTART_REQUESTED_AUTOMATIC) && (!wrapperData->restartPacketReceived)) {
/* If we get here it is because the Wrapper previously decided to do a restart to recover.
* That means that another message was already shown to the user. We want to show another
* message here so there is a record of why we don't restart. */
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT("Received Stopped packet late. Cancel automatic restart."));
wrapperData->restartRequested = WRAPPER_RESTART_REQUESTED_NO;
}
/* Make a note of the fact that we received this stopped packet. */
wrapperData->stoppedPacketReceived = TRUE;
if ((wrapperData->jState == WRAPPER_JSTATE_STARTING) ||
(wrapperData->jState == WRAPPER_JSTATE_STARTED) ||
(wrapperData->jState == WRAPPER_JSTATE_STOPPING)) {
/* The Java side of the wrapper signaled that it stopped
* allow 5 + jvmExitTimeout seconds for the JVM to exit. */
if (wrapperData->jvmExitTimeout > 0) {
wrapperSetJavaState(WRAPPER_JSTATE_STOPPED, wrapperGetTicks(), 5 + wrapperData->jvmExitTimeout);
} else {
wrapperSetJavaState(WRAPPER_JSTATE_STOPPED, 0, -1);
}
}
}
/**
* If the current state of the JVM is STARTING then this message is used to
* extend the time that the wrapper will wait for a STARTED message before
* giving up on the JVM and killing it.
*/
void wrapperStartPendingSignaled(int waitHint) {
if (wrapperData->isDebugging) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_DEBUG, TEXT("JVM signaled a start pending with waitHint of %d millis."), waitHint);
}
/* Only process the start pending signal if the JVM state is starting or
* stopping. Stopping are included because if the user hits CTRL-C while
* the application is starting, then the stop request will not be noticed
* until the application has completed its startup. */
if ((wrapperData->jState == WRAPPER_JSTATE_STARTING) ||
(wrapperData->jState == WRAPPER_JSTATE_STOPPING)) {
if (waitHint < 0) {
waitHint = 0;
}
wrapperUpdateJavaStateTimeout(wrapperGetTicks(), (int)ceil(waitHint / 1000.0));
}
}
/**
* The wrapper received a signal from the JVM that it has completed the startup
* process. If the state of the JVM is STARTING, then change the state to
* STARTED. It is possible to get this request after the Wrapper has given up
* waiting for the JVM. In this case, the message is ignored.
*/
void wrapperStartedSignaled() {
if (wrapperData->isDebugging) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_DEBUG, TEXT("JVM signaled that it was started."));
}
if (wrapperData->jState == WRAPPER_JSTATE_STARTING) {
/* We got the expected started packed. Now start pinging. Allow 5 + more seconds before the JVM
* is considered to be dead. */
if (wrapperData->pingTimeout > 0) {
wrapperSetJavaState(WRAPPER_JSTATE_STARTED, wrapperGetTicks(), 5 + wrapperData->pingTimeout);
} else {
wrapperSetJavaState(WRAPPER_JSTATE_STARTED, 0, -1);
}
/* Is the wrapper state STARTING? */
if (wrapperData->wState == WRAPPER_WSTATE_STARTING) {
wrapperSetWrapperState(WRAPPER_WSTATE_STARTED);
if (!wrapperData->isConsole) {
/* Tell the service manager that we started */
wrapperReportStatus(FALSE, WRAPPER_WSTATE_STARTED, 0, 0);
}
}
/* If we are configured to detach and shutdown when the JVM is started then start doing so. */
if (wrapperData->detachStarted) {
log_printf(WRAPPER_SOURCE_WRAPPER, LEVEL_STATUS, TEXT("JVM launched and detached. Wrapper Shutting down..."));
wrapperProtocolClose();
wrapperDetachJava();
wrapperStopProcess(0, FALSE);
}
} else if (wrapperData->jState == WRAPPER_JSTATE_STOP) {
/* This will happen if the Wrapper was asked to stop as the JVM is being launched. */
} else if (wrapperData->jState == WRAPPER_JSTATE_STOPPING) {
/* This will happen if the Wrapper was asked to stop as the JVM is being launched. */
wrapperSetJavaState(WRAPPER_JSTATE_STOP, 0, -1);
}
}
#ifdef CUNIT
static void subTestJavaAdditionalParamSuite(int stripQuote, TCHAR *config, TCHAR **strings, int strings_len, int isJVMParam) {
LoadParameterFileCallbackParam param;
int ret;
int i;
param.stripQuote = stripQuote;
param.strings = NULL;
param.index = 0;
param.isJVMParam = isJVMParam;
ret = loadParameterFileCallback((void *)(¶m), NULL, 0, config, FALSE);
CU_ASSERT_TRUE(ret);
CU_ASSERT(strings_len == param.index);
param.stripQuote = stripQuote;
param.strings = (TCHAR **)malloc(sizeof(TCHAR *) * strings_len);
param.index = 0;
param.isJVMParam = isJVMParam;
CU_ASSERT(param.strings != NULL);
ret = loadParameterFileCallback((void *)(¶m), NULL, 0, config, FALSE);
CU_ASSERT_TRUE(ret);
CU_ASSERT(strings_len == param.index);
for (i = 0; i < strings_len; i++) {
CU_ASSERT(_tcscmp(strings[i], param.strings[i]) == 0);
}
}
#define ARRAY_LENGTH(a) (sizeof(a) / sizeof(a[0]))
void testJavaAdditionalParamSuite(void) {
int stripQuote;
int i = 0;
int isJVM = TRUE;
for (i = 0; i < 2; i++) {
_tprintf(TEXT("%d round\n"), i);
if (i > 0) {
isJVM = FALSE;
}
/* Test set #1 */
{
/* Single parameter in 1 line. */
TCHAR *config = TEXT("-Dsomething=something");
TCHAR *strings[1];
strings[0] = TEXT("-Dsomething=something");
subTestJavaAdditionalParamSuite(FALSE, config, strings, ARRAY_LENGTH(strings), isJVM);
}
{
/* Multiple parameters in 1 line. */
TCHAR *config = TEXT("-Dsomething=something -Dxxx=xxx");
TCHAR *strings[2];
strings[0] = TEXT("-Dsomething=something");
strings[1] = TEXT("-Dxxx=xxx");
subTestJavaAdditionalParamSuite(FALSE, config, strings, ARRAY_LENGTH(strings), isJVM);
}
{
/* Horizontal Tab is not a delimiter. */
TCHAR *config = TEXT("-Dsomething1=something1\t-Dsomething2=something2 -Dxxx=xxx");
TCHAR *strings[2];
strings[0] = TEXT("-Dsomething1=something1\t-Dsomething2=something2");
strings[1] = TEXT("-Dxxx=xxx");
subTestJavaAdditionalParamSuite(FALSE, config, strings, ARRAY_LENGTH(strings), isJVM);
}
{
/* Horizontal Tab is not a delimiter. */
TCHAR *config = TEXT("-Dsomething1=something1\t-Dsomething2=something2 -Dxxx=xxx");
TCHAR *strings[2];
strings[0] = TEXT("-Dsomething1=something1\t-Dsomething2=something2");
strings[1] = TEXT("-Dxxx=xxx");
subTestJavaAdditionalParamSuite(FALSE, config, strings, ARRAY_LENGTH(strings), isJVM);
}
if (isJVM == TRUE) {
{
/* A parameter without heading '-' will be skipped. */
TCHAR *config = TEXT("something=something -Dxxx=xxx");
TCHAR *strings[1];
strings[0] = TEXT("-Dxxx=xxx");
subTestJavaAdditionalParamSuite(FALSE, config, strings, ARRAY_LENGTH(strings), isJVM);
}
} else {
{
/* A parameter without heading '-' will not be skipped. */
TCHAR *config = TEXT("something=something -Dxxx=xxx");
TCHAR *strings[2];
strings[0] = TEXT("something=something");
strings[1] = TEXT("-Dxxx=xxx");
subTestJavaAdditionalParamSuite(FALSE, config, strings, ARRAY_LENGTH(strings), isJVM);
}
}
/* Test set #2 : without stripping double quotations */
stripQuote = FALSE;
{
/* Quotations #1 */
TCHAR *config = TEXT("-DmyApp.x1=\"Hello World.\" -DmyApp.x2=x2");
TCHAR *strings[2];
strings[0] = TEXT("-DmyApp.x1=\"Hello World.\"");
strings[1] = TEXT("-DmyApp.x2=x2");
subTestJavaAdditionalParamSuite(stripQuote, config, strings, ARRAY_LENGTH(strings), isJVM);
}
{
/* Quotations #2 */
TCHAR *config = TEXT("\"-DmyApp.x1=Hello World.\" -DmyApp.x2=x2");
TCHAR *strings[2];
strings[0] = TEXT("\"-DmyApp.x1=Hello World.\"");
strings[1] = TEXT("-DmyApp.x2=x2");
subTestJavaAdditionalParamSuite(stripQuote, config, strings, ARRAY_LENGTH(strings), isJVM);
}
{
/* Escaped quotation */
TCHAR *config = TEXT("-DmyApp.x1=\"Hello \\\"World.\" -DmyApp.x2=x2");
TCHAR *strings[2];
strings[0] = TEXT("-DmyApp.x1=\"Hello \\\"World.\"");
strings[1] = TEXT("-DmyApp.x2=x2");
subTestJavaAdditionalParamSuite(stripQuote, config, strings, ARRAY_LENGTH(strings), isJVM);
}
{
/* Escaped backslash */
TCHAR *config = TEXT("-DmyApp.x1=\"Hello World.\\\\\" -DmyApp.x2=x2");
TCHAR *strings[2];
strings[0] = TEXT("-DmyApp.x1=\"Hello World.\\\\\"");
strings[1] = TEXT("-DmyApp.x2=x2");
subTestJavaAdditionalParamSuite(stripQuote, config, strings, ARRAY_LENGTH(strings), isJVM);
}
/* Test set #3 : with stripping double quotations */
stripQuote = TRUE;
{
/* Quotations #1 */
TCHAR *config = TEXT("-DmyApp.x1=\"Hello World.\" -DmyApp.x2=x2");
TCHAR *strings[2];
strings[0] = TEXT("-DmyApp.x1=Hello World.");
strings[1] = TEXT("-DmyApp.x2=x2");
subTestJavaAdditionalParamSuite(stripQuote, config, strings, ARRAY_LENGTH(strings), isJVM);
}
{
/* Quotations #2 */
TCHAR *config = TEXT("\"-DmyApp.x1=Hello World.\" -DmyApp.x2=x2");
TCHAR *strings[2];
strings[0] = TEXT("-DmyApp.x1=Hello World.");
strings[1] = TEXT("-DmyApp.x2=x2");
subTestJavaAdditionalParamSuite(stripQuote, config, strings, ARRAY_LENGTH(strings), isJVM);
}
{
/* Escaped quotation */
TCHAR *config = TEXT("-DmyApp.x1=\"Hello \\\"World.\" -DmyApp.x2=x2");
TCHAR *strings[2];
strings[0] = TEXT("-DmyApp.x1=Hello \"World.");
strings[1] = TEXT("-DmyApp.x2=x2");
subTestJavaAdditionalParamSuite(stripQuote, config, strings, ARRAY_LENGTH(strings), isJVM);
}
{
/* Escaped backslash */
TCHAR *config = TEXT("-DmyApp.x1=\"Hello World.\\\\\" -DmyApp.x2=x2");
TCHAR *strings[2];
strings[0] = TEXT("-DmyApp.x1=Hello World.\\");
strings[1] = TEXT("-DmyApp.x2=x2");
subTestJavaAdditionalParamSuite(stripQuote, config, strings, ARRAY_LENGTH(strings), isJVM);
}
}
}
#endif /* CUNIT */
wrapper_3.5.22_src/src/c/wrapper.h 100644 0 0 145451 12224722016 14255 0 ustar 0 0 /*
* Copyright (c) 1999, 2013 Tanuki Software, Ltd.
* http://www.tanukisoftware.com
* All rights reserved.
*
* This software is the proprietary information of Tanuki Software.
* You shall use it only in accordance with the terms of the
* license agreement you entered into with Tanuki Software.
* http://wrapper.tanukisoftware.com/doc/english/licenseOverview.html
*
*
* Portions of the Software have been derived from source code
* developed by Silver Egg Technology under the following license:
*
* Copyright (c) 2001 Silver Egg Technology
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sub-license, and/or
* sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*/
#ifndef _WRAPPER_H
#define _WRAPPER_H
#ifdef WIN32
#include
#endif
#include
#ifdef WIN32
#include
#else /* UNIX */
#include
#include
#include
#ifndef MACOSX
#define u_short unsigned short
#endif /* MACOSX */
#endif
#ifndef DWORD
#define DWORD unsigned long
#endif
#include
#include "property.h"
/* The following define will enable debug output of the code to parse the JVM output. */
/*#define DEBUG_CHILD_OUTPUT*/
/* Initialize the timerTicks to a very high value. This means that we will
* always encounter the first rollover (512 * WRAPPER_MS / 1000) seconds
* after the Wrapper the starts, which means the rollover will be well
* tested. */
#define WRAPPER_TICK_INITIAL 0xfffffe00
#define WRAPPER_TICK_MS 100 /* The number of ms that are represented by a single
* tick. Ticks are used as an alternative time
* keeping method. See the wrapperGetTicks() and
* wrapperGetTickAgeSeconds() functions for more information.
* Some code assumes that this number can be evenly
* divided into 1000. */
#define WRAPPER_MAX_UPTIME_SECONDS 365 * 24 * 3600 /* Maximum uptime count. 1 year. */
#define WRAPPER_MAX_UPTIME_TICKS (WRAPPER_MAX_UPTIME_SECONDS * (1000 / WRAPPER_TICK_MS)) /* The paranthesis are important to avoid overflow. */
#define WRAPPER_TIMER_FAST_THRESHOLD (2 * 24 * 3600 * 1000 / WRAPPER_TICK_MS) /* Default to 2 days. */
#define WRAPPER_TIMER_SLOW_THRESHOLD (2 * 24 * 3600 * 1000 / WRAPPER_TICK_MS) /* Default to 2 days. */
#define WRAPPER_BACKEND_TYPE_UNKNOWN 0 /* Unknown type. */
#define WRAPPER_BACKEND_TYPE_SOCKET 1 /* Use a loopback socket to communicate. */
#define WRAPPER_BACKEND_TYPE_PIPE 2 /* Use a pair of pipes to communicate. */
#define WRAPPER_WSTATE_STARTING 51 /* Wrapper is starting. Remains in this state
* until the JVM enters the STARTED state or
* the wrapper jumps into the STOPPING state
* in response to the JVM application asking
* to shut down. */
#define WRAPPER_WSTATE_STARTED 52 /* The JVM has entered the STARTED state.
* The wrapper will remain in this state
* until the wrapper decides to shut down.
* This is true even when the JVM process
* is being restarted. */
#define WRAPPER_WSTATE_PAUSING 53 /* The wrapper enters this state when asked to Pause. */
#define WRAPPER_WSTATE_PAUSED 54 /* The wrapper enters this state when the Wrapper
* has actually paused. */
#define WRAPPER_WSTATE_RESUMING 55 /* The wrapper enters this state when asked to Resume. */
#define WRAPPER_WSTATE_STOPPING 56 /* The wrapper is shutting down. Will be in
* this state until the JVM enters the DOWN
* state. */
#define WRAPPER_WSTATE_STOPPED 57 /* The wrapper enters this state just before
* it exits. */
#define WRAPPER_JSTATE_DOWN_CHECK 70 /* JVM is confirmed to be down, but we still need
* to do our cleanup work. This is the state after
* a JVM process has gone away. */
#define WRAPPER_JSTATE_DOWN_FLUSH 71 /* JVM is confirmed to be down but we still need
* flush and process all of its output. */
#define WRAPPER_JSTATE_DOWN_CLEAN 72 /* JVM is confirmed to be down and we have cleaned
* up and flushed all output. This is the initial
* state and the state after the JVM process has
* gone away and and cleanup has been done. */
#define WRAPPER_JSTATE_LAUNCH_DELAY 73 /* Set from the DOWN state to launch a JVM. The
* timeout will be the time to actually launch
* the JVM after any required delay. */
#define WRAPPER_JSTATE_RESTART 74 /* JVM is about to be restarted. No timeout. */
#define WRAPPER_JSTATE_LAUNCH 75 /* JVM is about to launch a JVM. No timeout. */
#define WRAPPER_JSTATE_LAUNCHING 76 /* JVM was launched, but has not yet responded.
* Must enter the LAUNCHED state before
* or the JVM will be killed. */
#define WRAPPER_JSTATE_LAUNCHED 77 /* JVM was launched, and responed to a ping. */
#define WRAPPER_JSTATE_STARTING 78 /* JVM has been asked to start. Must enter the
* STARTED state before or the JVM will be
* killed. */
#define WRAPPER_JSTATE_STARTED 79 /* JVM has responded that it is running. Must
* respond to a ping by or the JVM will
* be killed. */
#define WRAPPER_JSTATE_STOP 80 /* JVM is about to be sent a stop command to shutdown
* cleanly. */
#define WRAPPER_JSTATE_STOPPING 81 /* JVM was sent a stop command, but has not yet
* responded. Must enter the STOPPED state
* and exit before or the JVM will be killed. */
#define WRAPPER_JSTATE_STOPPED 82 /* JVM has responed that it is stopped. */
#define WRAPPER_JSTATE_KILLING 83 /* The Wrapper is about ready to kill the JVM
* process but it must wait a few moments before
* actually doing so. After has expired, the
* JVM will be killed and we will enter the STOPPED
* state. */
#define WRAPPER_JSTATE_KILL 84 /* The Wrapper is about ready to kill the JVM process. */
#define WRAPPER_JSTATE_KILLED 85 /* The Wrapper has requested termination of the JVM and
confirmed the JVM is actually killed */
/* Defined Action types. Registered actions are negative. Custom types are positive. */
#define ACTION_LIST_END 0
#define ACTION_NONE -1
#define ACTION_RESTART -2
#define ACTION_SHUTDOWN -3
#define ACTION_DUMP -4
#define ACTION_DEBUG -5
#define ACTION_PAUSE -6
#define ACTION_RESUME -7
#define ACTION_SUCCESS -8
#define ACTION_GC -9
#if defined(MACOSX)
#define TRIGGER_ADVICE_NIL_SERVER TEXT("****** Returning nil _server **********")
#define ACTION_ADVICE_NIL_SERVER -32
#endif
/* The following codes are passed through and referenced within the WrapperServiceActionEvent class.
* They can be added, but not changed without the possibility of affecting user code. */
#define WRAPPER_ACTION_SOURCE_CODE_FILTER 1 /* Action originated with a filter. */
#define WRAPPER_ACTION_SOURCE_CODE_COMMANDFILE 2 /* Action originated from a commandfile. */
#define WRAPPER_ACTION_SOURCE_CODE_WINDOWS_SERVICE_MANAGER 3 /* Action originated from the Windows Service Manager. */
#define WRAPPER_ACTION_SOURCE_CODE_ON_EXIT 4 /* Action originated from an on_exit configuration. */
#define WRAPPER_ACTION_SOURCE_CODE_PING_TIMEOUT 11 /* Action originated from a timeout. */
/* Because of the way time is converted to ticks, the largest possible timeout that
* can be specified without causing 32-bit overflows is (2^31 / 1000) - 5 = 2147478
* Which is a little over 24 days. To make the interface nice, round this down to
* 20 days. Or 1728000. */
#define WRAPPER_TIMEOUT_MAX 1728000
#define WRAPPER_IGNORE_SIGNALS_WRAPPER 1
#define WRAPPER_IGNORE_SIGNALS_JAVA 2
#define WRAPPER_RESTART_REQUESTED_NO 0
#define WRAPPER_RESTART_REQUESTED_INITIAL 1
#define WRAPPER_RESTART_REQUESTED_AUTOMATIC 2
#define WRAPPER_RESTART_REQUESTED_CONFIGURED 4
#ifdef JSW64
typedef unsigned int TICKS;
#else
typedef unsigned long TICKS;
#endif
#define WRAPPER_ENV_SOURCE_PARENT 1
#define WRAPPER_ENV_SOURCE_WRAPPER 2
#ifdef WIN32
#define WRAPPER_ENV_SOURCE_REG_SYSTEM 4
#define WRAPPER_ENV_SOURCE_REG_ACCOUNT 8
#endif
#ifdef WIN32
/* Defines the maximum number of service manager control events that can be queued in a single loop. */
#define CTRL_CODE_QUEUE_SIZE 26 /* Can enqueue one less than this count at any time. */
#endif
#define WRAPPER_JAVAIO_BUFFER_SIZE_SYSTEM_DEFAULT 0
#define WRAPPER_JAVAIO_BUFFER_SIZE_MIN 1024
#define WRAPPER_JAVAIO_BUFFER_SIZE_MAX (10 * 1024 * 1024)
#define WRAPPER_JAVAIO_BUFFER_SIZE_DEFAULT (64 * 1024)
/*#define DEBUG_PING_QUEUE*/
#define WRAPPER_MAX_PENDING_PINGS 10
typedef struct PendingPing PendingPing, *PPendingPing;
struct PendingPing {
TICKS sentTicks;
TICKS timeoutTicks;
TICKS slowTicks;
PPendingPing nextPendingPing;
};
/* Type definitions */
typedef struct WrapperConfig WrapperConfig;
struct WrapperConfig {
TCHAR *argBinary; /* The name of the wrapper binary. */
TCHAR *argCommand; /* The command used to launch the wrapper. */
TCHAR *argCommandArg; /* The argument to the command used to launch the wrapper. */
TCHAR *argConfFile; /* The name of the config file from the command line. */
TCHAR *confDir;
int argConfFileDefault; /* True if the config file was not specified. */
int argConfFileFound; /* True if the config file was found. */
int argCount; /* The total argument count. */
TCHAR **argValues; /* Argument values. */
TCHAR **javaArgValues; /* Arguments getting passed over to the java application */
int javaArgValueCount; /* Number of the arguments getting passed over to the java application */
TCHAR *initialPath; /* What the working directory was when the Wrapper process was first launched. */
TCHAR *language; /* The language */
int backendType; /* The type of the backend that the Wrapper and Java use to communicate. */
int configured; /* TRUE if loadConfiguration has been called. */
int useSystemTime; /* TRUE if the wrapper should use the system clock for timing, FALSE if a tick counter should be used. */
int logBufferGrowth; /* TRUE if changes to internal buffer sizes should be logged. */
int timerFastThreshold; /* If the difference between the system time based tick count and the timer tick count ever falls by more than this value then a warning will be displayed. */
int timerSlowThreshold; /* If the difference between the system time based tick count and the timer tick count ever grows by more than this value then a warning will be displayed. */
int useTickMutex; /* TRUE if access to the tick count should be protected by a mutex. */
int uptimeFlipped; /* TRUE when the maximum uptime has been flipped. (Overflown) */
int ignoreSequenceGaps; /* TRUE if all sequence properties should be used. */
int port; /* Port number which the Wrapper is configured to be listening on */
int portMin; /* Minimum port to use when looking for a port to bind to. */
int portMax; /* Maximum port to use when looking for a port to bind to. */
int actualPort; /* Port number which the Wrapper is actually listening on */
int jvmPort; /* The port which the JVM should bind to when connecting back to the wrapper. */
int jvmPortMin; /* Minimum port which the JVM should bind to when connecting back to the wrapper. */
int jvmPortMax; /* Maximum port which the JVM should bind to when connecting back to the wrapper. */
int sock; /* Socket number. if open. */
TCHAR *portAddress;
TCHAR *originalWorkingDir; /* Original Wrapper working directory. */
TCHAR *workingDir; /* Configured working directory. */
TCHAR *configFile; /* Name of the configuration file */
int commandLogLevel; /* The log level to use when logging the java command. */
int printJVMVersion; /* tells the Wrapper to create a temp JVM to query the version, before starting the java application */
#ifdef WIN32
TCHAR *jvmCommand; /* Command used to launch the JVM */
#else /* UNIX */
TCHAR **jvmCommand; /* Command used to launch the JVM */
#endif
int detachStarted; /* TRUE if the JVM process should be detached once it has started. */
int environmentClasspath; /* TRUE if the classpath should be passed to the JVM in the environment. */
TCHAR *classpath; /* Classpath to pass to the JVM. */
int debugJVM; /* True if the JVM is being launched with a debugger enabled. */
int debugJVMTimeoutNotified;/* True if the JVM is being launched with a debugger enabled and the user has already been notified of a timeout. */
TCHAR key[17]; /* Key which the JVM uses to authorize connections. (16 digits + \0) */
int isConsole; /* TRUE if the wrapper was launched as a console. */
int cpuTimeout; /* Number of seconds without CPU before the JVM will issue a warning and extend timeouts */
int startupTimeout; /* Number of seconds the wrapper will wait for a JVM to startup */
int pingTimeout; /* Number of seconds the wrapper will wait for a JVM to reply to a ping */
int pingAlertThreshold; /* Number of seconds without a ping response that the Wrapper will start to warn about a slow ping. */
int pingAlertLogLevel; /* Long level at which slow ping notices are logged. */
int pingInterval; /* Number of seconds between pinging the JVM */
int pingIntervalLogged; /* Number of seconds between pings which can be logged to debug output. */
int *pingActionList; /* The action list to take when a ping timeout is detected. */
int pingTimedOut;
int shutdownTimeout; /* Number of seconds the wrapper will wait for a JVM to shutdown */
int jvmExitTimeout; /* Number of seconds the wrapper will wait for a JVM to process to terminate */
int jvmCleanupTimeout; /* Number of seconds the wrapper will allow for its post JVM shudown cleanup. */
int jvmTerminateTimeout; /* Number of seconds the wrapper will allow for the JVM to respond to TerminateProcess request. */
#ifdef WIN32
int javaIOBufferSize; /* Size of the pipe buffer to use for java I/O. */
#endif
int useJavaIOThread; /* If TRUE then a dedicated thread will be used to process console output form the JVM. */
int pauseThreadMain; /* Number of seconds to pause the main thread on its next loop. Only used for testing. */
int pauseThreadTimer; /* Number of seconds to pause the timer thread on its next loop. Only used for testing. */
int pauseThreadJavaIO; /* Number of seconds to pause the javaio thread on its next loop. Only used for testing. */
#ifdef WIN32
int ignoreUserLogoffs; /* If TRUE, the Wrapper will ignore logoff events when run in the background as an in console mode. */
TCHAR *userName; /* The username (account) of the Wrapper process. */
TCHAR *domainName; /* The domain of the Wrapper process. */
DWORD wrapperPID; /* PID of the Wrapper process. */
DWORD javaPID; /* PID of the Java process. */
HANDLE wrapperProcess; /* Handle of the Wrapper process. */
HANDLE javaProcess; /* Handle of the Java process. */
#else
pid_t wrapperPID; /* PID of the Wrapper process. */
pid_t javaPID; /* PID of the Java process. */
#endif
int wState; /* The current state of the wrapper */
int jState; /* The current state of the jvm */
TICKS jStateTimeoutTicks; /* Tick count until which the current jState is valid */
int jStateTimeoutTicksSet; /* 1 if the current jStateTimeoutTicks is set. */
TICKS lastPingTicks; /* Time that the last ping was sent */
TICKS lastLoggedPingTicks; /* Time that the last logged ping was sent */
int isDebugging; /* TRUE if set in the configuration file */
int isAdviserEnabled; /* TRUE if advice messages should be output. */
const TCHAR *nativeLibrary; /* The base name of the native library loaded by the WrapperManager. */
int libraryPathAppendPath; /* TRUE if the PATH environment variable should be appended to the java library path. */
int isStateOutputEnabled; /* TRUE if set in the configuration file. Shows output on the state of the state engine. */
int isJavaIOOutputEnabled; /* TRUE if detailed javaIO output should be included in debug output. */
int isTickOutputEnabled; /* TRUE if detailed tick timer output should be included in debug output. */
int isLoopOutputEnabled; /* TRUE if very detailed output from the main loop should be output. */
int isSleepOutputEnabled; /* TRUE if detailed sleep output should be included in debug output. */
int isMemoryOutputEnabled; /* TRUE if detailed memory output should be included in status output. */
int memoryOutputInterval; /* Interval in seconds at which memory usage is logged. */
TICKS memoryOutputTimeoutTicks; /* Tick count at which memory will next be logged. */
int isCPUOutputEnabled; /* TRUE if detailed CPU output should be included in status output. */
int cpuOutputInterval; /* Interval in seconds at which CPU usage is logged. */
TICKS cpuOutputTimeoutTicks; /* Tick count at which CPU will next be logged. */
int isPageFaultOutputEnabled;/* TRUE if detailed PageFault output should be included in status output. */
int pageFaultOutputInterval;/* Interval in seconds at which PageFault usage is logged. */
TICKS pageFaultOutputTimeoutTicks; /* Tick count at which PageFault will next be logged. */
int logfileFlushTimeout; /* The number of seconds before the logfile will be flushed. */
TICKS logfileFlushTimeoutTicks; /* Tick count at which the logfile will be flushed. */
int logfileFlushTimeoutTicksSet; /* TRUE if logfileFlushTimeoutTicks is set. */
int logfileCloseTimeout; /* The number of seconds of inactivity before the logfile will be closed. */
TICKS logfileCloseTimeoutTicks; /* Tick count at which the logfile will be considered inactive and closed. */
int logfileCloseTimeoutTicksSet; /* TRUE if logfileCloseTimeoutTicks is set. */
int isTestsDisabled; /* TRUE if the use of tests in the WrapperManager class should be disabled. */
int isShutdownHookDisabled; /* TRUE if the use of a shutdown hook by the WrapperManager class should be disabled. */
int isForcedShutdownDisabled; /* TRUE if forced shutdowns are disabled. */
int startupDelayConsole; /* Delay in seconds before starting the first JVM in console mode. */
int startupDelayService; /* Delay in seconds before starting the first JVM in service mode. */
int exitCode; /* Code which the wrapper will exit with */
int exitRequested; /* TRUE if the current JVM should be shutdown. */
int restartRequested; /* WRAPPER_RESTART_REQUESTED_NO, WRAPPER_RESTART_REQUESTED_AUTOMATIC, or WRAPPER_RESTART_REQUESTED_CONFIGURED if the another JVM should be launched after the current JVM is shutdown. Only set if exitRequested is set. */
int stoppedPacketReceived; /* TRUE if the STOPPED packet was received before a restart. */
int restartPacketReceived; /* TRUE if the RESTART packet was received before a restart. */
int jvmRestarts; /* Number of times that a JVM has been launched since the wrapper was started. */
int restartDelay; /* Delay in seconds before restarting a new JVM. */
int restartReloadConf; /* TRUE if the configuration should be reloaded before a JVM restart. */
int isRestartDisabled; /* TRUE if restarts should be disabled. */
int isAutoRestartDisabled; /* TRUE if automatic restarts should be disabled. */
int requestThreadDumpOnFailedJVMExit; /* TRUE if the JVM should be asked to dump its state when it fails to halt on request. */
int requestThreadDumpOnFailedJVMExitDelay; /* Number of seconds to wait after the thread dump before killing the JVM. */
TICKS jvmLaunchTicks; /* The tick count at which the previous or current JVM was launched. */
int failedInvocationCount; /* The number of times that the JVM exited in less than successfulInvocationTime in a row. */
int successfulInvocationTime;/* Amount of time that a new JVM must be running so that the invocation will be considered to have been a success, leading to a reset of the restart count. */
int maxFailedInvocations; /* Maximum number of failed invocations in a row before the Wrapper will give up and exit. */
int outputFilterCount; /* Number of registered output filters. */
TCHAR **outputFilters; /* Array of output filters. */
int **outputFilterActionLists;/* Array of output filter action lists. */
TCHAR **outputFilterMessages; /* Array of output filter messages. */
int *outputFilterAllowWildFlags; /* Array of output filter flags that say whether or not wild cards in the filter can be processed. */
size_t *outputFilterMinLens; /* Array of the minimum text lengths that could possibly match the specified filter. Only used if it contains wildcards. */
TCHAR *pidFilename; /* Name of file to store wrapper pid in */
int pidFileStrict; /* TRUE if a preexisting pid file should cause an error. */
TCHAR *lockFilename; /* Name of file to store wrapper lock in */
TCHAR *javaPidFilename; /* Name of file to store jvm pid in */
TCHAR *javaIdFilename; /* Name of file to store jvm id in */
TCHAR *statusFilename; /* Name of file to store wrapper status in */
TCHAR *javaStatusFilename; /* Name of file to store jvm status in */
TCHAR *commandFilename; /* Name of a command file used to send commands to the Wrapper. */
int commandFileTests; /* True if test commands will be accepted via the command file. */
int commandPollInterval; /* Interval in seconds at which the existence of the command file is polled. */
TICKS commandTimeoutTicks; /* Tick count at which the command file will be checked next. */
TCHAR *anchorFilename; /* Name of an anchor file used to control when the Wrapper should quit. */
int anchorPollInterval; /* Interval in seconds at which the existence of the anchor file is polled. */
TICKS anchorTimeoutTicks; /* Tick count at which the anchor file will be checked next. */
int umask; /* Default umask for all files. */
int javaUmask; /* Default umask for the java process. */
int pidFileUmask; /* Umask to use when creating the pid file. */
int lockFileUmask; /* Umask to use when creating the lock file. */
int javaPidFileUmask; /* Umask to use when creating the java pid file. */
int javaIdFileUmask; /* Umask to use when creating the java id file. */
int statusFileUmask; /* Umask to use when creating the status file. */
int javaStatusFileUmask; /* Umask to use when creating the java status file. */
int anchorFileUmask; /* Umask to use when creating the anchor file. */
int ignoreSignals; /* Mask that determines where the Wrapper should ignore any catchable system signals. Can be ingored in the Wrapper and/or JVM. */
TCHAR *consoleTitle; /* Text to set the console title to. */
TCHAR *serviceName; /* Name of the service. */
TCHAR *serviceDisplayName; /* Display name of the service. */
TCHAR *serviceDescription; /* Description for service. */
TCHAR *hostName; /* The name of the current host. */
int pausable; /* Should the service be allowed to be paused? */
int pausableStopJVM; /* Should the JVM be stopped when the service is paused? */
int initiallyPaused; /* Should the Wrapper come up initially in a paused state? */
int logLFDelayThreshold; /* The LF Delay threshold to use when logging java output. */
#ifdef WIN32
int isSingleInvocation; /* TRUE if only a single invocation of an application should be allowed to launch. */
TCHAR *ntServiceLoadOrderGroup; /* Load order group name. */
TCHAR *ntServiceDependencies; /* List of Dependencies */
int ntServiceStartType; /* Mode in which the Service is installed.
* {SERVICE_AUTO_START | SERVICE_DEMAND_START} */
DWORD ntServicePriorityClass; /* Priority at which the Wrapper and its JVMS will run.
* {HIGH_PRIORITY_CLASS | IDLE_PRIORITY_CLASS | NORMAL_PRIORITY_CLASS | REALTIME_PRIORITY_CLASS} */
TCHAR *ntServiceAccount; /* Account name to use when running as a service. NULL to use the LocalSystem account. */
TCHAR *ntServicePassword; /* Password to use when running as a service. NULL means no password. */
int ntServicePrompt; /* If true then the user will be prompted for a account name, domain, password when installing as a service. */
int ntServicePasswordPrompt; /* If true then the user will be prompted for a password when installing as a service. */
int ntServicePasswordPromptMask; /* If true then the password will be masked as it is input. */
int ntServiceInteractive; /* Should the service be allowed to interact with the desktop? */
int ntHideJVMConsole; /* Should the JVMs Console window be hidden when run as a service. True by default but GUIs will not be visible for JVMs prior to 1.4.0. */
int ntHideWrapperConsole; /* Should the Wrapper Console window be hidden when run as a service. */
HINSTANCE wrapperHInstance; /* The HINSTANCE of the Wrapper process. */
int wrapperConsoleHide; /* True if the Wrapper Console window should be hidden. */
HWND wrapperConsoleHWND; /* The HWND of the Wrapper's console if it was located. */
int wrapperConsoleVisible; /* True if the Wrapper Console window is visible. */
HWND jvmConsoleHandle; /* Pointer to the JVM Console handle if it exists. */
int jvmConsoleVisible; /* True if the JVM Console window is visible. */
int ntAllocConsole; /* True if a console should be allocated for the Service. */
int generateConsole; /* Make sure that a console is always generated to support thread dumps */
int threadDumpControlCode; /* Control code which can be used to trigger a thread dump. */
#else /* UNIX */
int daemonize; /* TRUE if the process should be spawned as a daemon process on launch. */
int signalHUPMode; /* Controls what happens when the Wrapper receives a HUP signal. */
int signalUSR1Mode; /* Controls what happens when the Wrapper receives a USR1 signal. */
int signalUSR2Mode; /* Controls what happens when the Wrapper receives a USR2 signal. */
int jvmStopped; /* Flag which remembers the the stopped state of the JVM process. */
#endif
int pendingPingQueueOverflow; /* Flag which is set to true if the PendingPingQueue overflows the limit of WRAPPER_MAX_PENDING_PINGS. */
int pendingPingQueueOverflowEmptied; /* Flag which is set when the queue size is reduced to 0 after having overflowed. */
int pendingPingCount; /* Number of PendingPing events in the list. */
PPendingPing firstPendingPing; /* Pointer to the first PendingPing in the list. */
PPendingPing firstUnwarnedPendingPing; /* Pointer to the first PendingPing in the list for which a slow warning has not been logged. */
PPendingPing lastPendingPing; /* Pointer to the last PendingPing in the list. */
#ifdef WIN32
int ctrlEventCTRLCTrapped; /* CTRL_C_EVENT trapped. */
int ctrlEventCloseTrapped; /* CTRL_CLOSE_EVENT trapped. */
int ctrlEventLogoffTrapped; /* CTRL_LOGOFF_EVENT trapped. */
int ctrlEventShutdownTrapped;/* CTRL_SHUTDOWN_EVENT trapped. */
int *ctrlCodeQueue; /* Queue of control code ids trapped. */
int ctrlCodeQueueWriteIndex;
int ctrlCodeQueueReadIndex;
int ctrlCodeQueueWrapped;
int ctrlCodePauseTrapped; /* SERVICE_CONTROL_PAUSE was trapped. */
int ctrlCodeContinueTrapped;/* SERVICE_CONTROL_CONTINUE was trapped. */
int ctrlCodeStopTrapped; /* SERVICE_CONTROL_STOP was trapped. */
int ctrlCodeShutdownTrapped;/* SERVICE_CONTROL_SHUTDOWN was trapped. */
int ctrlCodeDumpTrapped; /* The configured thread dump control code was trapped. */
#else
int signalInterruptTrapped; /* SIGINT was trapped. */
int signalQuitTrapped; /* SIGQUIT was trapped. */
int signalChildTrapped; /* SIGCHLD was trapped. */
int signalTermTrapped; /* SIGTERM was trapped. */
int signalHUPTrapped; /* SIGHUP was trapped. */
int signalUSR1Trapped; /* SIGUSR1 was trapped. */
int signalUSR2Trapped; /* SIGUSR2 was trapped. */
#endif
};
#define WRAPPER_SIGNAL_MODE_IGNORE (char)100
#define WRAPPER_SIGNAL_MODE_RESTART (char)101
#define WRAPPER_SIGNAL_MODE_SHUTDOWN (char)102
#define WRAPPER_SIGNAL_MODE_FORWARD (char)103
#define WRAPPER_MSG_START (char)100
#define WRAPPER_MSG_STOP (char)101
#define WRAPPER_MSG_RESTART (char)102
#define WRAPPER_MSG_PING (char)103
#define WRAPPER_MSG_STOP_PENDING (char)104
#define WRAPPER_MSG_START_PENDING (char)105
#define WRAPPER_MSG_STARTED (char)106
#define WRAPPER_MSG_STOPPED (char)107
#define WRAPPER_MSG_KEY (char)110
#define WRAPPER_MSG_BADKEY (char)111
#define WRAPPER_MSG_LOW_LOG_LEVEL (char)112
#define WRAPPER_MSG_PING_TIMEOUT (char)113 /* No longer used. But keep reserved to avoid future problems. */
#define WRAPPER_MSG_SERVICE_CONTROL_CODE (char)114
#define WRAPPER_MSG_PROPERTIES (char)115
/** Log commands are actually 116 + the LOG LEVEL (LEVEL_UNKNOWN ~ LEVEL_NONE), (116 ~ 124). */
#define WRAPPER_MSG_LOG (char)116
#define WRAPPER_MSG_LOGFILE (char)134
#define WRAPPER_MSG_APPEAR_ORPHAN (char)137 /* No longer used. But keep reserved to avoid future problems. */
#define WRAPPER_MSG_PAUSE (char)138
#define WRAPPER_MSG_RESUME (char)139
#define WRAPPER_MSG_GC (char)140
#define WRAPPER_PROCESS_DOWN 200
#define WRAPPER_PROCESS_UP 201
extern WrapperConfig *wrapperData;
extern Properties *properties;
extern TCHAR wrapperClasspathSeparator;
/* Protocol Functions */
/**
* Close the backend socket.
*/
extern void wrapperProtocolClose();
/**
* Sends a command to the JVM process.
*
* @param function The command to send. (This is intentionally an 8-bit char.)
* @param message Message to send along with the command.
*
* @return TRUE if there were any problems.
*/
extern int wrapperProtocolFunction(char function, const TCHAR *message);
/**
* Checks the status of the server backend.
*
* The backend will be initialized if the JVM is in a state where it should
* be up, otherwise the backend will be left alone.
*
* If the forceOpen flag is set then an attempt will be made to initialize
* the backend regardless of the JVM state.
*
* Returns TRUE if the backend is open and ready on return, FALSE if not.
*/
extern int wrapperCheckServerBackend(int forceOpen);
/**
* Read any data sent from the JVM. This function will loop and read as many
* packets are available. The loop will only be allowed to go for 250ms to
* ensure that other functions are handled correctly.
*
* Returns 0 if all available data has been read, 1 if more data is waiting.
*/
extern int wrapperProtocolRead();
/******************************************************************************
* Utility Functions
*****************************************************************************/
/**
* Test function to pause the current thread for the specified amount of time.
* This is used to test how the rest of the Wrapper behaves when a particular
* thread blocks for any reason.
*
* @param pauseTime Number of seconds to pause for. -1 will pause indefinitely.
* @param threadName Name of the thread that will be logged prior to pausing.
*/
extern void wrapperPauseThread(int pauseTime, const TCHAR *threadName);
/**
* Function that will recursively attempt to match two strings where the
* pattern can contain '?' or '*' wildcard characters.
*
* @param text Text to be searched.
* @param pattern Pattern to search for.
* @param patternLen Length of the pattern.
* @param minTextLen Minimum number of characters that the text needs to possibly match the pattern.
*
* @return TRUE if found, FALSE otherwise.
*/
extern int wrapperWildcardMatch(const TCHAR *text, const TCHAR *pattern, size_t minTextLen);
/**
* Calculates the minimum text length which could be matched by the specified pattern.
* Patterns can contain '*' or '?' wildcards.
* '*' matches 0 or more characters.
* '?' matches exactly one character.
*
* @param pattern Pattern to calculate.
*
* @return The minimum text length of the pattern.
*/
extern size_t wrapperGetMinimumTextLengthForPattern(const TCHAR *pattern);
/**
* Returns a constant text representation of the specified Wrapper State.
*
* @param wState The Wrapper State whose name is being requested.
*
* @return Thre requested Wrapper State.
*/
extern const TCHAR *wrapperGetWState(int wState);
/**
* Returns a constant text representation of the specified Java State.
*
* @param jState The Java State whose name is being requested.
*
* @return Thre requested Java State.
*/
extern const TCHAR *wrapperGetJState(int jState);
extern struct tm wrapperGetReleaseTime();
extern struct tm wrapperGetBuildTime();
#ifdef WIN32
extern int initializeStartup();
extern void disposeStartup();
#endif
extern void disposeJavaIO();
extern void disposeTimer();
extern int showHostIds(int logLevel);
extern void wrapperLoadHostName();
/**
* Parses a list of actions for an action property.
*
* @param actionNameList A space separated list of action names.
* @param propertyName The name of the property where the action name originated.
*
* @return an array of integer action ids, or NULL if there were any problems.
*/
extern int *wrapperGetActionListForNames(const TCHAR *actionNameList, const TCHAR *propertyName);
/**
* Performs the specified action,
*
* @param actionList An array of action Ids ending with a value ACTION_LIST_END.
* Negative values are standard actions, positive are user
* custom events.
* @param triggerMsg The reason the actions are being fired.
* @param actionSourceCode Tracks where the action originated.
* @param logForActionNone Flag stating whether or not a message should be logged
* for the NONE action.
* @param exitCode Error code to use in case the action results in a shutdown.
*/
extern void wrapperProcessActionList(int *actionList, const TCHAR *triggerMsg, int actionSourceCode, int logForActionNone, int exitCode);
extern void wrapperAddDefaultProperties();
extern int wrapperLoadConfigurationProperties(int preload);
extern void wrapperGetCurrentTime(struct timeb *timeBuffer);
#ifdef WIN32
extern void wrapperInitializeProfileCounters();
extern void wrapperDumpPageFaultUsage();
extern void updateStringValue(TCHAR **ptr, const TCHAR *value);
extern TCHAR** wrapperGetSystemPath();
extern int wrapperGetJavaHomeFromWindowsRegistry(TCHAR *javaHome);
#endif
extern int wrapperCheckRestartTimeOK();
extern int wrapperBuildJavaClasspath(TCHAR **classpath);
/**
* command is a pointer to a pointer of an array of character strings.
* length is the number of strings in the above array.
*/
extern int wrapperBuildJavaCommandArray(TCHAR ***strings, int *length, int addQuotes, const TCHAR *classpath);
extern void wrapperFreeJavaCommandArray(TCHAR **strings, int length);
extern int wrapperInitialize();
extern void wrapperDispose();
/**
* Returns the file name base as a newly malloced TCHAR *. The resulting
* base file name will have any path and extension stripped.
*
* baseName should be long enough to always contain the base name.
* (strlen(fileName) + 1) is safe.
*/
extern void wrapperGetFileBase(const TCHAR *fileName, TCHAR *baseName);
/**
* Output the version.
*/
extern void wrapperVersionBanner();
/**
* Output the application usage.
*/
extern void wrapperUsage(TCHAR *appName);
/**
* Parse the main arguments.
*
* Returns FALSE if the application should exit with an error. A message will
* already have been logged.
*/
extern int wrapperParseArguments(int argc, TCHAR **argv);
/**
* Called when the Wrapper detects that the JVM process has exited.
* Contains code common to all platforms.
*/
extern void wrapperJVMProcessExited(TICKS nowTicks, int exitCode);
/**
* Read and process any output from the child JVM Process.
*
* When maxTimeMS is non-zero this function will only be allowed to run for that maximum
* amount of time. This is done to make sure the calling function is allowed CPU for
* other activities. When timing out for this reason when there is more data in the
* pipe, this function will return TRUE to let the calling code know that it should
* not to any unnecessary sleeps. Otherwise FALSE will be returned.
*
* @param maxTimeMS The maximum number of milliseconds that this function will be allowed
* to run without returning. In reality no new reads will happen after
* this time, but actual processing may take longer.
*
* @return TRUE if the calling code should call this function again as soon as possible.
*/
extern int wrapperReadChildOutput(int maxTimeMS);
/**
* Changes the current Wrapper state.
*
* wState - The new Wrapper state.
*/
extern void wrapperSetWrapperState(int wState);
/**
* Updates the current state time out.
*
* nowTicks - The current tick count at the time of the call, may be -1 if
* delay is negative.
* delay - The delay in seconds, added to the nowTicks after which the state
* will time out, if negative will never time out.
*/
extern void wrapperUpdateJavaStateTimeout(TICKS nowTicks, int delay);
/**
* Changes the current Java state.
*
* jState - The new Java state.
* nowTicks - The current tick count at the time of the call, may be -1 if
* delay is negative.
* delay - The delay in seconds, added to the nowTicks after which the state
* will time out, if negative will never time out.
*/
extern void wrapperSetJavaState(int jState, TICKS nowTicks, int delay);
/******************************************************************************
* Platform specific methods
*****************************************************************************/
#ifdef WIN32
extern void wrapperCheckConsoleWindows();
/**
* checks the digital Signature of the binary and reports the result.
*/
extern BOOL verifyEmbeddedSignature();
extern int exceptionFilterFunction(PEXCEPTION_POINTERS exceptionPointers);
BOOL extern elevateThis(int argc, TCHAR **argv);
BOOL extern duplicateSTD();
BOOL extern myShellExec(HWND hwnd, LPCTSTR pszVerb, LPCTSTR pszPath, LPCTSTR pszParameters, LPCTSTR pszDirectory, TCHAR* namedPipeName);
BOOL extern runElevated( __in LPCTSTR pszPath, __in_opt LPCTSTR pszParameters, __in_opt LPCTSTR pszDirectory, TCHAR* namedPipeName);
BOOL extern isElevated();
BOOL extern isVista();
extern void wrapperMaintainControlCodes();
#else
extern void wrapperMaintainSignals();
extern TCHAR* findPathOf(const TCHAR *exe, const TCHAR* name);
#endif
/**
* Gets the error code for the last operation that failed.
*/
extern int wrapperGetLastError();
/**
* Execute initialization code to get the wrapper set up.
*/
extern int wrapperInitializeRun();
/**
* Cause the current thread to sleep for the specified number of milliseconds.
* Sleeps over one second are not allowed.
*
* @param ms Number of milliseconds to wait for.
*
* @return TRUE if the was interrupted, FALSE otherwise. Neither is an error.
*/
extern int wrapperSleep(int ms);
/**
* Reports the status of the wrapper to the service manager
* Possible status values:
* WRAPPER_WSTATE_STARTING
* WRAPPER_WSTATE_STARTED
* WRAPPER_WSTATE_STOPPING
* WRAPPER_WSTATE_STOPPED
*/
extern void wrapperReportStatus(int useLoggerQueue, int status, int errorCode, int waitHint);
/**
* Reads a single block of data from the child pipe.
*
* @param blockBuffer Pointer to the buffer where the block will be read.
* @param blockSize Maximum number of bytes to read.
* @param readCount Pointer to an int which will hold the number of bytes
* actually read by the call.
*
* Returns TRUE if there were any problems, FALSE otherwise.
*/
extern int wrapperReadChildOutputBlock(char *blockBuffer, int blockSize, int *readCount);
/**
* Checks on the status of the JVM Process.
* Returns WRAPPER_PROCESS_UP or WRAPPER_PROCESS_DOWN
*/
extern int wrapperGetProcessStatus(TICKS nowTicks, int sigChild);
/**
* Pauses before launching a new JVM if necessary.
*/
extern void wrapperPauseBeforeExecute();
/**
* Launches a JVM process and store it internally
*/
extern void wrapperExecute();
/**
* Returns a tick count that can be used in combination with the
* wrapperGetTickAgeSeconds() function to perform time keeping.
*/
extern TICKS wrapperGetTicks();
/**
* Runs some assertion checks on the tick timer logic.
*/
extern int wrapperTickAssertions();
/**
* Outputs a a log entry describing what the memory dump columns are.
*/
extern void wrapperDumpMemoryBanner();
/**
* Outputs a log entry at regular intervals to track the memory usage of the
* Wrapper and its JVM.
*/
extern void wrapperDumpMemory();
/**
* Outputs a log entry at regular intervals to track the CPU usage over each
* interval for the Wrapper and its JVM.
*/
extern void wrapperDumpCPUUsage();
/******************************************************************************
* Wrapper inner methods.
*****************************************************************************/
/**
* Immediately kill the JVM process and set the JVM state to
* WRAPPER_JSTATE_DOWN.
*/
extern int wrapperKillProcessNow();
/**
* Puts the Wrapper into a state where the JVM will be killed at the soonest
* possible opportunity. It is necessary to wait a moment if a final thread
* dump is to be requested. This call wll always set the JVM state to
* WRAPPER_JSTATE_KILLING.
*/
extern void wrapperKillProcess();
/**
* Launch the wrapper as a console application.
*/
extern int wrapperRunConsole();
/**
* Launch the wrapper as a service application.
*/
extern int wrapperRunService();
/**
* Used to ask the state engine to pause the JVM and Wrapper
*
* @param actionSourceCode Tracks where the action originated.
*/
extern void wrapperPauseProcess(int actionSourceCode);
/**
* Used to ask the state engine to resume the JVM and Wrapper
*
* @param actionSourceCode Tracks where the action originated.
*/
extern void wrapperResumeProcess(int actionSourceCode);
/**
* Detaches the Java process so the Wrapper will if effect forget about it.
*/
extern void wrapperDetachJava();
/**
* Used to ask the state engine to shut down the JVM and Wrapper.
*
* @param exitCode Exit code to use when shutting down.
* @param force True to force the Wrapper to shutdown even if some configuration
* had previously asked that the JVM be restarted. This will reset
* any existing restart requests, but it will still be possible for
* later actions to request a restart.
*/
extern void wrapperStopProcess(int exitCode, int force);
/**
* Used to ask the state engine to shut down the JVM.
*/
extern void wrapperRestartProcess();
/**
* Sends a command off to the JVM asking it to perform a garbage collection sweep.
*
* @param actionSourceCode Tracks where the action originated.
*/
extern void wrapperRequestJVMGC(int actionSourceCode);
/**
* Loops over and strips all double quotes from prop and places the
* stripped version into propStripped.
*
* The exception is double quotes that are preceeded by a backslash
* in this case the backslash is stripped.
*
* If two backslashes are found in a row, then the first escapes the
* second and the second is removed.
*/
extern void wrapperStripQuotes(const TCHAR *prop, TCHAR *propStripped);
/**
* Adds quotes around the specified string in such a way that everything is
* escaped correctly. If the bufferSize is not large enough then the
* required size will be returned. 0 is returned if successful.
*/
extern size_t wrapperQuoteValue(const TCHAR* value, TCHAR *buffer, size_t bufferSize);
/**
* Checks the quotes in the value and displays an error if there are any problems.
* This can be useful to help users debug quote problems.
*/
extern int wrapperCheckQuotes(const TCHAR *value, const TCHAR *propName);
/**
* The main event loop for the wrapper. Handles all state changes and events.
*/
extern void wrapperEventLoop();
extern void wrapperBuildKey();
/**
* Send a signal to the JVM process asking it to dump its JVM state.
*/
extern void wrapperRequestDumpJVMState();
/**
* Build the java command line.
*
* @return TRUE if there were any problems.
*/
extern int wrapperBuildJavaCommand();
/**
* Requests a lock on the tick mutex.
*/
extern int wrapperLockTickMutex();
/**
* Releases a lock on the tick mutex.
*/
extern int wrapperReleaseTickMutex();
/**
* Calculates a tick count using the system time.
*/
extern TICKS wrapperGetSystemTicks();
/**
* Returns difference in seconds between the start and end ticks. This function
* handles cases where the tick counter has wrapped between when the start
* and end tick counts were taken. See the wrapperGetTicks() function.
*/
extern int wrapperGetTickAgeSeconds(TICKS start, TICKS end);
/**
* Returns difference in ticks between the start and end ticks. This function
* handles cases where the tick counter has wrapped between when the start
* and end tick counts were taken. See the wrapperGetTicks() function.
*
* This can be done safely in 32 bits
*/
extern int wrapperGetTickAgeTicks(TICKS start, TICKS end);
/**
* Returns TRUE if the specified tick timeout has expired relative to the
* specified tick count.
*/
extern int wrapperTickExpired(TICKS nowTicks, TICKS timeoutTicks);
/**
* Returns a tick count that is the specified number of seconds later than
* the base tick count.
*/
extern TICKS wrapperAddToTicks(TICKS start, int seconds);
/**
* Sets the working directory of the Wrapper to the specified directory.
* The directory can be relative or absolute.
* If there are any problems then a non-zero value will be returned.
*
* @param dir Directory to change to.
* @param logErrors TRUE if errors should be logged.
*/
extern int wrapperSetWorkingDir(const TCHAR* dir, int logErrors);
/******************************************************************************
* Protocol callback functions
*****************************************************************************/
extern void wrapperLogSignaled(int logLevel, TCHAR *msg);
extern void wrapperKeyRegistered(TCHAR *key);
/**
* Called when a ping is first determined to be slower than the wrapper.ping.alert.threshold.
* This will happen before it has actually been responded to.
*/
extern void wrapperPingSlow();
/**
* Called when a ping is responded to, but was slower than the wrapper.ping.alert.threshold.
*
* @param tickAge The number of seconds it took to respond.
*/
extern void wrapperPingRespondedSlow(int tickAge);
/**
* Called when a ping response is received.
*
* @param pingSendTicks Time in ticks when the ping was originally sent.
* @param queueWarnings TRUE if warnings about the queue should be logged, FALSE if the ping response did not contain a time.
*/
extern void wrapperPingResponded(TICKS pingSendTicks, int queueWarnings);
extern void wrapperPingTimeoutResponded();
extern void wrapperStopRequested(int exitCode);
extern void wrapperRestartRequested();
extern void wrapperStopPendingSignaled(int waitHint);
extern void wrapperStoppedSignaled();
extern void wrapperStartPendingSignaled(int waitHint);
extern void wrapperStartedSignaled();
/******************************************************************************
* Inner types and methods for loading Wrapper configuration.
*****************************************************************************/
/* Callback parameter for loading the file specified by
wrapper.java.additional_file configuration property. */
typedef struct LoadParameterFileCallbackParam LoadParameterFileCallbackParam;
struct LoadParameterFileCallbackParam {
int stripQuote; /* Value of wrapper.java.additional_file.stripquotes property */
TCHAR **strings; /* Array of character strings to which configurations are loaded */
int index; /* Index of a string in `strings' to which a configuration
are copied next */
int isJVMParam; /* Indicates whether the loaded parameters will be JVM parameters */
};
#ifdef CUNIT
extern void testJavaAdditionalParamSuite(void);
#endif /* CUNIT */
#endif
wrapper_3.5.22_src/src/c/wrapper.ico 100644 0 0 61176 12224722007 14561 0 ustar 0 0 ( h h & v 00 h ' 00 .. 00 % <