📄 jdbcmailrepository.java
字号:
/**************************************************************** * Licensed to the Apache Software Foundation (ASF) under one * * or more contributor license agreements. See the NOTICE file * * distributed with this work for additional information * * regarding copyright ownership. The ASF licenses this file * * to you under the Apache License, Version 2.0 (the * * "License"); you may not use this file except in compliance * * with the License. You may obtain a copy of the License at * * * * http://www.apache.org/licenses/LICENSE-2.0 * * * * Unless required by applicable law or agreed to in writing, * * software distributed under the License is distributed on an * * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * * KIND, either express or implied. See the License for the * * specific language governing permissions and limitations * * under the License. * ****************************************************************/package org.apache.james.mailrepository;import org.apache.avalon.cornerstone.services.datasources.DataSourceSelector;import org.apache.avalon.cornerstone.services.store.Store;import org.apache.avalon.cornerstone.services.store.StreamRepository;import org.apache.avalon.excalibur.datasource.DataSourceComponent;import org.apache.avalon.framework.activity.Initializable;import org.apache.avalon.framework.service.Serviceable;import org.apache.avalon.framework.service.ServiceManager;import org.apache.avalon.framework.service.ServiceException;import org.apache.avalon.framework.configuration.Configurable;import org.apache.avalon.framework.configuration.Configuration;import org.apache.avalon.framework.configuration.ConfigurationException;import org.apache.avalon.framework.configuration.DefaultConfiguration;import org.apache.avalon.framework.context.Context;import org.apache.avalon.framework.context.ContextException;import org.apache.avalon.framework.context.Contextualizable;import org.apache.avalon.framework.logger.AbstractLogEnabled;import org.apache.james.context.AvalonContextUtilities;import org.apache.james.core.MailImpl;import org.apache.james.core.MimeMessageCopyOnWriteProxy;import org.apache.james.core.MimeMessageWrapper;import org.apache.james.services.MailRepository;import org.apache.james.util.JDBCUtil;import org.apache.james.util.Lock;import org.apache.james.util.SqlResources;import org.apache.mailet.Mail;import org.apache.mailet.MailAddress;import javax.mail.MessagingException;import javax.mail.internet.MimeMessage;import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.File;import java.io.IOException;import java.io.ObjectOutputStream;import java.io.ObjectInputStream;import java.sql.Blob;import java.sql.Connection;import java.sql.DatabaseMetaData;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException;import java.sql.Statement;import java.util.ArrayList;import java.util.Collection;import java.util.HashMap;import java.util.HashSet;import java.util.Iterator;import java.util.List;import java.util.Map;import java.util.Set;import java.util.StringTokenizer;/** * Implementation of a MailRepository on a database. * * <p>Requires a configuration element in the .conf.xml file of the form: * <br><repository destinationURL="db://<datasource>/<table_name>/<repository_name>" * <br> type="MAIL" * <br> model="SYNCHRONOUS"/> * <br></repository> * <p>destinationURL specifies..(Serge??) * <br>Type can be SPOOL or MAIL * <br>Model is currently not used and may be dropped * * <p>Requires a logger called MailRepository. * * @version CVS $Revision: 494012 $ $Date: 2007-01-08 11:23:58 +0100 (Mo, 08 Jan 2007) $ */public class JDBCMailRepository extends AbstractLogEnabled implements MailRepository, Contextualizable, Serviceable, Configurable, Initializable { /** * Whether 'deep debugging' is turned on. */ private static final boolean DEEP_DEBUG = false; /** * The Avalon componentManager used by the instance */ private ServiceManager componentManager; /** * The Avalon context used by the instance */ protected Context context; /** * A lock used to control access to repository elements, locking access * based on the key */ private Lock lock; /** * The table name parsed from the destination URL */ protected String tableName; /** * The repository name parsed from the destination URL */ protected String repositoryName; /** * The name of the SQL configuration file to be used to configure this repository. */ private String sqlFileName; /** * The stream repository used in dbfile mode */ private StreamRepository sr = null; /** * The selector used to obtain the JDBC datasource */ protected DataSourceSelector datasources; /** * The JDBC datasource that provides the JDBC connection */ protected DataSourceComponent datasource; /** * The name of the datasource used by this repository */ protected String datasourceName; /** * Contains all of the sql strings for this component. */ protected SqlResources sqlQueries; /** * The JDBCUtil helper class */ protected JDBCUtil theJDBCUtil; /** * "Support for Mail Attributes under JDBC repositories is ready" indicator. */ protected boolean jdbcMailAttributesReady = false; /** * The size threshold for in memory handling of storing operations */ private int inMemorySizeLimit; /** * @see org.apache.avalon.framework.context.Contextualizable#contextualize(Context) */ public void contextualize(final Context context) throws ContextException { this.context = context; } /** * @see org.apache.avalon.framework.service.Servicable#service(ServiceManager) */ public void service( final ServiceManager componentManager ) throws ServiceException { StringBuffer logBuffer = null; if (getLogger().isDebugEnabled()) { logBuffer = new StringBuffer(64) .append(this.getClass().getName()) .append(".compose()"); getLogger().debug(logBuffer.toString()); } // Get the DataSourceSelector service datasources = (DataSourceSelector)componentManager.lookup( DataSourceSelector.ROLE ); this.componentManager = componentManager; } /** * @see org.apache.avalon.framework.configuration.Configurable#configure(Configuration) */ public void configure(Configuration conf) throws ConfigurationException { if (getLogger().isDebugEnabled()) { getLogger().debug(this.getClass().getName() + ".configure()"); } String destination = conf.getAttribute("destinationURL"); // normalize the destination, to simplify processing. if ( ! destination.endsWith("/") ) { destination += "/"; } // Parse the DestinationURL for the name of the datasource, // the table to use, and the (optional) repository Key. // Split on "/", starting after "db://" List urlParams = new ArrayList(); int start = 5; if (destination.startsWith("dbfile")) { //this is dbfile:// instead of db:// start += 4; } int end = destination.indexOf('/', start); while ( end > -1 ) { urlParams.add(destination.substring(start, end)); start = end + 1; end = destination.indexOf('/', start); } // Build SqlParameters and get datasource name from URL parameters if (urlParams.size() == 0) { StringBuffer exceptionBuffer = new StringBuffer(256) .append("Malformed destinationURL - Must be of the format '") .append("db://<data-source>[/<table>[/<repositoryName>]]'. Was passed ") .append(conf.getAttribute("destinationURL")); throw new ConfigurationException(exceptionBuffer.toString()); } if (urlParams.size() >= 1) { datasourceName = (String)urlParams.get(0); } if (urlParams.size() >= 2) { tableName = (String)urlParams.get(1); } if (urlParams.size() >= 3) { repositoryName = ""; for (int i = 2; i < urlParams.size(); i++) { if (i >= 3) { repositoryName += '/'; } repositoryName += (String)urlParams.get(i); } } if (getLogger().isDebugEnabled()) { StringBuffer logBuffer = new StringBuffer(128) .append("Parsed URL: table = '") .append(tableName) .append("', repositoryName = '") .append(repositoryName) .append("'"); getLogger().debug(logBuffer.toString()); } inMemorySizeLimit = conf.getChild("inMemorySizeLimit").getValueAsInteger(409600000); String filestore = conf.getChild("filestore").getValue(null); sqlFileName = conf.getChild("sqlFile").getValue(); if (!sqlFileName.startsWith("file://")) { throw new ConfigurationException ("Malformed sqlFile - Must be of the format 'file://<filename>'."); } try { if (filestore != null) { Store store = (Store)componentManager.lookup(Store.ROLE); //prepare Configurations for stream repositories DefaultConfiguration streamConfiguration = new DefaultConfiguration( "repository", "generated:JDBCMailRepository.configure()" ); streamConfiguration.setAttribute( "destinationURL", filestore ); streamConfiguration.setAttribute( "type", "STREAM" ); streamConfiguration.setAttribute( "model", "SYNCHRONOUS" ); sr = (StreamRepository) store.select(streamConfiguration); if (getLogger().isDebugEnabled()) { getLogger().debug("Got filestore for JdbcMailRepository: " + filestore); } } lock = new Lock(); if (getLogger().isDebugEnabled()) { StringBuffer logBuffer = new StringBuffer(128) .append(this.getClass().getName()) .append(" created according to ") .append(destination); getLogger().debug(logBuffer.toString()); } } catch (Exception e) { final String message = "Failed to retrieve Store component:" + e.getMessage(); getLogger().error(message, e); throw new ConfigurationException(message, e); } } /** * Initialises the JDBC repository. * 1) Tests the connection to the database. * 2) Loads SQL strings from the SQL definition file, * choosing the appropriate SQL for this connection, * and performing paramter substitution, * 3) Initialises the database with the required tables, if necessary. * * @throws Exception if an error occurs */ public void initialize() throws Exception { StringBuffer logBuffer = null; if (getLogger().isDebugEnabled()) { getLogger().debug(this.getClass().getName() + ".initialize()"); } theJDBCUtil = new JDBCUtil() { protected void delegatedLog(String logString) { JDBCMailRepository.this.getLogger().warn("JDBCMailRepository: " + logString); } }; // Get the data-source required. datasource = (DataSourceComponent)datasources.select(datasourceName); // Test the connection to the database, by getting the DatabaseMetaData. Connection conn = datasource.getConnection(); PreparedStatement createStatement = null; try { // Initialise the sql strings. File sqlFile = null; try { sqlFile = AvalonContextUtilities.getFile(context, sqlFileName); sqlFileName = null; } catch (Exception e) { getLogger().fatalError(e.getMessage(), e); throw e; } if (getLogger().isDebugEnabled()) { logBuffer = new StringBuffer(128) .append("Reading SQL resources from file: ") .append(sqlFile.getAbsolutePath()) .append(", section ") .append(this.getClass().getName()) .append("."); getLogger().debug(logBuffer.toString()); } // Build the statement parameters
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -