/*
* 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 de.unioninvestment.eai.portal.portlet.crud.persistence;
import java.io.IOException;
import java.io.InputStream;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.sql.Types;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Profile;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.support.AbstractLobCreatingPreparedStatementCallback;
import org.springframework.jdbc.support.lob.DefaultLobHandler;
import org.springframework.jdbc.support.lob.LobCreator;
import org.springframework.jdbc.support.lob.LobHandler;
import org.springframework.stereotype.Repository;
/**
* Data Access Object for the portlet configuration data.
*
* @author markus.bonsch
*
*
*/
@Repository
@Profile("ORACLE_STORAGE")
public class DefaultConfigurationDao implements ConfigurationDao {
static final class ConfigStreamRowMapper<T> implements RowMapper<T> {
private final StreamProcessor<T> processor;
private LobHandler lobHandler;
public ConfigStreamRowMapper(StreamProcessor<T> processor,
LobHandler lobHandler) {
this.processor = processor;
this.lobHandler = lobHandler;
}
public T mapRow(ResultSet rs, int i) throws SQLException {
ConfigurationMetaData metaData = new MetaDataRowMapper().mapRow(rs,
i);
InputStream stream = lobHandler.getBlobAsBinaryStream(rs,
"CONFIG_XML");
try {
return processor.process(stream, metaData);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
private static final class MetaDataRowMapper implements
RowMapper<ConfigurationMetaData> {
public ConfigurationMetaData mapRow(ResultSet rs, int rowNum)
throws SQLException {
return new ConfigurationMetaData( //
rs.getString("USER_CREATED"), //
rs.getTimestamp("DATE_CREATED"), //
rs.getTimestamp("DATE_UPDATED"), //
rs.getString("CONFIG_NAME"));
}
}
protected LobHandler lobHandler = new DefaultLobHandler();
protected JdbcTemplate jdbcTemplate;
/**
*
* @param jdbcTemplate
* JdbcTemplate
*/
@Autowired
public DefaultConfigurationDao(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
/**
* @param portletId
* die PortletID der aktuellen Portlet-Instanz
* @param communityId
* @return <code>true</code>, falls eine Konfiguration existiert
*/
public boolean hasConfigData(final String portletId, long communityId) {
int count = jdbcTemplate
.queryForObject(
"SELECT COUNT(ID) FROM ADM_CONFIG WHERE PORTLET_ID = ? AND COMMUNITY_ID = ?",
Integer.class, portletId, communityId);
return count > 0;
}
/**
* @param portletId
* die PortletID der aktuellen Portlet-Instanz
* @param communityId
* @return die ID des aktuellen Datenbankeintrags oder null wenn kein
* Eintrag vorhanden.
*/
public Long getId(final String portletId, long communityId) {
List<Long> result = jdbcTemplate
.queryForList(
"SELECT ID FROM ADM_CONFIG WHERE PORTLET_ID = ? AND COMMUNITY_ID = ? ORDER BY DATE_CREATED DESC",
Long.class, portletId, communityId);
if (result.isEmpty()) {
return null;
}
return result.get(0);
}
/**
*
* @param porteltId
* , dient zur eindeutigen Identifizierung der
* Portletkonfiguration.
* @param communityId
* @return Die zur PortletId abgelegte Portlet-Konfiguration.
*/
public ConfigurationMetaData readConfigMetaData(final String porteltId,
long communityId) {
List<ConfigurationMetaData> result = jdbcTemplate
.query("SELECT DATE_CREATED, DATE_UPDATED, USER_CREATED, CONFIG_NAME FROM ADM_CONFIG WHERE PORTLET_ID = ? AND COMMUNITY_ID = ? ORDER BY DATE_CREATED DESC",
new Object[] { porteltId, communityId },
new MetaDataRowMapper());
if (result.isEmpty()) {
return null;
}
return result.get(0);
}
/**
* @param <T>
* der Rückgabetyp des {@link StreamProcessor} Callbacks
* @param portletId
* die PortletID der aktuellen Portlet-Instanz
* @param processor
* eine Callback-Instanz die mit dem {@link InputStream} des
* Config-Blobs aufgerufen wird
* @return das vom processor zurückgelieferte Objekt
*/
public <T> T readConfigStream(String portletId, long communityId,
final StreamProcessor<T> processor) {
return jdbcTemplate
.queryForObject(
"SELECT * FROM ( SELECT DATE_CREATED, DATE_UPDATED, USER_CREATED, CONFIG_NAME, CONFIG_XML FROM ADM_CONFIG WHERE PORTLET_ID = ? AND COMMUNITY_ID = ? ORDER BY DATE_CREATED DESC ) WHERE ROWNUM = 1",
new ConfigStreamRowMapper<T>(processor, lobHandler),
portletId, communityId);
}
/**
* Speichert eine neue Konfiguration für die PortletID und den
* Konfigurationsnamen ab oder überschreibt eine entsprechende Konfiguration
* gleichen Namens.
*
* @param portletId
* die PortletID der aktuellen Portlet-Instanz
* @param communityId
* @param configName
* der Name der Konfiguration
* @param configXML
* die Konfiguration
* @param user
* der aktuelle Benutzername
*/
public void saveOrUpdateConfigData(final String portletId,
long communityId, final String configName, final byte[] configXML,
final String user) {
Long id = getId(portletId, communityId);
if (id != null) {
updateConfigData(id, configName, configXML, user);
} else {
insertConfigData(portletId, communityId, configName, configXML,
user);
}
}
/**
* Legt einen eindeutigen Schlüssel an.
*
* @return Eindeutiger Schlüssel.
*/
private Long readNextRoleResourceIdPrimKey() {
return jdbcTemplate.queryForObject(
"select RESOURCEID_SEQ.nextval from dual", Long.class);
}
/**
* Liest einen Eintrag aus der Mappingtabelle.
*
* @param resourceId
* Id des
* @return ResourceId bzw. Primäschlüssel
*/
public Long readRoleResourceIdPrimKey(String resourceId) {
try {
return jdbcTemplate
.queryForObject(
"SELECT PRIMKEY FROM RESOURCEID_PRIMKEY WHERE RESOURCEID = ?",
Long.class, resourceId);
} catch (EmptyResultDataAccessException e) {
return null;
}
}
/**
* Legt einen Eintrag in der Mappingtabelle an.
*
* @param primkey
* Primärschlüssel
* @param resourceId
* Id des Portlets.
* @return
*/
public long storeRoleResourceIdPrimKey(String resourceId) {
long primkey = readNextRoleResourceIdPrimKey();
jdbcTemplate
.update("INSERT INTO RESOURCEID_PRIMKEY (PRIMKEY, RESOURCEID) values (?,?)",
new Object[] { primkey, resourceId }, new int[] {
Types.NUMERIC, Types.VARCHAR });
return primkey;
}
/**
* @param configId
* die ID des bestehenden Datensatzes
* @param configName
* der Name der Konfiguration
* @param configXML
* die Konfiguration
* @param user
* der aktuelle Benutzername
*/
private void updateConfigData(final long configId, final String configName,
final byte[] configXML, final String user) {
jdbcTemplate
.execute(
"UPDATE ADM_CONFIG SET CONFIG_NAME = ?, CONFIG_XML = ?, USER_CREATED = ? WHERE ID=?",
new AbstractLobCreatingPreparedStatementCallback(
lobHandler) {
protected void setValues(PreparedStatement ps,
LobCreator lobCreator) throws SQLException {
ps.setString(1, configName);
lobCreator.setBlobAsBytes(ps, 2, configXML);
ps.setString(3, user);
ps.setLong(4, configId);
}
});
}
/**
* Speichert eine neue Konfiguration ab.
*
* @param portletId
* die PortletID der aktuellen Portlet-Instanz
* @param configName
* der Name der Konfiguration
* @param configXML
* die Konfiguration
* @param user
* der aktuelle Benutzername
*/
private void insertConfigData(final String portletId,
final long communityId, final String configName,
final byte[] configXML, final String user) {
jdbcTemplate
.execute(
"INSERT INTO ADM_CONFIG (PORTLET_ID, COMMUNITY_ID, CONFIG_NAME, CONFIG_XML,USER_CREATED,DATE_CREATED) VALUES (?,?,?,?,?,?)",
new AbstractLobCreatingPreparedStatementCallback(
lobHandler) {
protected void setValues(PreparedStatement ps,
LobCreator lobCreator) throws SQLException {
ps.setString(1, portletId);
ps.setLong(2, communityId);
ps.setString(3, configName);
lobCreator.setBlobAsBytes(ps, 4, configXML);
ps.setString(5, user);
ps.setTimestamp(
6,
new Timestamp(System
.currentTimeMillis()));
}
});
}
@Override
public void removeConfiguration(String portletId, long communityId) {
jdbcTemplate
.update("DELETE FROM ADM_CONFIG WHERE PORTLET_ID = ? AND COMMUNITY_ID = ?",
portletId, communityId);
}
@Override
public void removeExistingRoleResourceIds(String portletId, long communityId) {
jdbcTemplate
.execute("DELETE FROM RESOURCEID_PRIMKEY WHERE RESOURCEID LIKE '"
+ portletId + "_" + communityId + "_%' escape '#'");
}
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
}