Ron and Ella Wiki Page

Extremely Serious

Page 22 of 29

Configuring Tomcat 7 Package in Synology Diskstation

  1. Install Tomcat 7 package.
  2. Edit the following file:
    /volume1/@appstore/Tomcat7/src/conf/tomcat-users.xml
  3. Add the following entries:
    <role rolename="manager-gui"/>
    <user username="admin" password="<PASSWORD_HERE>" roles="manager-gui"/>

    Note: Update the token <PASSWORD_HERE> appropriately.

  4. Access the manager-gui using the following address format:
    http://<DISKSTATION_HOST_IP>:7070/manager/html

    Note: Update the token <DISKSTATION_HOST_IP> with the IP of your Synology Diskstation.

Using JShell for testing an API

Java 9 was released and JShell (i.e. The REPL of Java) is now real and we can use this to test an API.

For example if we want to check the reverse function StringUtils from the commons-lang3-3.1.jar.
1.) Using windows terminal (i.e. cmd command).
2.) From this directory execute to following command jshell command.
jshell --class-path .\commons-lang3-3.1.jar
Expect to see something similar to the following:
Welcome to JShell -- Version 9.0.1
For an introduction type: /help intro

jshell>
3.) From the jshell prompt import the class org.apache.commons.lang3.StringUtils just like we normally do in java and then press enter.
e.g.
jshell> import org.apache.commons.lang3.StringUtils
4.) To optionally check all the imported classes on the current jshell session we can use /imports command.
e.g.
jshell> /imports
The sample output would be:
|    import java.io.*
|    import java.math.*
|    import java.net.*
|    import java.nio.file.*
|    import java.util.*
|    import java.util.concurrent.*
|    import java.util.function.*
|    import java.util.prefs.*
|    import java.util.regex.*
|    import java.util.stream.*
|    import org.apache.commons.lang3.StringUtils
5.) Since we know that the StringUtils class was already loaded. We can now execute its reverse function.
e.g.
jshell> StringUtils.reverse("abcde")
The output must be:
$2 ==> "edcba"
Note: if you want to exit jshell execute the /exit command.

Enable Windows Subsystem for Linux (WSL) and Install Linux Distribution

If you want to install any Linux distributions for WSL ensure that the Microsoft-Windows-Subsystem-Linux optional feature is enabled using the following procedure:

  1. Open a PowerShell as Administrator and run the following (i.e. if it is not installed):
    Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux
  2. Restart the computer when prompted.
  3. Open the Microsoft Store
  4. Search for the Linux distribution (e.g. Ubuntu) you like.
  5. Click it and the click the Install button.
  6. After finishing the installation search for it in the Start menu.

    Usually the newly installed application is at the top of the start menu.

Pushing files with More than 1MB in Size via HTTP in Git

For some reason, you have files with more than 1MB in total size to push to git respository by HTTP. You might be surprised that you cannot do it. This is because by default, git only posts to remote server via HTTP protocol with a maximum of 1MB. To remedy this, increase the http.postBuffer to 500MB (i.e. if you have to send files with 500MB total size) on client side like the following:

git config --global http.postBuffer 524288000

Reference

https://mirrors.edge.kernel.org/pub/software/scm/git/docs/git-config.html

Capturing the Output of a Command to a Variable

Use the following for statement syntax with /f option

FOR /F ["options"] %variable IN (file-set) DO command [command-parameters]
FOR /F ["options"] %variable IN ("string") DO command [command-parameters]
FOR /F ["options"] %variable IN ('command') DO command [command-parameters]

    or, if usebackq option present:

FOR /F ["options"] %variable IN (file-set) DO command [command-parameters]
FOR /F ["options"] %variable IN ('string') DO command [command-parameters]
FOR /F ["options"] %variable IN (`command`) DO command [command-parameters]

    file-set is one or more file names.  Each file is opened, read
    and processed before going on to the next file in file-set.
    Processing consists of reading in the file, breaking it up into
    individual lines of text and then parsing each line into zero or
    more tokens.  The body of the for loop is then called with the
    variable value(s) set to the found token string(s).  By default, /F
    passes the first blank separated token from each line of each file.
    Blank lines are skipped.  You can override the default parsing
    behavior by specifying the optional "options" parameter.  This
    is a quoted string which contains one or more keywords to specify
    different parsing options.  The keywords are:

        eol=c           - specifies an end of line comment character
                          (just one)
        skip=n          - specifies the number of lines to skip at the
                          beginning of the file.
        delims=xxx      - specifies a delimiter set.  This replaces the
                          default delimiter set of space and tab.
        tokens=x,y,m-n  - specifies which tokens from each line are to
                          be passed to the for body for each iteration.
                          This will cause additional variable names to
                          be allocated.  The m-n form is a range,
                          specifying the mth through the nth tokens.  If
                          the last character in the tokens= string is an
                          asterisk, then an additional variable is
                          allocated and receives the remaining text on
                          the line after the last token parsed.
        usebackq        - specifies that the new semantics are in force,
                          where a back quoted string is executed as a
                          command and a single quoted string is a
                          literal string command and allows the use of
                          double quotes to quote file names in
                          file-set.

For a very basic example, lets capture the result of the echo test to a variable. This can be done as follows:

for /f %I in ('echo test') do set OUTPUT="%~I"

Note: The echo test command here could be any executable command (e.g. executing a different batch or any executable file).

Reading a Batch Variable without the Quotes

Read a Batch Argument without the Quotes

This can be done by inserting a tilde (i.e. ~) character between the percent character and the corresponding argument position. 

For example for argument position 1 we can access it as the following:

%~1

Read a Batch Variable without the Quotes

This can be done with the following syntax:

%<VARIABLE_NAME>:"=%

Note: This is just using the replacement syntax as follows:

%<VARIABLE_NAME>:<FIND>=<REPLACE>%

Basic log4j.properties for console and file output

# Root logger option
log4j.rootLogger=INFO, file, stdout

# Console output
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%m%n

# File output
log4j.appender.file=org.apache.log4j.RollingFileAppender
log4j.appender.file.File=./logs/logging.log
log4j.appender.file.MaxFileSize=10MB
log4j.appender.file.MaxBackupIndex=10
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%t - %m%n

Using Map to Code Conditionally without using the If statement

Preface

The following is an example of conditional programming using the key of the map as the condition and the value is the logic to be executed when a particular key was satisfied.

uses java.util.LinkedHashMap

var mainLogicIfRegistry : LinkedHashMap<block(___param : int) : boolean, block()>
 = {
  \ ___param : int -> 1 == ___param -> \ -> {print("one-0")},
  \ ___param : int -> 1 == ___param -> \ -> {print("one-1")},
  \ ___param : int -> 2 == ___param -> \ -> {print("two")},
  \ ___param : int -> 3 == ___param -> \ -> {print("three")}
}

(1..4).each(\ ___idx -> 
  mainLogicIfRegistry.Keys.where(\ ___cond -> ___cond(___idx))
    .each(\ ___key -> mainLogicIfRegistry.get(___key)())
)

We are using a LinkedHashMap in the example to make the execution based on the order of entries the logic were added in the map. If we are not that concern about the order of logic we can just use a regular map (i.e. HashMap).

Inspecting the First Entry in the Map

Let's see how the following first logic was registered in the map.

\ ___param : int -> 1 == ___param -> \ -> {print("one-0")}

The key part of the entry here is the following:

\ ___param : int -> 1 == ___param

The value part of the entry here is the following:

\ -> {print("one-0")}

As we can see both the key and value are lambda expressions and we can repeat the same lambda expression (i.e. but must be different instances) as the key (i.e. as long as you instantiate them separately) since those two are different instances of a block. Knowing this, we can filter the map based on the key (i.e. condition logic) and if it returns true use that key instance to retrieve the value (i.e. logic to execute) from the map.

Note: The lambda expression on the keys must have the same argument signatures. Because the key of the map must be of a consistent type.

Lets interpret the key part, all the lambda expressions of the key requires a parameter (i.e. for consistency of the block instance generated from the lambda expression). So it has one, and is being used to compare to 1. Actually both the first and second entries has the same lambda implementation but with different instances of block. Thus, when we pass in 1, both the first and the second entries will be executed.

Now for the value part, it is just printing the string one-0. To distinguish this from the second entry (i.e. since both the first and second entries has the same lambda expression), the second entry prints the string one-1.

Executing the Entries in the Map

Execute a particular entries using the following statement:

mainLogicIfRegistry.Keys.where(\ ___cond -> ___cond(___idx)).each(\ ___key -> mainLogicIfRegistry.get(___key)())

Lets dissect the statement above. We filter the key by executing the logic in the key like the following (i.e. ___idx is a argument of the lambda expression):

mainLogicIfRegistry.Keys.where(\ ___cond -> ___cond(___idx))

Once all the targeted keys were found execute each one like the following:

.each(\ ___key -> mainLogicIfRegistry.get(___key)())

If we execute the code from the preface it will be like this:

one-0
one-1
two
three

As we can see, both the 1 were executed (i.e. one-0 and one-1) followed by the 2 and 3. And since there's no entry for the 4 nothing was executed for it.

« Older posts Newer posts »