From 4fb9a704ea045dc8f3211173b1e05d6e825d55d8 Mon Sep 17 00:00:00 2001 From: Cleverson Sacramento Date: Thu, 7 Feb 2013 13:13:40 -0300 Subject: [PATCH] Início da implementação do mecanismo completo que possibilita a configuração de diversos bancos de dados --- impl/extension/jdbc/src/main/java/br/gov/frameworkdemoiselle/internal/configuration/JdbcConfig.java | 10 +++++++++- impl/extension/jdbc/src/main/java/br/gov/frameworkdemoiselle/internal/producer/ConnectionProducer.java | 125 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------- impl/extension/jdbc/src/main/java/br/gov/frameworkdemoiselle/internal/producer/DataSourceProducer.java | 119 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------- impl/extension/jdbc/src/main/java/br/gov/frameworkdemoiselle/internal/proxy/ConnectionProxy.java | 239 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ impl/extension/jdbc/src/main/resources/demoiselle-jaas-bundle.properties | 34 ---------------------------------- impl/extension/jdbc/src/main/resources/demoiselle-jdbc-bundle.properties | 42 ++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 502 insertions(+), 67 deletions(-) create mode 100644 impl/extension/jdbc/src/main/java/br/gov/frameworkdemoiselle/internal/proxy/ConnectionProxy.java delete mode 100644 impl/extension/jdbc/src/main/resources/demoiselle-jaas-bundle.properties create mode 100644 impl/extension/jdbc/src/main/resources/demoiselle-jdbc-bundle.properties diff --git a/impl/extension/jdbc/src/main/java/br/gov/frameworkdemoiselle/internal/configuration/JdbcConfig.java b/impl/extension/jdbc/src/main/java/br/gov/frameworkdemoiselle/internal/configuration/JdbcConfig.java index 41f1f28..7fad0b2 100644 --- a/impl/extension/jdbc/src/main/java/br/gov/frameworkdemoiselle/internal/configuration/JdbcConfig.java +++ b/impl/extension/jdbc/src/main/java/br/gov/frameworkdemoiselle/internal/configuration/JdbcConfig.java @@ -42,17 +42,24 @@ import java.util.Map; import br.gov.frameworkdemoiselle.annotation.Name; import br.gov.frameworkdemoiselle.configuration.Configuration; -@Configuration(prefix = "frameworkdemoiselle.jdbc.") +@Configuration(prefix = "frameworkdemoiselle.persistence.") public class JdbcConfig implements Serializable { private static final long serialVersionUID = 1L; + @Name("default.datasource.name") + private String defaultDataDourceName; + @Name("jndi.name") private Map jndiName; @Name("driver.class") private Map driverClass; + public String getDefaultDataDourceName() { + return defaultDataDourceName; + } + public Map getJndiName() { return jndiName; } @@ -60,4 +67,5 @@ public class JdbcConfig implements Serializable { public Map getDriverClass() { return driverClass; } + } diff --git a/impl/extension/jdbc/src/main/java/br/gov/frameworkdemoiselle/internal/producer/ConnectionProducer.java b/impl/extension/jdbc/src/main/java/br/gov/frameworkdemoiselle/internal/producer/ConnectionProducer.java index 8687877..d15fb07 100644 --- a/impl/extension/jdbc/src/main/java/br/gov/frameworkdemoiselle/internal/producer/ConnectionProducer.java +++ b/impl/extension/jdbc/src/main/java/br/gov/frameworkdemoiselle/internal/producer/ConnectionProducer.java @@ -2,42 +2,119 @@ package br.gov.frameworkdemoiselle.internal.producer; import java.io.Serializable; import java.sql.Connection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; import javax.enterprise.context.RequestScoped; +import javax.enterprise.inject.Default; import javax.enterprise.inject.Produces; -import javax.sql.DataSource; +import javax.enterprise.inject.spi.InjectionPoint; +import javax.inject.Inject; -import br.gov.frameworkdemoiselle.configuration.ConfigurationException; -import br.gov.frameworkdemoiselle.util.Beans; +import org.slf4j.Logger; + +import br.gov.frameworkdemoiselle.DemoiselleException; +import br.gov.frameworkdemoiselle.annotation.Name; +import br.gov.frameworkdemoiselle.internal.configuration.JdbcConfig; +import br.gov.frameworkdemoiselle.internal.proxy.ConnectionProxy; +import br.gov.frameworkdemoiselle.util.ResourceBundle; @RequestScoped public class ConnectionProducer implements Serializable { private static final long serialVersionUID = 1L; - private transient Connection connection; + @Inject + private Logger logger; + + @Inject + @Name("demoiselle-jdbc-bundle") + private ResourceBundle bundle; + + private final Map cache = Collections.synchronizedMap(new HashMap()); + + @Inject + private DataSourceProducer producer; + + @PostConstruct + public void init() { + for (String name : producer.getCache().keySet()) { + getConnection(name); + } + } + @Default @Produces - public Connection create() { - if (this.connection == null) { - this.connection = init(); + public Connection create(InjectionPoint ip, JdbcConfig config) { + String name = getName(ip, config); + return new ConnectionProxy(name); + } + + public Connection getConnection(String name) { + Connection result = null; + + if (cache.containsKey(name)) { + result = cache.get(name); + + } else { + try { + result = producer.create(name).getConnection(); + + cache.put(name, result); + this.logger.info(bundle.getString("connection-was-created", name)); + + } catch (Exception cause) { + // TODO Colocar uma mensagem amigável + + throw new DemoiselleException("", cause); + } } - return this.connection; + return result; } - private Connection init() { - Connection result; + private String getName(InjectionPoint ip, JdbcConfig config) { + String result; - try { - DataSource dataSource = Beans.getReference(DataSource.class); - result = dataSource.getConnection(); + if (ip != null && ip.getAnnotated() != null && ip.getAnnotated().isAnnotationPresent(Name.class)) { + // TODO Quando o comando Beans.getReference é usado para simular injeção, não existe + // anotação @Inject então precisamos testar se #getAnnotated() retorna nulo aqui. + result = ip.getAnnotated().getAnnotation(Name.class).value(); - } catch (Exception cause) { - // TODO Colocar uma mensagem amigável + } else { + result = getNameFromProperties(config); - throw new ConfigurationException("", cause); + if (result == null) { + result = getNameFromCache(); + } + } + + return result; + } + + private String getNameFromProperties(JdbcConfig config) { + String result = config.getDefaultDataDourceName(); + + if (result != null) { + this.logger.debug(bundle.getString("getting-default-datasource-name-from-properties", result)); + } + + return result; + } + + private String getNameFromCache() { + String result; + Set names = producer.getCache().keySet(); + + if (names.size() > 1) { + throw new DemoiselleException(bundle.getString("more-than-one-datasource-defined", + Name.class.getSimpleName())); + } else { + result = names.iterator().next(); } return result; @@ -45,22 +122,28 @@ public class ConnectionProducer implements Serializable { @PreDestroy public void close() { - if (this.connection != null) { - + for (Connection connection : cache.values()) { try { - if (this.connection.isClosed()) { + if (connection.isClosed()) { // TODO Logar um warning informando que a conexão já havia sido finalizada. } else { - this.connection.close(); + connection.close(); // TODO Logar um info informando que a conexão foi finalizada. } } catch (Exception cause) { // TODO Colocar uma mensagem amigável - throw new ConfigurationException("", cause); + throw new DemoiselleException("", cause); } } + + cache.clear(); + } + + public Map getCache() { + return cache; } + } diff --git a/impl/extension/jdbc/src/main/java/br/gov/frameworkdemoiselle/internal/producer/DataSourceProducer.java b/impl/extension/jdbc/src/main/java/br/gov/frameworkdemoiselle/internal/producer/DataSourceProducer.java index 598f0fd..49be7b7 100644 --- a/impl/extension/jdbc/src/main/java/br/gov/frameworkdemoiselle/internal/producer/DataSourceProducer.java +++ b/impl/extension/jdbc/src/main/java/br/gov/frameworkdemoiselle/internal/producer/DataSourceProducer.java @@ -1,39 +1,115 @@ package br.gov.frameworkdemoiselle.internal.producer; import java.io.Serializable; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import javax.annotation.PostConstruct; +import javax.annotation.PreDestroy; import javax.enterprise.context.ApplicationScoped; -import javax.enterprise.inject.Produces; +import javax.inject.Inject; import javax.naming.Context; import javax.naming.InitialContext; import javax.sql.DataSource; -import br.gov.frameworkdemoiselle.configuration.ConfigurationException; +import org.slf4j.Logger; + +import br.gov.frameworkdemoiselle.DemoiselleException; +import br.gov.frameworkdemoiselle.annotation.Name; import br.gov.frameworkdemoiselle.internal.configuration.JdbcConfig; import br.gov.frameworkdemoiselle.util.Beans; +import br.gov.frameworkdemoiselle.util.ResourceBundle; @ApplicationScoped public class DataSourceProducer implements Serializable { private static final long serialVersionUID = 1L; - private transient DataSource dataSource; + @Inject + private Logger logger; + + @Inject + @Name("demoiselle-jdbc-bundle") + private ResourceBundle bundle; + + private final Map> cache = Collections + .synchronizedMap(new HashMap>()); + + @PostConstruct + public void loadDataSources() { + ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); + + for (String dataBaseName : getDataSourceNames(contextClassLoader)) { + + try { + create(dataBaseName); + } catch (Throwable t) { + throw new DemoiselleException(t); + } + + logger.debug(bundle.getString("datasource-name-found", dataBaseName)); + } + } + + private Set getDataSourceNames(ClassLoader classLoader) { + Set result = new HashSet(); + + JdbcConfig config = Beans.getReference(JdbcConfig.class); + + if (config.getJndiName() != null) { + result.addAll(config.getJndiName().keySet()); + } + + if (config.getDriverClass() != null) { + result.addAll(config.getDriverClass().keySet()); + } + + if (result.isEmpty()) { + throw new DemoiselleException(bundle.getString("datasource-name-not-found")); + } + + return result; + } + + public DataSource create(String dataSourceName) { + DataSource factory; + + ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); + Map localCache; + + if (cache.containsKey(contextClassLoader)) { + localCache = cache.get(contextClassLoader); + + if (localCache.containsKey(dataSourceName)) { + factory = localCache.get(dataSourceName); + + } else { + factory = initDataSource(dataSourceName); + + localCache.put(dataSourceName, factory); + cache.put(contextClassLoader, localCache); + } + + } else { + localCache = new HashMap(); + factory = initDataSource(dataSourceName); - @Produces - public DataSource create() { - if (this.dataSource == null) { - this.dataSource = init(); + localCache.put(dataSourceName, factory); + cache.put(contextClassLoader, localCache); } - return this.dataSource; + return factory; } - private DataSource init() { + private DataSource initDataSource(String dataSourceName) { DataSource result; try { JdbcConfig config = Beans.getReference(JdbcConfig.class); - String jndi = config.getJndiName().get("default"); + String jndi = config.getJndiName().get(dataSourceName); // TODO Lançar exceção caso o JNDI esteja vazio ou nulo. @@ -43,7 +119,28 @@ public class DataSourceProducer implements Serializable { } catch (Exception cause) { // TODO Colocar uma mensagem amigável - throw new ConfigurationException("", cause); + throw new DemoiselleException("", cause); + } + + return result; + } + + @PreDestroy + public void close() { + cache.clear(); + } + + public Map getCache() { + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + Map result = cache.get(classLoader); + + if (result == null || result.isEmpty()) { + logger.debug(bundle.getString("datasource-not-found-in-cache")); + + for (String name : getDataSourceNames(classLoader)) { + create(name); + result = cache.get(classLoader); + } } return result; diff --git a/impl/extension/jdbc/src/main/java/br/gov/frameworkdemoiselle/internal/proxy/ConnectionProxy.java b/impl/extension/jdbc/src/main/java/br/gov/frameworkdemoiselle/internal/proxy/ConnectionProxy.java new file mode 100644 index 0000000..c645d39 --- /dev/null +++ b/impl/extension/jdbc/src/main/java/br/gov/frameworkdemoiselle/internal/proxy/ConnectionProxy.java @@ -0,0 +1,239 @@ +package br.gov.frameworkdemoiselle.internal.proxy; + +import java.io.Serializable; +import java.sql.Array; +import java.sql.Blob; +import java.sql.CallableStatement; +import java.sql.Clob; +import java.sql.Connection; +import java.sql.DatabaseMetaData; +import java.sql.NClob; +import java.sql.PreparedStatement; +import java.sql.SQLClientInfoException; +import java.sql.SQLException; +import java.sql.SQLWarning; +import java.sql.SQLXML; +import java.sql.Savepoint; +import java.sql.Statement; +import java.sql.Struct; +import java.util.Map; +import java.util.Properties; + +import br.gov.frameworkdemoiselle.internal.producer.ConnectionProducer; +import br.gov.frameworkdemoiselle.util.Beans; + +public class ConnectionProxy implements Connection, Serializable { + + private static final long serialVersionUID = 1L; + + private final String dataSourceName; + + public ConnectionProxy(String dataSourceName) { + this.dataSourceName = dataSourceName; + } + + private Connection getDelegate() { + ConnectionProducer emp = Beans.getReference(ConnectionProducer.class); + return emp.getConnection(this.dataSourceName); + } + + public void clearWarnings() throws SQLException { + getDelegate().clearWarnings(); + } + + public void close() throws SQLException { + getDelegate().close(); + } + + public void commit() throws SQLException { + getDelegate().commit(); + } + + public Array createArrayOf(String typeName, Object[] elements) throws SQLException { + return getDelegate().createArrayOf(typeName, elements); + } + + public Blob createBlob() throws SQLException { + return getDelegate().createBlob(); + } + + public Clob createClob() throws SQLException { + return getDelegate().createClob(); + } + + public NClob createNClob() throws SQLException { + return getDelegate().createNClob(); + } + + public SQLXML createSQLXML() throws SQLException { + return getDelegate().createSQLXML(); + } + + public Statement createStatement() throws SQLException { + return getDelegate().createStatement(); + } + + public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) + throws SQLException { + return getDelegate().createStatement(resultSetType, resultSetConcurrency, resultSetHoldability); + } + + public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException { + return getDelegate().createStatement(resultSetType, resultSetConcurrency); + } + + public Struct createStruct(String typeName, Object[] attributes) throws SQLException { + return getDelegate().createStruct(typeName, attributes); + } + + public boolean getAutoCommit() throws SQLException { + return getDelegate().getAutoCommit(); + } + + public String getCatalog() throws SQLException { + return getDelegate().getCatalog(); + } + + public Properties getClientInfo() throws SQLException { + return getDelegate().getClientInfo(); + } + + public String getClientInfo(String name) throws SQLException { + return getDelegate().getClientInfo(name); + } + + public int getHoldability() throws SQLException { + return getDelegate().getHoldability(); + } + + public DatabaseMetaData getMetaData() throws SQLException { + return getDelegate().getMetaData(); + } + + public int getTransactionIsolation() throws SQLException { + return getDelegate().getTransactionIsolation(); + } + + public Map> getTypeMap() throws SQLException { + return getDelegate().getTypeMap(); + } + + public SQLWarning getWarnings() throws SQLException { + return getDelegate().getWarnings(); + } + + public boolean isClosed() throws SQLException { + return getDelegate().isClosed(); + } + + public boolean isReadOnly() throws SQLException { + return getDelegate().isReadOnly(); + } + + public boolean isValid(int timeout) throws SQLException { + return getDelegate().isValid(timeout); + } + + public boolean isWrapperFor(Class iface) throws SQLException { + return getDelegate().isWrapperFor(iface); + } + + public String nativeSQL(String sql) throws SQLException { + return getDelegate().nativeSQL(sql); + } + + public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, + int resultSetHoldability) throws SQLException { + return getDelegate().prepareCall(sql, resultSetType, resultSetConcurrency, resultSetHoldability); + } + + public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException { + return getDelegate().prepareCall(sql, resultSetType, resultSetConcurrency); + } + + public CallableStatement prepareCall(String sql) throws SQLException { + return getDelegate().prepareCall(sql); + } + + public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, + int resultSetHoldability) throws SQLException { + return getDelegate().prepareStatement(sql, resultSetType, resultSetConcurrency, resultSetHoldability); + } + + public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) + throws SQLException { + return getDelegate().prepareStatement(sql, resultSetType, resultSetConcurrency); + } + + public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException { + return getDelegate().prepareStatement(sql, autoGeneratedKeys); + } + + public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException { + return getDelegate().prepareStatement(sql, columnIndexes); + } + + public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException { + return getDelegate().prepareStatement(sql, columnNames); + } + + public PreparedStatement prepareStatement(String sql) throws SQLException { + return getDelegate().prepareStatement(sql); + } + + public void releaseSavepoint(Savepoint savepoint) throws SQLException { + getDelegate().releaseSavepoint(savepoint); + } + + public void rollback() throws SQLException { + getDelegate().rollback(); + } + + public void rollback(Savepoint savepoint) throws SQLException { + getDelegate().rollback(savepoint); + } + + public void setAutoCommit(boolean autoCommit) throws SQLException { + getDelegate().setAutoCommit(autoCommit); + } + + public void setCatalog(String catalog) throws SQLException { + getDelegate().setCatalog(catalog); + } + + public void setClientInfo(Properties properties) throws SQLClientInfoException { + getDelegate().setClientInfo(properties); + } + + public void setClientInfo(String name, String value) throws SQLClientInfoException { + getDelegate().setClientInfo(name, value); + } + + public void setHoldability(int holdability) throws SQLException { + getDelegate().setHoldability(holdability); + } + + public void setReadOnly(boolean readOnly) throws SQLException { + getDelegate().setReadOnly(readOnly); + } + + public Savepoint setSavepoint() throws SQLException { + return getDelegate().setSavepoint(); + } + + public Savepoint setSavepoint(String name) throws SQLException { + return getDelegate().setSavepoint(name); + } + + public void setTransactionIsolation(int level) throws SQLException { + getDelegate().setTransactionIsolation(level); + } + + public void setTypeMap(Map> map) throws SQLException { + getDelegate().setTypeMap(map); + } + + public T unwrap(Class iface) throws SQLException { + return getDelegate().unwrap(iface); + } +} diff --git a/impl/extension/jdbc/src/main/resources/demoiselle-jaas-bundle.properties b/impl/extension/jdbc/src/main/resources/demoiselle-jaas-bundle.properties deleted file mode 100644 index 3f1fa2e..0000000 --- a/impl/extension/jdbc/src/main/resources/demoiselle-jaas-bundle.properties +++ /dev/null @@ -1,34 +0,0 @@ -# Demoiselle Framework -# Copyright (C) 2010 SERPRO -# ---------------------------------------------------------------------------- -# This file is part of Demoiselle Framework. -# -# Demoiselle Framework is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public License version 3 -# as published by the Free Software Foundation. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License version 3 -# along with this program; if not, see -# or write to the Free Software Foundation, Inc., 51 Franklin Street, -# Fifth Floor, Boston, MA 02110-1301, USA. -# ---------------------------------------------------------------------------- -# Este arquivo é parte do Framework Demoiselle. -# -# O Framework Demoiselle é um software livre; você pode redistribuí-lo e/ou -# modificá-lo dentro dos termos da GNU LGPL versão 3 como publicada pela Fundação -# do Software Livre (FSF). -# -# Este programa é distribuído na esperança que possa ser útil, mas SEM NENHUMA -# GARANTIA; sem uma garantia implícita de ADEQUAÇÃO a qualquer MERCADO ou -# APLICAÇÃO EM PARTICULAR. Veja a Licença Pública Geral GNU/LGPL em português -# para maiores detalhes. -# -# Você deve ter recebido uma cópia da GNU LGPL versão 3, sob o título -# "LICENCA.txt", junto com esse programa. Se não, acesse -# ou escreva para a Fundação do Software Livre (FSF) Inc., -# 51 Franklin St, Fifth Floor, Boston, MA 02111-1301, USA. diff --git a/impl/extension/jdbc/src/main/resources/demoiselle-jdbc-bundle.properties b/impl/extension/jdbc/src/main/resources/demoiselle-jdbc-bundle.properties new file mode 100644 index 0000000..bb91a36 --- /dev/null +++ b/impl/extension/jdbc/src/main/resources/demoiselle-jdbc-bundle.properties @@ -0,0 +1,42 @@ +# Demoiselle Framework +# Copyright (C) 2010 SERPRO +# ---------------------------------------------------------------------------- +# This file is part of Demoiselle Framework. +# +# Demoiselle Framework is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License version 3 +# as published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License version 3 +# along with this program; if not, see +# or write to the Free Software Foundation, Inc., 51 Franklin Street, +# Fifth Floor, Boston, MA 02110-1301, USA. +# ---------------------------------------------------------------------------- +# Este arquivo é parte do Framework Demoiselle. +# +# O Framework Demoiselle é um software livre; você pode redistribuí-lo e/ou +# modificá-lo dentro dos termos da GNU LGPL versão 3 como publicada pela Fundação +# do Software Livre (FSF). +# +# Este programa é distribuído na esperança que possa ser útil, mas SEM NENHUMA +# GARANTIA; sem uma garantia implícita de ADEQUAÇÃO a qualquer MERCADO ou +# APLICAÇÃO EM PARTICULAR. Veja a Licença Pública Geral GNU/LGPL em português +# para maiores detalhes. +# +# Você deve ter recebido uma cópia da GNU LGPL versão 3, sob o título +# "LICENCA.txt", junto com esse programa. Se não, acesse +# ou escreva para a Fundação do Software Livre (FSF) Inc., +# 51 Franklin St, Fifth Floor, Boston, MA 02111-1301, USA. + +more-than-one-datasource-defined=Existe mais de um banco de dados definido. Utilize @{0} no ponto de inje\u00E7\u00E3o ou defina o atributo "frameworkdemoiselle.persistence.default.datasource.name" no arquivo demoiselle.properties. +getting-default-datasource-name-from-properties=Obtendo a configura\u00E7\u00E3o de banco de dados padr\u00E3o "{0}" a partir do arquivo de configura\u00E7\u00E3o demoiselle.properties. +datasource-name-found=Configura\u00E7\u00E3o de banco de dados "{0}" encontrada. +persistence-unit-name-found=Configura\u00E7\u00E3o do banco de dados "{0}" encontrada. +datasource-not-found-in-cache=DataSource n\u00E3o encontrado para contexto atual, criando um agora. +connection-was-created=Conex\u00E3o criada a partir da configura\u00E7\u00E3o "{0}". +datasource-name-not-found=Nenhuma configura\u00E7\u00E3o de banco de dados foi encontrada no "demoiselle.properties" -- libgit2 0.21.2