001/* 002 * This library is part of OpenCms - 003 * the Open Source Content Management System 004 * 005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com) 006 * 007 * This library is free software; you can redistribute it and/or 008 * modify it under the terms of the GNU Lesser General Public 009 * License as published by the Free Software Foundation; either 010 * version 2.1 of the License, or (at your option) any later version. 011 * 012 * This library is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 * Lesser General Public License for more details. 016 * 017 * For further information about Alkacon Software GmbH & Co. KG, please see the 018 * company website: http://www.alkacon.com 019 * 020 * For further information about OpenCms, please see the 021 * project website: http://www.opencms.org 022 * 023 * You should have received a copy of the GNU Lesser General Public 024 * License along with this library; if not, write to the Free Software 025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 026 */ 027 028package org.opencms.db.oracle; 029 030import org.opencms.db.CmsDbContext; 031import org.opencms.db.CmsDbEntryNotFoundException; 032import org.opencms.db.CmsDbIoException; 033import org.opencms.db.CmsDbSqlException; 034import org.opencms.db.generic.CmsSqlManager; 035import org.opencms.db.generic.Messages; 036import org.opencms.file.CmsDataAccessException; 037import org.opencms.file.CmsProject; 038import org.opencms.main.OpenCms; 039import org.opencms.util.CmsUUID; 040 041import java.io.IOException; 042import java.io.OutputStream; 043import java.sql.Connection; 044import java.sql.PreparedStatement; 045import java.sql.ResultSet; 046import java.sql.SQLException; 047 048/** 049 * Oracle implementation of the VFS driver methods.<p> 050 * 051 * @since 6.0.0 052 */ 053public class CmsVfsDriver extends org.opencms.db.generic.CmsVfsDriver { 054 055 /** 056 * @see org.opencms.db.I_CmsVfsDriver#createContent(CmsDbContext, CmsUUID, CmsUUID, byte[]) 057 */ 058 @Override 059 public void createContent(CmsDbContext dbc, CmsUUID projectId, CmsUUID resourceId, byte[] content) 060 throws CmsDataAccessException { 061 062 Connection conn = null; 063 PreparedStatement stmt = null; 064 065 try { 066 conn = m_sqlManager.getConnection(dbc); 067 stmt = m_sqlManager.getPreparedStatement(conn, projectId, "C_ORACLE_OFFLINE_CONTENTS_WRITE"); 068 069 // first insert new file without file_content, then update the file_content 070 // these two steps are necessary because of using BLOBs in the Oracle DB 071 stmt.setString(1, resourceId.toString()); 072 073 stmt.executeUpdate(); 074 } catch (SQLException e) { 075 throw new CmsDbSqlException( 076 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 077 e); 078 } finally { 079 m_sqlManager.closeAll(dbc, conn, stmt, null); 080 } 081 082 // now update the file content 083 internalWriteContent(dbc, projectId, resourceId, content, -1); 084 } 085 086 /** 087 * @see org.opencms.db.generic.CmsVfsDriver#createOnlineContent(CmsDbContext, CmsUUID, byte[], int, boolean, boolean) 088 */ 089 @Override 090 public void createOnlineContent( 091 CmsDbContext dbc, 092 CmsUUID resourceId, 093 byte[] contents, 094 int publishTag, 095 boolean keepOnline, 096 boolean needToUpdateContent) 097 throws CmsDataAccessException { 098 099 Connection conn = null; 100 PreparedStatement stmt = null; 101 102 try { 103 conn = m_sqlManager.getConnection(dbc); 104 boolean dbcHasProjectId = (dbc.getProjectId() != null) && !dbc.getProjectId().isNullUUID(); 105 if (needToUpdateContent || dbcHasProjectId) { 106 if (dbcHasProjectId || !OpenCms.getSystemInfo().isHistoryEnabled()) { 107 // remove the online content for this resource id 108 stmt = m_sqlManager.getPreparedStatement(conn, "C_ONLINE_CONTENTS_DELETE"); 109 stmt.setString(1, resourceId.toString()); 110 stmt.executeUpdate(); 111 m_sqlManager.closeAll(dbc, null, stmt, null); 112 } else { 113 // put the online content in the history 114 stmt = m_sqlManager.getPreparedStatement(conn, "C_ONLINE_CONTENTS_HISTORY"); 115 stmt.setString(1, resourceId.toString()); 116 stmt.executeUpdate(); 117 m_sqlManager.closeAll(dbc, null, stmt, null); 118 } 119 120 // create new empty online content entry 121 stmt = m_sqlManager.getPreparedStatement(conn, "C_ORACLE_ONLINE_CONTENTS_WRITE"); 122 stmt.setString(1, resourceId.toString()); 123 stmt.setInt(2, publishTag); 124 stmt.setInt(3, publishTag); 125 stmt.setInt(4, keepOnline ? 1 : 0); 126 stmt.executeUpdate(); 127 m_sqlManager.closeAll(dbc, conn, stmt, null); 128 129 // now update the file content 130 internalWriteContent(dbc, CmsProject.ONLINE_PROJECT_ID, resourceId, contents, publishTag); 131 } else { 132 // update old content entry 133 stmt = m_sqlManager.getPreparedStatement(conn, "C_HISTORY_CONTENTS_UPDATE"); 134 stmt.setInt(1, publishTag); 135 stmt.setString(2, resourceId.toString()); 136 stmt.executeUpdate(); 137 m_sqlManager.closeAll(dbc, null, stmt, null); 138 139 if (!keepOnline) { 140 // put the online content in the history 141 stmt = m_sqlManager.getPreparedStatement(conn, "C_ONLINE_CONTENTS_HISTORY"); 142 stmt.setString(1, resourceId.toString()); 143 stmt.executeUpdate(); 144 m_sqlManager.closeAll(dbc, null, stmt, null); 145 } 146 } 147 } catch (SQLException e) { 148 throw new CmsDbSqlException( 149 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 150 e); 151 } finally { 152 m_sqlManager.closeAll(dbc, conn, stmt, null); 153 } 154 } 155 156 /** 157 * @see org.opencms.db.I_CmsVfsDriver#initSqlManager(String) 158 */ 159 @Override 160 public org.opencms.db.generic.CmsSqlManager initSqlManager(String classname) { 161 162 return CmsSqlManager.getInstance(classname); 163 } 164 165 /** 166 * @see org.opencms.db.I_CmsVfsDriver#writeContent(CmsDbContext, CmsUUID, byte[]) 167 */ 168 @Override 169 public void writeContent(CmsDbContext dbc, CmsUUID resourceId, byte[] content) throws CmsDataAccessException { 170 171 internalWriteContent(dbc, dbc.currentProject().getUuid(), resourceId, content, -1); 172 } 173 174 /** 175 * Writes the resource content with the specified resource id.<p> 176 * 177 * @param dbc the current database context 178 * @param projectId the id of the current project 179 * @param resourceId the id of the resource used to identify the content to update 180 * @param contents the new content of the file 181 * @param publishTag the publish tag if to be written to the online content 182 * 183 * @throws CmsDataAccessException if something goes wrong 184 */ 185 protected void internalWriteContent( 186 CmsDbContext dbc, 187 CmsUUID projectId, 188 CmsUUID resourceId, 189 byte[] contents, 190 int publishTag) 191 throws CmsDataAccessException { 192 193 PreparedStatement stmt = null; 194 PreparedStatement commit = null; 195 Connection conn = null; 196 ResultSet res = null; 197 198 boolean wasInTransaction = false; 199 try { 200 conn = m_sqlManager.getConnection(dbc); 201 if (projectId.equals(CmsProject.ONLINE_PROJECT_ID)) { 202 stmt = m_sqlManager.getPreparedStatement(conn, projectId, "C_ORACLE_ONLINE_CONTENTS_UPDATECONTENT"); 203 } else { 204 stmt = m_sqlManager.getPreparedStatement(conn, projectId, "C_ORACLE_OFFLINE_CONTENTS_UPDATECONTENT"); 205 } 206 207 wasInTransaction = !conn.getAutoCommit(); 208 if (!wasInTransaction) { 209 conn.setAutoCommit(false); 210 } 211 212 // update the file content in the contents table 213 stmt.setString(1, resourceId.toString()); 214 if (projectId.equals(CmsProject.ONLINE_PROJECT_ID)) { 215 stmt.setInt(2, publishTag); 216 stmt.setInt(3, publishTag); 217 } 218 res = stmt.executeQuery(); 219 if (!res.next()) { 220 throw new CmsDbEntryNotFoundException( 221 Messages.get().container(Messages.LOG_READING_RESOURCE_1, resourceId)); 222 } 223 // write file content 224 OutputStream output = CmsUserDriver.getOutputStreamFromBlob(res, "FILE_CONTENT"); 225 output.write(contents, 0, contents.length); 226 output.close(); 227 228 if (!wasInTransaction) { 229 commit = m_sqlManager.getPreparedStatement(conn, "C_COMMIT"); 230 commit.execute(); 231 m_sqlManager.closeAll(dbc, null, commit, null); 232 } 233 234 m_sqlManager.closeAll(dbc, null, stmt, res); 235 236 // this is needed so the finally block works correctly 237 commit = null; 238 stmt = null; 239 res = null; 240 241 if (!wasInTransaction) { 242 conn.setAutoCommit(true); 243 } 244 } catch (IOException e) { 245 throw new CmsDbIoException( 246 Messages.get().container(Messages.ERR_WRITING_TO_OUTPUT_STREAM_1, resourceId), 247 e); 248 } catch (SQLException e) { 249 throw new CmsDbSqlException( 250 org.opencms.db.generic.Messages.get().container( 251 org.opencms.db.generic.Messages.ERR_GENERIC_SQL_1, 252 CmsDbSqlException.getErrorQuery(stmt)), 253 e); 254 } finally { 255 org.opencms.db.oracle.CmsSqlManager.closeAllInTransaction( 256 m_sqlManager, 257 dbc, 258 conn, 259 stmt, 260 res, 261 commit, 262 wasInTransaction); 263 } 264 } 265}