Tomcat: подключение внешнего файла в конфигурацию server.xml

By | 06/03/2014
 

apache-tomcat-7-logoЗадача – иметь возможность подключить дополнительную конфигурацию в файл server.xml сервера Tomcat.

Так как сам файл конфигурации server.xml является простым XML-файлом, то и выполнять это мы будем с помощью XML entity includes.

В начале файла добавляем строки:

<!DOCTYPE server [
<!ENTITY jdbcrealm SYSTEM "jdbcrealm.xml">
]>

Путь к файлу можно указывать как относительно самого файла server.xml – так и от корня файловой системы, например:

<!ENTITY jdbcrealm SYSTEM "/home/user/APP/app-install/conf/jdbcrealm.xml">

Файл jdbcrealm.xml просто описывает realm подключения к базе OracleTomcat: аутентификация пользователей с помощью JDBCRealm и MySQL или Oracle, его содержимое в данном примере такое:

<Realm
  className="org.apache.catalina.realm.JDBCRealm" driverName="oracle.jdbc.driver.OracleDriver" connectionURL="jdbc:oracle:thin:@oraclehost:1521:schemename" connectionName="DBusername" connectionPassword="DBuserpass" userTable="tmc_users_set" userNameCol="user_name" userCredCol="user_pass" userRoleTable="user_roles_set" roleNameCol="role_name" />

Далее, в нужном месте, вставляем вызов этого файла:

&jdbcrealm;

Полностью файл server.xml выглядит так:

<!DOCTYPE server [
<!ENTITY jdbcrealm SYSTEM "/home/user/APP/app-install/conf/jdbcrealm.xml">
]>

<Server port="${port.shutdown}" shutdown="SHUTDOWN">
  <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
  <Listener className="org.apache.catalina.core.JasperListener" />
  <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
  <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
  <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />

  <Service name="APP">

    <Connector
      port="${port.http}"
      protocol="HTTP/1.1"
      connectionTimeout="20000"
      redirectPort="${port.https}"
    />

    <Connector
      port="${port.https}" protocol="HTTP/1.1"
      maxThreads="200" SSLEnabled="true" scheme="https" secure="true" debug="0"
      clientAuth="want" sslProtocol="TLS"
      keystoreFile="/home/user/APP/app-install/conf/ssl/tomca7.jks"
      keyAlias="tomcat7"
      keystorePass="password"
      truststoreFile="/home/user/APP/app-server/conf/.ssl/trustcacerts.jks"
      truststorePass="password"
    />

    <Engine
      name="APP-UI"
      defaultHost="localhost">

    &jdbcrealm;

        <Host
          name="localhost"
          appBase="${appbase}"
          unpackWARs="false"
          autoDeploy="false"
          deployOnStartup="false">

          <Context
            path=""
            docBase="app-application"
          />

          <Valve
            className="org.apache.catalina.valves.AccessLogValve"
            directory="logs"
            prefix="localhost_access_log."
            suffix=".txt"
            pattern="%h %l %u %t &quot;%r&quot; %s %b"
          />

        </Host>
    </Engine>
  </Service>
</Server>

Зачем это нужно? Пример использования на реальном приложении.

В зависимости от сервера, на котором запускается приложение, необходимо задавать различные сервера для аутентификации. Можно было бы использовать вариант с переменными и опциями $CATALINA_OPTS из статьи Tomcat: трюки — использование переменных в server.xml – но передавать пароли, хоть и зашифрованные, в аргументах, которые будут видны в выводе process status – не лучшая идея.

Потому – было добавлено несколько файлов для включения в server.xml:

$ ls -l conf/ | grep jdbc
-rw-rw-r-- 1 user user  441 Jun  2 14:32 jdbcrealm-DEV.xml
-rw-rw-r-- 1 user user  441 Jun  2 14:32 jdbcrealm-KIEV_DEV.xml
-rw-rw-r-- 1 user user  441 Jun  2 14:32 jdbcrealm-UAT.xml
-rw-rw-r-- 1 user user  441 Jun  2 13:35 jdbcrealm.xml

Далее – простой скрипт, который создаёт нужный файл при запуске, в зависимости от системной переменной $ENV:

$ cat bin/create_jdbc_conf.sh
#!/usr/bin/env bash

replace () {

echo -e "nWorking on $ENV box."

local FILE="$1"
local FILETOCOPY="$2"
local CONF="$3"

if [ -e $CONF ]; then
  echo -e "nOld $FILE found;"
  rm $CONF && echo -e "Old $FILE deleted." || echo -e "ERROR: can't delete old file $CONF!n"
fi

echo -e "nCopyiyng new $FILE - $FILETOCOPY;"
cp $FILETOCOPY $CONF && echo "New $FILE copied: " || echo -e n"ERROR - can't copy new file $FILETOCOPY to $CONF!n"
file $CONF
echo
}

replace "jdbcrealm.xml" "$APP_INSTALL/conf/jdbcrealm-$ENV.xml" "$APP_INSTALL/conf/jdbcrealm.xml";

И его выполнение:

$ ./bin/create_jdbc_conf.sh

Working on KIEV_DEV box.

Old jdbcrealm.xml found;
Old jdbcrealm.xml deleted.

Copyiyng new jdbcrealm.xml - /home/user/APP/app-install/conf/jdbcrealm-KIEV_DEV.xml;
New jdbcrealm.xml copied:
/home/user/APP/app-install/conf/jdbcrealm.xml: ASCII text

И при каждом запуске Tomcat – вызываем этот скрипт из startup.sh:

$ cat bin/startup.sh | grep jdbc
source $APP_INSTALL/bin/create_jdbc_conf.sh

Его выполнение:

$ ./bin/startup.sh

Working on KIEV_DEV box.

Old jdbcrealm.xml found;
Old jdbcrealm.xml deleted.

Copyiyng new jdbcrealm.xml - /home/user/APP/app-install/conf/jdbcrealm-KIEV_DEV.xml;
New jdbcrealm.xml copied:
/home/user/APP/app-install/conf/jdbcrealm.xml: ASCII text

Using CATALINA_BASE:   /home/user/APP/app-server
Using CATALINA_HOME:   /home/user/APP/app-server
Using CATALINA_TMPDIR: /home/user/APP/app-server/temp
Using JRE_HOME:        /home/user/APP/Java/jdk1.6.0_45/jre
Using CLASSPATH:       /home/user/APP/app-server/bin/bootstrap.jar:/home/user/APP/app-server/bin/tomcat-juli.jar
Using CATALINA_PID:    /home/user/APP/app-server/conf/catalina.pid
Tomcat started.

“А теперь – со всем этим … на борту мы попробуем взлететь” (с)