-
Notifications
You must be signed in to change notification settings - Fork 0
Home
JAppJUp is a project of a Client and Server applications able to download and install updates for some software.
- project consist of Client and Server,
- Server should be created with Spring Framework and Hibernate technologies,
- Client is responsible for connecting to Server, obtaining information about available updates, their download and installation,
- Client should be accessible from tray icon. Its menu should make it possible to install all updates or update-and-run some specified program,
- information about updates is modeled as follows:
- Programs - top level aggregation by programs for which updates are prepared,
- Packages - aggregates specified part of a Program - submodule, library, subprogram etc.,
- Updates - updates for each Package - each has information about whether it's intended for "development" or "release" version, as well as version number and changes description,
- Programs should also have information about known bugs.
This section covers basic setup for building and development. For configuration see Client configuration and Server configuration. For usage see Client usage and Server usage.
Currently source code of AutoUpdater is located at SVN.
Building require presence of Gradle
at version 1.0. Before first build You should make sure that proxy
definition in /build.gradle
is configured properly and that internet
connection is available:
- open build.gradle in Updater's main directory,
- at the beginning of file there will be lines like:
System.properties['http.proxyHost'] = 'something'
System.properties['http.proxyPort'] = 'something'
- if they are commented out, uncomment them and change "something" to the right values of host and port for Your configuration.
Configuration of Servier is located in
/AutoUpdaterServer/src/main/webapp/WEB-INF/classes
.
Hibernate.properties
and JDBC.properties
are used for database
configuration and should be review before building and deploying WAR
file to server. ServerRepoApplication.properties
contains informaton
about places where Updates are stored on server. messages.properties
and ValidationMessages.properties
stores messages displayed in
browser. Before building it for deployment make sure that configuration
files contain proper values.
More details:
- Server configuration - how to configure server, so that WAR file built by Gradle will be ready to be deployed.
All Gradle commands have to be executed in Updater's main directory.
Both Client and Server can be build with gradle build
command. If You
only want to build one of them, use:
-
gradle buildClient
(shortcut for:AutoUpdaterGuiClient:build
) -
gradle buildServer
(shortcut for:AutoUpdaterServer:build
)
respectively.
Results will be stored in /Dist
directory. It should be noted that
currently builder only creates .jar files (for Client) and WAR file (for
Server). While WAR file can be immediately deployed to any J2EE server
(e.g. Tomcat via its AppManager), Client is only a runnable JAR.
For ensuring that Client can be run without heavy reliance on Java
installation, it can be wrapped with
launch4j. Prepared configuration is
available in /Misc/Launch4j
directory - it contains configuration for
Client.jar -> Client.exe
and Installer.jar -> Installer.exe
, as well
as manifest and icon. They should be edited to run executable JARs with
portable JRE
stored in ./jre
directory. Launch4j configuration can be edited via
executable provided with launch4j package.
In future prepared Client instance can be distributed with Inno Setup installer.
More details:
To import projects to Eclipse, run gradle eclipse
task, and then
import all projects into workspace. Settings used during development can
be found in /Misc/EclipseSettings
:
- build projects for Eclipse with
gradle eclipse
, - open Eclipse and select option "import existing projects into workspace",
- if You feel like it, create "Client" and "Server" working sets and place projects there accordingly,
- select option "import preferences" and import preferences from
/Misc/EclipseSettings/settings.ebf
.
Notice that sometimes there might appear empty warning - it can be ignored, as it Eclipse validator error.
Tests can be found inside /test/unit
or /test/functional
directories
of a project, and have "Test" word asa class name prefix. They use
JUnit4 as well as Mockito and FESTAssertions libraries.
To run test we can simply use default Eclipse configuration ("Run
as/JUnit Test"), or make use of Gradle. Command gradle test
runs all
tests, while gradle :ProjectName:test
only tests for a specified
project.
More details:
By default all building commands (gradle build
, gradle buildClient
,
gradle buildServer
) runs tests. To build everything without testing
You should use gradle build -x test
.
Unfortunately not everything is yet covered by tests.
!!! Important !!! While testing application
from under Eclipse in settings.xml
we should change path to
Installer.exe
to absolute path. Since path are resolved in relation to
current position of a Client.exe
when project is run from Eclipse it
will fail to find it in the same directory as *.class
binaries.
Setting path to absolute will solve that problem. In release version
though path should be set back to relative (.
) to ensure that no
matter where Updater will be placed, it will manage to find
Installer.exe
.
Same as with building these commands have to be executed in Updater's main directory:
-
gradle tasks
- displays task that we can build for Updater, -
gradle tasks --all
- displays all task - including task per project (e.g.AutoUpdaterServer:test
), -
gradle javadoc
- generates documentation basing on Javadoc block comments (besides GUI project, majority of classes and methods is documented), -
gradle dependencies
- displays dependencies. While root project doesn't have any,gradle :ProjectName:dependencies
shows all required libraries and projects.
This section covers only configuration of a Client. For building see Building project. For usage see Client usage.
Client's settings are stored in AutoUpdater
withing local AppData
directory (e.g. user_directory/AppData/Local/AutoUpdater
on Windows
7). Information is divided into to files:
-
settings.xml
- containing information about Proxy, location of Installer.exe, and programs that will be updated, -
installationData.xml
- contains information about current installations: what packages are installed for each of programs defined insettings.xml
, and what are their versions.
settings.xml
is created during startup of program if program cannot
find it, while installationData.xml
after first successful
installation (after each successful installation information in file is
updated).
Simple editor of settings can be started with Client.exe --config
command, though its currently very simple, as it can only add new
program (neither edition nor deletion works). One might also try to edit
settings.xml
manually, though it's not recommended.
Prepared settings.xml
can be initiated by some installer to ensure
that end user wouldn't need to enter data manually.
<?xml version="1.0" encoding="UTF-8"?>
<configuration> <!-- (1) -->
<client <!-- (2) -->
name="AutoUpdater" <!-- (3) -->
executable="Client.jar"> <!-- (4) -->
<locations <!-- (5) -->
clientDir="." <!-- (6) -->
console="java -jar .\Client.jar" <!-- (7) -->
installer=".\Installer.exe" /> <!-- (8) -->
</client>
<programs> <!-- (9) -->
<program <!-- (10) -->
name="Program_9_2" <!-- (11) -->
executableName="C:\Program Files (x86)\Nokia Siemens Networks\Program\9.2\Program.exe" <!-- (12) -->
programDir="C:\Program Files (x86)\Nokia Siemens Networks\Program\9.2" <!-- (13) -->
console=""C:\Program Files (x86)\Nokia Siemens Networks\Program\9.2\Program.exe"" <!-- (14) -->
serverURL="http://10.154.46.119:8080/Program_repo" <!-- (15) -->
developmentVersion="false" /> <!-- (16) -->
</programs>
</configuration>
- (1) configuration is root of a
settings.xml
file. It contains two direct descendants: (2) client and (9) programs,- (2) client contains general information about update process
and the updater itself. It doesn't have any information
program-specific,
- (3) name was intended to contains Client's name recognized on repository. It would have been during update of the program itself, but that functionality wasn't introduced yet. Currently it isn't used anywhere besides tests,
- (4) executable was intended to contain name by which spawned process would kill Updater via JSDPU. Same situation as above,
- (5) locations stores information about some locations
used by updater,
- (6) clientDir stores information about
relative/absolute path to the client directory. By
default it point to
.
(current directory), but for test purpose it can be hardcoded to point at some specific directory, - (7) console contains information about command that can be used to startup Client after it was updated. Same as (2) and (3),
- (8) installer points to location of the
Installer.jar/Installer.exe file. During normal use it
can be simply set to
.
, but for test purpose (running Updater under Eclipse) it should point to absolute location of an existing Installer.exe, since it cannot resolve its location another way,
- (6) clientDir stores information about
relative/absolute path to the client directory. By
default it point to
- (9) programs contain information specific to each managed
program,
- (10) program node with contains all settings for a
single program,
- (11) name stores program's name identified by server,
- (12) executableName stores location of a program, that can be used during its termination by JSDPU (substring inside initialization command of a process that we intend to terminate. Exact executable name is usually enough to identify process, and differ it from other processes with the same name.exe),
- (13) programDir contains absolute path to a program. All relative paths during update will be calculated in relation to this directory,
- (14) console contains exact command that would be
typed to console to startup program, including arguments
and/or launchers. It should be noted that if some part
of that command would have to be wrapped in quotation
marks (e.g. path to program containing spaces), it has
to be wrapped here as well (
&quot;
for XML), - (15) serverURL address of a repository from which information and updates should be obtained. Since used procedures cannot resolve redirecting there should be typed final URL and not shortened,
- (16) developmentVersion if true updates should be downloaded for "development version", if "false" they will be obtained for "release version".
- (10) program node with contains all settings for a
single program,
- (2) client contains general information about update process
and the updater itself. It doesn't have any information
program-specific,
<?xml version="1.0" encoding="UTF-8"?>
<installed> <!-- (1) -->
<program <!-- (2) -->
name="Program_trunk" <!-- (3) -->
pathToDirectory="C:\Program Files (x86)\Nokia Siemens Networks\Program\trunk" <!-- (4) -->
serverAddress="http://10.154.46.119:8080/Program_repo"> <!-- (5) -->
<package <!-- (6) -->
name="Installation" <!-- (7) -->
version="9.2.4.10317" /> <!-- (8) -->
</program>
</installed>
- (1) installed is a root containing all programs that have
installed at least one package,
- (2) program contains information about installed packages
for a specified program,
- (3) name contains program name on server - first of 3
properties uniquely identifying program for Updater. Has to
match program/name property in
settings.xml
, - (4) pathToDirectory contains path to program's directory
- second of 3 properties uniquely identifying program for
Updater. Has to match program/programDir property in
settings.xml
,
- second of 3 properties uniquely identifying program for
Updater. Has to match program/programDir property in
- (5) serverAddress contains address of a program's
repository - third of 3 properties uniquely identifying
program for Updater. Has to match program/serverURL
property in
settings.xml
, - (6) package contains information about single package of
a program,
- (7) name contains name of an installed package. Has to match package name on server,
- (8) version contains version number of current installation of a package.
- (3) name contains program name on server - first of 3
properties uniquely identifying program for Updater. Has to
match program/name property in
- (2) program contains information about installed packages
for a specified program,
Notice that program's name, installation directory and repository uniquely identify program. It means that:
- at the same directory we CAN keep 2 installations from 2 different repositories or with 2 different name on 1 repository (e.g. one providing main app, while the other plugins),
- we CAN keep several installations of the same program (e.g. one being development while the other being release version),
- we CANNOT have installed development and release version of the same program in one directory.
This section covers only configuration of a Server. For building see Building project. For installation and usage see Server usage.
Servers configuration is stored within src/main/webapp/WEB-INF/classes
directory:
- repository-specific properties not used by dependent libraries:
-
ServerRepoApplication.properties
- contains settings mostly related to storing Updates on disc and mapping of resources used by site (e.g. CSS and JS files),
-
- properties used by libraries managing DB connection and ORM:
-
JDBC.properties
- contains settings related to handling connection to DB by JDBC drivers, -
Hibernate.properties
- contains settings related to Hibernate (logging, event handling),
-
- messages used for displaying information to user:
-
messages.properties
- contains messages displayed to used, that are obtained by thei identifier, -
ValidationMessages.properties
- contains messages resolved and displayed by Spring validators,
-
- logging:
-
log4j.properties
- contains settings about loggins used by different packages.
-
# Resources properties
# Address to which resources should be mapped
resources.mapping=/resources/** # (1)
# Locations where resources should be searched
resources.locations=/resources/ # (2)
# Cache period of resources
resources.cachePeriod=10000 # (3)
# Storage properties
# Mapping of directory storing uploaded files
# Available prefixes:
# "home:" => System.getProperty("user.home")
# "run:" => System.getProperty("user.dir")
storage.mapping=C:\\UploadStorage # (4)
# MulitpartResolver properties
# Maximal size of uploaded file in bytes
multipartResolver.maxUploadSize=268435456 # (5)
- (1)
resources.mapping
defines which URIs should be mapped to local resources. It shouldn't be changed, - (2)
resources.locations
defines local directories containing mapped resources. It shouldn't be changed, - (3)
resources.cachePeriod
defines length of a cache period for resources, - (4)
storage.mapping
defines local directory that will store updates. After migration to another server, content of this folder should be copied and mapping updated to a new location, - (5)
multipartResolver.maxUploadSize
maximal allowed size of file. Anything above that will result in failure.
# Defines driver used by JDBC
jdbc.driver=org.postgresql.Driver # (1)
# Defines URL connectiong to DB, usually jdbc:dbtype://address/schemaname
jdbc.url=jdbc:postgresql://localhost:5432/updater # (2)
# Defines username and password of an user connecting to DB
jdbc.user=[DB username] # (3)
jdbc.password=[DB password] # (4)
- (1)
jdbc.driver
full name of a driver used to connecting to DB, - (2)
jdbc.url
URL in JDBC format (jdbc:[DB type]://[server address]/[name of schema in DB]
), - (3)
jdbc.user
contains username used during connection to DB, - (4)
jdbc.password
contains password used during connection to DB.
# Hibernate properties
# Defines drivers used to connect to DB
hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect # (1)
# Defines whether or not update DB on SessionFactory creation,
# Possible values:
# - validate - validates the schema of DB,
# - update - updates the schema of existing DB,
# - create - destroys old and creates new schema,
# - create-drop - drop schema at the end of session,
hibernate.hbm2ddl.auto=update # (2)
# Defines BLOB treating in Hibernate
hibernate.jdbc.use_streams_for_binary=true # (3)
hibernate.connection.SetBigStringTryClob=true # (4)
# Maximal allowed JDBC batches
hibernate.jdbc.batch_size=0 # (5)
# Defines options regarding logging
hibernate.show_sql=true # (6)
hibernate.format_sql=true # (7)
hibernate.use_sql_comments=true # (8)
# Javax Persistance properties
# Defines validation mode
javax.persistence.validation.mode=NONE # (9)
- (1)
hibernate.dialect
defines dialect used by Hibernate to communicate with DB. It has to be checked after each change of DB, - (2)
hibernate.hbm2ddl.auto
defines behavior on SessionFactory creation - it can be used to ensure that DB schema match mapping defined by model, - (3)
hibernate.jdbc.use_streams_for_binary
whether to use streams while uploading binary data to DB, - (4)
hibernate.connection.SetBigStringTryClob
whether use CLOB to handle big streams, - (5)
hibernate.jdbc.batch_size
defined the batch size. It is used to merge several queries into one to improve performance, - (6)
hibernate.show_sql
whether or not show SQL in logs (it is safe since dump omits values used to parametrize query), - (7)
hibernate.format_sql
whether SQL dump should be formatted to be more readable, - (8)
hibernate.use_sql_comments
whether SQL dumps should have comments, - (9)
javax.persistence.validation.mode
- Spring Framework binding provides model validation. Since they aren't modified after receiving from user it is not needed to validate them again. Hibernate 4.1 doesn't have event listeners that would have been used to initiate services injected into validators, so in case validator has to connect to DB, action would result in NullPointerException when attempting to use uninitialized service (Checking with DB is the only way to ensure uniqueness of some field without handling runtime SQLException).
Messages are obtained by their ID via
<spring:message code="message_id" />
from messages.properties
.
Validators use their own properties file ValidationMessages.properies
.
They are obtained via constraint annotations, by message()
property:
String message() default "{name_of_validation_message}";
.
See log4j.properties
to obtain more information (it is nicely
documented were necessary).
This section covers actual usage of the Client. For building see Building project. For configuration see Client configuration.
After building in directory /Dist/Client
we have several JAR files
(each for one project) and ./libraries
catalog containing required
dependencies.
File Client.jar contains manifest.mf
that makes it possible to use it
as a runnable JAR. Since some of System
properties depend on place from which we startup VM, it is required to
either run in directly from directory, or ensure that shourtcut has
"Start in" path same to directory containing Updater. If we start
program from command line it is javaw -jar Client.jar
(if we use
"java" instead of "javaw" console window appear besides GUI window).
launch4j make it possible to set up current directory to the JAR's one, and then it can be run safely from any location.
Right after startup client will appear in tray as a blue icon. Single left click will open Updater's management window, while single right click open tray menu.
From tray menu we are able to update-and-start one of programs defined
in settings.xml
, fetch update information again, or start/cancel all
available updates installation.
Inside management window we can fetch updates information, start/cancel installation of all updates and check current status of each managed program by selecting tab with its name (first two tabs though are used to manage Updater).
Each program's tab make it possible to check:
- version number of each package,
- changelogs,
- known bugs.
Logging is managed by properties client.logger.properties
and
installer.logger.properties
. There level of logging can be defined as
in net.jsdpu.logger.Level
for each class/package.
Results will be written to client.log
and installer.log
.
This section covers actual usage of the Server. For building see Building project. For configuration see Server configuration.
!!! Notice !!! - IE in compatibility mode messes up with page's CSS - make sure to disable it for repository, if You browse it with IE.
- check what kind of DB is used, its location, schema, and credentials of the that will connect to it,
- if necessary modify
JDBC.properties
andHibernate.properties
accordingly, - select directory that will store updates on server and set it
ServerRepoApplication.properties
, - build WAR with
gradle buildServer
(run command in Updater's main directory), - deploy it to the server,
- in Tomcat's case open server's main page,
- select "Manage app" and log in,
- undeploy
/Program_repo
if it is there, - deploy
Program_repo.war
by form below - make sure that WAR has exactly that name, since Tomcat doesn't allow to specify name of subsite deployed by file, other way that by WAR's name,
- application should initiate existing DB schema with required tables,
- since at least 1 administrator is required to manage it, we need to
initiate tables with one. Authentication manager uses BCrypt, so we
need to ensure that password is in supported format - it can be done
with help of
AutoUpdaterServer/sql
files - they initiate all the tables, but we can easily extract the part that only creates "root" user, - check if You can log with default credentials ([root], [password]),
- change password to something else. Link to the form can be found on the top bar.
Logged user can manage repository according to his privileges:
- user without any can view projects, known bugs, packages and updates; he can download updates; he cannot display other users list,
- user with "Admin" privilege can display and manage other users - create and delete them, and change their privileges; he cannot though change password of other users,
- user with "Repo Admin" privilege can add, edit and delete programs, known bugs, packages and updates.
Not logged users can use quick file upload form. It makes possible to:
- check credentials,
- check privileges,
- validate all data, in one go. It is required though that program and package for which we are adding update exists, update cannot be already added to repository and user must exist and have privileged to add update.
It is used by script /Misc/PythonUploadScript/uploader.py
as a public
upload API.
- refactoring and improvement of JSDPU library,
- replacing manual parsing of XML with Jaxb schemes,
- moving hardcoded messages into properties,
- more clean notifications,
- replacing of custom logger with log4j or similar,
- improvement of interface in repository.
- Updater runs program as child process, resulting in VM waiting with exit to ending all programs started by it. Since only one instance of Updater is allowed, it results in not being able to run Updater after closing it, till all its children are terminated. Possible solution would be to find a way to run programs as detached processes.