Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Como carregar valores dinamicamente no arquivo XML de contexto do Tomcat


Digamos que você tenha um arquivo tomcat/conf/context.xml que se parece com isso:
<?xml version="1.0" encoding="utf-8"?>
<Context>
    <WatchedResource>WEB-INF/web.xml</WatchedResource>
    <Resource 
            name="jdbc/MyDB" 
            auth="Container" 
            type="javax.sql.DataSource" 
            removeAbandoned="true" 
            removeAbandonedTimeout="15" 
            maxActive="5" 
            maxIdle="5" 
            maxWait="7000" 
            username="${db.mydb.uid}"
            password="${db.mydb.pwd}"
            driverClassName="${db.mydb.driver}"
            url="${db.mydb.url}${db.mydb.dbName}?autoReconnectForPools=true&amp;characterEncoding=UTF-8"
            factory="com.mycompany.util.configuration.CustomDataSourceFactory"
            validationQuery="SELECT '1';"
            testOnBorrow="true"/>
</Context>

O que queremos substituir neste caso é qualquer coisa no material ${.*} nesta definição de recurso. Com uma pequena modificação no código abaixo, no entanto, você pode realizar essas substituições em praticamente qualquer critério que desejar.

Observe a linha factory="com.mycompany.util.configuration.CustomDataSourceFactory"

O que isso significa é que o Tomcat tentará usar essa fábrica para processar esse recurso. Deve ser mencionado que isso significa que esta fábrica terá que estar no classpath do Tomcat na inicialização (Pessoalmente, eu coloquei o meu em um JAR no Tomcat lib diretório).

Veja como está minha fábrica:
package com.mycompany.util.configuration;

import java.util.Hashtable;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.naming.Context;
import javax.naming.Name;
import javax.naming.RefAddr;
import javax.naming.Reference;
import javax.naming.StringRefAddr;
import javax.naming.spi.ObjectFactory;
import org.apache.commons.dbcp.BasicDataSourceFactory;

public class CustomDataSourceFactory extends BasicDataSourceFactory implements ObjectFactory {

    private static final Pattern _propRefPattern = Pattern.compile("\\$\\{.*?\\}");

    //http://tomcat.apache.org/tomcat-6.0-doc/jndi-resources-howto.html#Adding_Custom_Resource_Factories
    @Override
    public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable environment) throws Exception {
        if (obj instanceof Reference) {
            Reference ref = (Reference) obj;
            System.out.println("Resolving context reference values dynamically");

            for(int i = 0; i < ref.size(); i++) {
                RefAddr addr = ref.get(i);
                String tag = addr.getType();
                String value = (String) addr.getContent();

                Matcher matcher = _propRefPattern.matcher(value);
                if (matcher.find()) {
                    String resolvedValue = resolve(value);
                    System.out.println("Resolved " + value + " to " + resolvedValue);
                    ref.remove(i);
                    ref.add(i, new StringRefAddr(tag, resolvedValue));
                }
            }
        }
        // Return the customized instance
        return super.getObjectInstance(obj, name, nameCtx, environment);
    }

    private String resolve(String value) {
        //Given the placeholder, do stuff to figure out what it's true value should be, and return that String.
        //This could be decryption, or maybe using a properties file.
    }
}

Então, quando esse código estiver no caminho de classe, reinicie o Tomcat e observe catalina.out para as mensagens de log. NOTA:O System.out.println As instruções provavelmente acabarão imprimindo informações confidenciais em seus logs, portanto, você pode removê-las assim que terminar a depuração.

Em uma nota lateral, escrevi isso porque descobri que muitos exemplos eram muito específicos para um tópico específico (como a utilização de criptografia) e queria mostrar como isso pode ser feito genericamente. Além disso, algumas das outras respostas a essa pergunta não se explicam muito bem, e eu tive que pesquisar para descobrir o que precisava ser feito para que isso funcionasse. Eu queria compartilhar minhas descobertas com vocês. Sinta-se à vontade para comentar sobre isso, fazer perguntas ou fazer correções se encontrar problemas, e com certeza incluirei as correções em minha resposta.