001/*
002 *  Copyright 2015 Anyware Services
003 *
004 *  Licensed under the Apache License, Version 2.0 (the "License");
005 *  you may not use this file except in compliance with the License.
006 *  You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 *  Unless required by applicable law or agreed to in writing, software
011 *  distributed under the License is distributed on an "AS IS" BASIS,
012 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 *  See the License for the specific language governing permissions and
014 *  limitations under the License.
015 */
016package org.ametys.plugins.core.impl.datasource;
017
018import java.io.ByteArrayInputStream;
019import java.io.InputStream;
020import java.io.UnsupportedEncodingException;
021import java.sql.Blob;
022import java.sql.PreparedStatement;
023import java.sql.ResultSet;
024import java.sql.SQLException;
025import java.sql.Types;
026
027import org.apache.avalon.framework.configuration.Configurable;
028import org.apache.avalon.framework.configuration.Configuration;
029import org.apache.avalon.framework.configuration.ConfigurationException;
030import org.apache.commons.lang3.StringUtils;
031
032import org.ametys.core.datasource.dbtype.SQLDatabaseType;
033import org.ametys.runtime.i18n.I18nizableText;
034import org.ametys.runtime.plugin.component.AbstractLogEnabled;
035import org.ametys.runtime.plugin.component.PluginAware;
036
037/**
038 * Default implementation for a {@link SQLDatabaseType}.
039 */
040public class StaticSQLDatabaseType extends AbstractLogEnabled implements Configurable, SQLDatabaseType, PluginAware
041{
042    /** The id of the database type */
043    protected String _id;
044    
045    /** The label of the database type */
046    protected I18nizableText _label;
047
048    /** The driver of the database type */
049    protected String _driver;
050    
051    /** The url template for this database type */
052    protected String _template;
053    
054    /** The plugin's name */
055    protected String _pluginName;
056    
057    /** The SQL query to validate the connection is still alive */
058    protected String _validationQuery;
059    
060    /** The driver not found message */
061    protected I18nizableText _driverNotFoundMessage;
062
063    /** The template to escape the table name. Must contain {tableName} */
064    protected String _languageEscapeTableNameTemplate;
065    /** The template to limit the query to a limit/offset. Must contain {query} {limit} and {offset}*/
066    protected String _languageLimitQueryTemplate;
067    
068    public void setPluginInfo(String pluginName, String featureName, String id)
069    {
070        _pluginName = pluginName;
071        _id = id;
072    }
073    
074    public void configure(Configuration configuration) throws ConfigurationException
075    {
076        if (getLogger().isDebugEnabled())
077        {
078            getLogger().debug("Configuring database type with id '" + _id  + "'");
079        }
080        
081        _label = I18nizableText.parseI18nizableText(configuration.getChild("label"), "plugin." + _pluginName);
082        _driver = configuration.getChild("driver").getValue();
083        _driverNotFoundMessage = I18nizableText.parseI18nizableText(configuration.getChild("driver-not-found-message"), "plugin." + _pluginName); 
084        _template = configuration.getChild("template").getValue("");
085        _validationQuery = configuration.getChild("validation-query").getValue("SELECT 1");
086        _languageEscapeTableNameTemplate = configuration.getChild("language").getChild("escape-table-name").getValue("{tableName}");
087        _languageLimitQueryTemplate = configuration.getChild("language").getChild("limit-query").getValue("{query} LIMIT {limit} OFFSET {offset}");
088    }
089    
090    public String getId()
091    {
092        return _id;
093    }
094    
095    public I18nizableText getLabel() 
096    {
097        return _label;
098    }
099    
100    public String getDriver() 
101    {
102        return _driver;
103    }
104    
105    public String getTemplate()
106    {
107        return _template;
108    }
109    
110    public String getValidationQuery()
111    {
112        return _validationQuery;
113    }
114    
115    public I18nizableText getDriverNotFoundMessage()
116    {
117        return _driverNotFoundMessage;
118    }
119    
120    public String languageEscapeTableName(String tableNameToEscape)
121    {
122        return StringUtils.replace(_languageEscapeTableNameTemplate, "{tableName}", tableNameToEscape);
123    }
124    
125    public String languageLimitQuery(String queryToLimit, String limit, String offset)
126    {
127        return StringUtils.replace(StringUtils.replace(StringUtils.replace(_languageLimitQueryTemplate, "{query}", queryToLimit), "{limit}", limit), "{offset}", offset);
128    }
129    
130    public InputStream getBlob(ResultSet resultSet, String columnName) throws SQLException
131    {
132        Blob commentBlob = resultSet.getBlob(columnName);
133        return commentBlob != null ? commentBlob.getBinaryStream() : null;
134    }
135    
136    public InputStream getBlob(ResultSet resultSet, int pos) throws SQLException
137    {
138        Blob commentBlob = resultSet.getBlob(pos);
139        return commentBlob != null ? commentBlob.getBinaryStream() : null;
140    }
141    
142    public void setBlob(PreparedStatement statement, int pos, String blob) throws SQLException, UnsupportedEncodingException
143    {
144        if (blob == null)
145        {
146            statement.setNull(pos, Types.BLOB);
147        }
148        else
149        {
150            byte[] bytes = blob.getBytes("UTF-8");
151            setBlob(statement, pos, bytes);
152        }
153    }
154    
155    public void setBlob(PreparedStatement statement, int pos, byte[] bytes) throws SQLException
156    {
157        if (bytes == null)
158        {
159            statement.setNull(pos, Types.BLOB);
160        }
161        else
162        {
163            statement.setBlob(pos, new ByteArrayInputStream(bytes));
164        }
165    }
166
167    public void setBlob(PreparedStatement statement, int pos, InputStream is, long length) throws SQLException
168    {
169        if (is == null)
170        {
171            statement.setNull(pos, Types.BLOB);
172        }
173        else
174        {
175            statement.setBlob(pos, is);
176        }
177    }
178}