001/* 002 * This library is part of OpenCms - 003 * the Open Source Content Management System 004 * 005 * Copyright (c) Alkacon Software GmbH & Co. KG (https://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: https://www.alkacon.com 019 * 020 * For further information about OpenCms, please see the 021 * project website: https://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.file.CmsResource; 039import org.opencms.main.OpenCms; 040import org.opencms.util.CmsUUID; 041 042import java.io.IOException; 043import java.io.OutputStream; 044import java.sql.Connection; 045import java.sql.PreparedStatement; 046import java.sql.ResultSet; 047import java.sql.SQLException; 048 049/** 050 * Oracle implementation of the VFS driver methods.<p> 051 * 052 * @since 6.0.0 053 */ 054public class CmsVfsDriver extends org.opencms.db.generic.CmsVfsDriver { 055 056 /** 057 * @see org.opencms.db.I_CmsVfsDriver#createContent(CmsDbContext, CmsUUID, CmsResource, byte[]) 058 */ 059 @Override 060 public void createContent(CmsDbContext dbc, CmsUUID projectId, CmsResource resource, byte[] content) 061 throws CmsDataAccessException { 062 063 Connection conn = null; 064 PreparedStatement stmt = null; 065 066 try { 067 conn = m_sqlManager.getConnection(dbc); 068 stmt = m_sqlManager.getPreparedStatement(conn, projectId, "C_ORACLE_OFFLINE_CONTENTS_WRITE"); 069 070 // first insert new file without file_content, then update the file_content 071 // these two steps are necessary because of using BLOBs in the Oracle DB 072 stmt.setString(1, resource.getResourceId().toString()); 073 074 stmt.executeUpdate(); 075 } catch (SQLException e) { 076 throw new CmsDbSqlException( 077 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 078 e); 079 } finally { 080 m_sqlManager.closeAll(dbc, conn, stmt, null); 081 } 082 083 // now update the file content 084 internalWriteContent(dbc, projectId, resource.getResourceId(), content, -1); 085 } 086 087 /** 088 * @see org.opencms.db.generic.CmsVfsDriver#createOnlineContent(CmsDbContext, CmsUUID, byte[], int, boolean, boolean) 089 */ 090 @Override 091 public void createOnlineContent( 092 CmsDbContext dbc, 093 CmsUUID resourceId, 094 byte[] contents, 095 int publishTag, 096 boolean keepOnline, 097 boolean needToUpdateContent) 098 throws CmsDataAccessException { 099 100 Connection conn = null; 101 PreparedStatement stmt = null; 102 103 try { 104 conn = m_sqlManager.getConnection(dbc); 105 boolean dbcHasProjectId = (dbc.getProjectId() != null) && !dbc.getProjectId().isNullUUID(); 106 if (needToUpdateContent || dbcHasProjectId) { 107 if (dbcHasProjectId || !OpenCms.getSystemInfo().isHistoryEnabled()) { 108 // remove the online content for this resource id 109 stmt = m_sqlManager.getPreparedStatement(conn, "C_ONLINE_CONTENTS_DELETE"); 110 stmt.setString(1, resourceId.toString()); 111 stmt.executeUpdate(); 112 m_sqlManager.closeAll(dbc, null, stmt, null); 113 } else { 114 // put the online content in the history 115 stmt = m_sqlManager.getPreparedStatement(conn, "C_ONLINE_CONTENTS_HISTORY"); 116 stmt.setString(1, resourceId.toString()); 117 stmt.executeUpdate(); 118 m_sqlManager.closeAll(dbc, null, stmt, null); 119 } 120 121 // create new empty online content entry 122 stmt = m_sqlManager.getPreparedStatement(conn, "C_ORACLE_ONLINE_CONTENTS_WRITE"); 123 stmt.setString(1, resourceId.toString()); 124 stmt.setInt(2, publishTag); 125 stmt.setInt(3, publishTag); 126 stmt.setInt(4, keepOnline ? 1 : 0); 127 stmt.executeUpdate(); 128 m_sqlManager.closeAll(dbc, conn, stmt, null); 129 130 // now update the file content 131 internalWriteContent(dbc, CmsProject.ONLINE_PROJECT_ID, resourceId, contents, publishTag); 132 } else { 133 // update old content entry 134 stmt = m_sqlManager.getPreparedStatement(conn, "C_HISTORY_CONTENTS_UPDATE"); 135 stmt.setInt(1, publishTag); 136 stmt.setString(2, resourceId.toString()); 137 stmt.executeUpdate(); 138 m_sqlManager.closeAll(dbc, null, stmt, null); 139 140 if (!keepOnline) { 141 // put the online content in the history 142 stmt = m_sqlManager.getPreparedStatement(conn, "C_ONLINE_CONTENTS_HISTORY"); 143 stmt.setString(1, resourceId.toString()); 144 stmt.executeUpdate(); 145 m_sqlManager.closeAll(dbc, null, stmt, null); 146 } 147 } 148 } catch (SQLException e) { 149 throw new CmsDbSqlException( 150 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 151 e); 152 } finally { 153 m_sqlManager.closeAll(dbc, conn, stmt, null); 154 } 155 } 156 157 /** 158 * @see org.opencms.db.I_CmsVfsDriver#initSqlManager(String) 159 */ 160 @Override 161 public org.opencms.db.generic.CmsSqlManager initSqlManager(String classname) { 162 163 return CmsSqlManager.getInstance(classname); 164 } 165 166 /** 167 * @see org.opencms.db.generic.CmsVfsDriver#initSqlManager(String, java.util.List) 168 */ 169 @Override 170 public org.opencms.db.generic.CmsSqlManager initSqlManager( 171 String classname, 172 java.util.List<String> additionalQueryProperties) { 173 174 return CmsSqlManager.getInstance(classname, additionalQueryProperties); 175 } 176 177 /** 178 * @see org.opencms.db.I_CmsVfsDriver#writeContent(CmsDbContext, CmsResource, byte[]) 179 */ 180 @Override 181 public void writeContent(CmsDbContext dbc, CmsResource resource, byte[] content) throws CmsDataAccessException { 182 183 internalWriteContent(dbc, dbc.currentProject().getUuid(), resource.getResourceId(), content, -1); 184 } 185 186 /** 187 * Writes the resource content with the specified resource id.<p> 188 * 189 * @param dbc the current database context 190 * @param projectId the id of the current project 191 * @param resourceId the id of the resource used to identify the content to update 192 * @param contents the new content of the file 193 * @param publishTag the publish tag if to be written to the online content 194 * 195 * @throws CmsDataAccessException if something goes wrong 196 */ 197 protected void internalWriteContent( 198 CmsDbContext dbc, 199 CmsUUID projectId, 200 CmsUUID resourceId, 201 byte[] contents, 202 int publishTag) 203 throws CmsDataAccessException { 204 205 PreparedStatement stmt = null; 206 PreparedStatement commit = null; 207 Connection conn = null; 208 ResultSet res = null; 209 210 boolean wasInTransaction = false; 211 try { 212 conn = m_sqlManager.getConnection(dbc); 213 if (projectId.equals(CmsProject.ONLINE_PROJECT_ID)) { 214 stmt = m_sqlManager.getPreparedStatement(conn, projectId, "C_ORACLE_ONLINE_CONTENTS_UPDATECONTENT"); 215 } else { 216 stmt = m_sqlManager.getPreparedStatement(conn, projectId, "C_ORACLE_OFFLINE_CONTENTS_UPDATECONTENT"); 217 } 218 219 wasInTransaction = !conn.getAutoCommit(); 220 if (!wasInTransaction) { 221 conn.setAutoCommit(false); 222 } 223 224 // update the file content in the contents table 225 stmt.setString(1, resourceId.toString()); 226 if (projectId.equals(CmsProject.ONLINE_PROJECT_ID)) { 227 stmt.setInt(2, publishTag); 228 stmt.setInt(3, publishTag); 229 } 230 res = stmt.executeQuery(); 231 if (!res.next()) { 232 throw new CmsDbEntryNotFoundException( 233 Messages.get().container(Messages.LOG_READING_RESOURCE_1, resourceId)); 234 } 235 // write file content 236 OutputStream output = CmsUserDriver.getOutputStreamFromBlob(res, "FILE_CONTENT"); 237 output.write(contents, 0, contents.length); 238 output.close(); 239 240 if (!wasInTransaction) { 241 commit = m_sqlManager.getPreparedStatement(conn, "C_COMMIT"); 242 commit.execute(); 243 m_sqlManager.closeAll(dbc, null, commit, null); 244 } 245 246 m_sqlManager.closeAll(dbc, null, stmt, res); 247 248 // this is needed so the finally block works correctly 249 commit = null; 250 stmt = null; 251 res = null; 252 253 if (!wasInTransaction) { 254 conn.setAutoCommit(true); 255 } 256 } catch (IOException e) { 257 throw new CmsDbIoException( 258 Messages.get().container(Messages.ERR_WRITING_TO_OUTPUT_STREAM_1, resourceId), 259 e); 260 } catch (SQLException e) { 261 throw new CmsDbSqlException( 262 org.opencms.db.generic.Messages.get().container( 263 org.opencms.db.generic.Messages.ERR_GENERIC_SQL_1, 264 CmsDbSqlException.getErrorQuery(stmt)), 265 e); 266 } finally { 267 org.opencms.db.oracle.CmsSqlManager.closeAllInTransaction( 268 m_sqlManager, 269 dbc, 270 conn, 271 stmt, 272 res, 273 commit, 274 wasInTransaction); 275 } 276 } 277}