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.generic; 029 030import org.opencms.configuration.CmsConfigurationManager; 031import org.opencms.configuration.CmsParameterConfiguration; 032import org.opencms.db.CmsDbConsistencyException; 033import org.opencms.db.CmsDbContext; 034import org.opencms.db.CmsDbEntryNotFoundException; 035import org.opencms.db.CmsDbSqlException; 036import org.opencms.db.CmsDriverManager; 037import org.opencms.db.CmsResourceState; 038import org.opencms.db.I_CmsDriver; 039import org.opencms.db.I_CmsHistoryDriver; 040import org.opencms.db.I_CmsVfsDriver; 041import org.opencms.file.CmsDataAccessException; 042import org.opencms.file.CmsFile; 043import org.opencms.file.CmsFolder; 044import org.opencms.file.CmsProject; 045import org.opencms.file.CmsProperty; 046import org.opencms.file.CmsPropertyDefinition; 047import org.opencms.file.CmsResource; 048import org.opencms.file.CmsUser; 049import org.opencms.file.CmsVfsResourceNotFoundException; 050import org.opencms.file.history.CmsHistoryFile; 051import org.opencms.file.history.CmsHistoryFolder; 052import org.opencms.file.history.CmsHistoryPrincipal; 053import org.opencms.file.history.CmsHistoryProject; 054import org.opencms.file.history.I_CmsHistoryResource; 055import org.opencms.main.CmsLog; 056import org.opencms.security.CmsOrganizationalUnit; 057import org.opencms.security.I_CmsPrincipal; 058import org.opencms.util.CmsStringUtil; 059import org.opencms.util.CmsUUID; 060 061import java.sql.Connection; 062import java.sql.PreparedStatement; 063import java.sql.ResultSet; 064import java.sql.SQLException; 065import java.util.ArrayList; 066import java.util.HashMap; 067import java.util.Iterator; 068import java.util.List; 069import java.util.Map; 070import java.util.Set; 071 072import org.apache.commons.logging.Log; 073 074/** 075 * Generic (ANSI-SQL) database server implementation of the history driver methods.<p> 076 * 077 * @since 6.9.1 078 */ 079public class CmsHistoryDriver implements I_CmsDriver, I_CmsHistoryDriver { 080 081 /** The log object for this class. */ 082 private static final Log LOG = CmsLog.getLog(org.opencms.db.generic.CmsHistoryDriver.class); 083 084 /** The driver manager instance. */ 085 protected CmsDriverManager m_driverManager; 086 087 /** The SQL manager instance. */ 088 protected CmsSqlManager m_sqlManager; 089 090 /** 091 * @see org.opencms.db.I_CmsHistoryDriver#createPropertyDefinition(org.opencms.db.CmsDbContext, java.lang.String, org.opencms.file.CmsPropertyDefinition.CmsPropertyType) 092 */ 093 public CmsPropertyDefinition createPropertyDefinition( 094 CmsDbContext dbc, 095 String name, 096 CmsPropertyDefinition.CmsPropertyType type) 097 throws CmsDataAccessException { 098 099 Connection conn = null; 100 PreparedStatement stmt = null; 101 102 try { 103 conn = m_sqlManager.getConnection(dbc); 104 stmt = m_sqlManager.getPreparedStatement(conn, "C_PROPERTYDEF_CREATE_HISTORY"); 105 stmt.setString(1, new CmsUUID().toString()); 106 stmt.setString(2, name); 107 stmt.setInt(3, type.getMode()); 108 stmt.executeUpdate(); 109 } catch (SQLException e) { 110 throw new CmsDbSqlException( 111 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 112 e); 113 114 } finally { 115 m_sqlManager.closeAll(dbc, conn, stmt, null); 116 } 117 118 return readPropertyDefinition(dbc, name); 119 } 120 121 /** 122 * @see org.opencms.db.I_CmsHistoryDriver#deleteEntries(CmsDbContext, I_CmsHistoryResource, int, long) 123 */ 124 public int deleteEntries(CmsDbContext dbc, I_CmsHistoryResource resource, int versionsToKeep, long time) 125 throws CmsDataAccessException { 126 127 Connection conn = null; 128 PreparedStatement stmt = null; 129 ResultSet res = null; 130 131 try { 132 conn = m_sqlManager.getConnection(dbc); 133 134 int maxVersion = -1; 135 // get the maximal version number for this resource 136 stmt = m_sqlManager.getPreparedStatement(conn, "C_STRUCTURE_HISTORY_MAXVER"); 137 stmt.setString(1, resource.getStructureId().toString()); 138 res = stmt.executeQuery(); 139 boolean noHistoryStructure = false; 140 if (res.next()) { 141 maxVersion = res.getInt(1); 142 noHistoryStructure |= res.wasNull(); 143 while (res.next()) { 144 // do nothing only move through all rows because of mssql odbc driver 145 } 146 } else { 147 // make sure the connection is closed 148 m_sqlManager.closeAll(dbc, conn, stmt, res); 149 // nothing to delete 150 internalCleanup(dbc, resource); 151 return 0; 152 } 153 m_sqlManager.closeAll(dbc, conn, stmt, res); 154 155 if (time >= 0) { 156 int maxVersionByTime = -1; 157 conn = m_sqlManager.getConnection(dbc); 158 // get the maximal version to keep for this resource based on the time parameter 159 stmt = m_sqlManager.getPreparedStatement(conn, "C_STRUCTURE_HISTORY_MAXVER_BYTIME"); 160 stmt.setString(1, resource.getStructureId().toString()); 161 stmt.setLong(2, time); 162 res = stmt.executeQuery(); 163 if (res.next()) { 164 maxVersionByTime = res.getInt(1); 165 while (res.next()) { 166 // do nothing only move through all rows because of mssql odbc driver 167 } 168 } 169 m_sqlManager.closeAll(dbc, conn, stmt, res); 170 if (maxVersionByTime > 0) { 171 if (versionsToKeep < 0) { 172 versionsToKeep = (maxVersion - maxVersionByTime); 173 } else { 174 versionsToKeep = Math.min(versionsToKeep, (maxVersion - maxVersionByTime)); 175 } 176 } 177 } 178 int structureVersions = 0; 179 // get the minimal structure publish tag to keep for this sibling 180 conn = m_sqlManager.getConnection(dbc); 181 if (!noHistoryStructure) { 182 if ((versionsToKeep == -1) || ((maxVersion - versionsToKeep) <= 0)) { 183 // nothing to delete 184 internalCleanup(dbc, resource); 185 return 0; 186 } 187 188 // get the minimal structure publish tag to keep for this sibling 189 int minStrPublishTagToKeep = -1; 190 191 stmt = m_sqlManager.getPreparedStatement(conn, "C_HISTORY_READ_MAXTAG_FOR_VERSION"); 192 stmt.setString(1, resource.getStructureId().toString()); 193 stmt.setInt(2, (1 + maxVersion) - versionsToKeep); 194 res = stmt.executeQuery(); 195 if (res.next()) { 196 minStrPublishTagToKeep = res.getInt(1); 197 while (res.next()) { 198 // do nothing only move through all rows because of mssql odbc driver 199 } 200 } else { 201 // make sure the statement and the result is closed 202 m_sqlManager.closeAll(dbc, conn, stmt, res); 203 // nothing to delete 204 internalCleanup(dbc, resource); 205 return 0; 206 } 207 m_sqlManager.closeAll(dbc, conn, stmt, res); 208 if (minStrPublishTagToKeep < 1) { 209 // nothing to delete 210 internalCleanup(dbc, resource); 211 return 0; 212 } 213 minStrPublishTagToKeep++; 214 215 // delete the properties 216 conn = m_sqlManager.getConnection(dbc); 217 stmt = m_sqlManager.getPreparedStatement(conn, "C_PROPERTIES_HISTORY_DELETE"); 218 stmt.setString(1, resource.getStructureId().toString()); 219 stmt.setInt(2, minStrPublishTagToKeep); 220 stmt.executeUpdate(); 221 m_sqlManager.closeAll(dbc, null, stmt, null); 222 223 // delete the structure entries 224 stmt = m_sqlManager.getPreparedStatement(conn, "C_STRUCTURE_HISTORY_DELETE"); 225 stmt.setString(1, resource.getStructureId().toString()); 226 stmt.setInt(2, minStrPublishTagToKeep); 227 structureVersions = stmt.executeUpdate(); 228 m_sqlManager.closeAll(dbc, null, stmt, null); 229 } 230 231 // get the minimal resource publish tag to keep, 232 // all entries with publish tag less than this will be deleted 233 int minResPublishTagToKeep = -1; 234 stmt = m_sqlManager.getPreparedStatement(conn, "C_HISTORY_READ_MIN_USED_TAG"); 235 stmt.setString(1, resource.getResourceId().toString()); 236 res = stmt.executeQuery(); 237 if (res.next()) { 238 minResPublishTagToKeep = res.getInt(1); 239 if (res.wasNull()) { 240 // the database will return a row with a single NULL column if there are no rows at all for the given 241 // resource id. This means that we want to clean up all resource history and content history entries 242 // for this resource id, and we achieve this by comparing their publish tag with the maximum integer. 243 minResPublishTagToKeep = Integer.MAX_VALUE; 244 } 245 while (res.next()) { 246 // do nothing only move through all rows because of mssql odbc driver 247 } 248 } 249 m_sqlManager.closeAll(dbc, conn, stmt, res); 250 251 // delete the resource entries 252 conn = m_sqlManager.getConnection(dbc); 253 stmt = m_sqlManager.getPreparedStatement(conn, "C_RESOURCES_HISTORY_DELETE"); 254 stmt.setString(1, resource.getResourceId().toString()); 255 stmt.setInt(2, minResPublishTagToKeep); 256 int resourceVersions = stmt.executeUpdate(); 257 m_sqlManager.closeAll(dbc, null, stmt, null); 258 259 // delete the content entries 260 stmt = m_sqlManager.getPreparedStatement(conn, "C_CONTENT_HISTORY_DELETE"); 261 stmt.setString(1, resource.getResourceId().toString()); 262 stmt.setInt(2, minResPublishTagToKeep); 263 stmt.executeUpdate(); 264 265 // make sure the statement and the result is closed 266 m_sqlManager.closeAll(dbc, conn, stmt, res); 267 internalCleanup(dbc, resource); 268 return Math.max(structureVersions, resourceVersions); 269 } catch (SQLException e) { 270 throw new CmsDbSqlException( 271 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 272 e); 273 } finally { 274 m_sqlManager.closeAll(dbc, conn, stmt, res); 275 } 276 } 277 278 /** 279 * @see org.opencms.db.I_CmsHistoryDriver#deletePropertyDefinition(org.opencms.db.CmsDbContext, org.opencms.file.CmsPropertyDefinition) 280 */ 281 public void deletePropertyDefinition(CmsDbContext dbc, CmsPropertyDefinition metadef) 282 throws CmsDataAccessException { 283 284 Connection conn = null; 285 PreparedStatement stmt = null; 286 287 try { 288 if ((internalCountProperties(dbc, metadef, CmsProject.ONLINE_PROJECT_ID) != 0) 289 || (internalCountProperties(dbc, metadef, CmsUUID.getOpenCmsUUID()) != 0)) { // HACK: to get an offline project 290 291 throw new CmsDbConsistencyException( 292 Messages.get().container(Messages.ERR_ERROR_DELETING_PROPERTYDEF_1, metadef.getName())); 293 } 294 295 // delete the historical property definition 296 conn = m_sqlManager.getConnection(dbc); 297 stmt = m_sqlManager.getPreparedStatement(conn, "C_PROPERTYDEF_DELETE_HISTORY"); 298 stmt.setString(1, metadef.getId().toString()); 299 stmt.executeUpdate(); 300 } catch (SQLException e) { 301 throw new CmsDbSqlException( 302 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 303 e); 304 } finally { 305 m_sqlManager.closeAll(dbc, conn, stmt, null); 306 } 307 } 308 309 /** 310 * @see org.opencms.db.I_CmsHistoryDriver#destroy() 311 */ 312 public void destroy() throws Throwable { 313 314 m_sqlManager = null; 315 m_driverManager = null; 316 317 if (CmsLog.INIT.isInfoEnabled()) { 318 CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_SHUTDOWN_DRIVER_1, getClass().getName())); 319 } 320 } 321 322 /** 323 * @see org.opencms.db.I_CmsHistoryDriver#getAllDeletedEntries(org.opencms.db.CmsDbContext) 324 */ 325 public List<I_CmsHistoryResource> getAllDeletedEntries(CmsDbContext dbc) throws CmsDataAccessException { 326 327 Connection conn = null; 328 PreparedStatement stmt = null; 329 ResultSet res = null; 330 331 Map<CmsUUID, Integer> tmpEntrieis = new HashMap<CmsUUID, Integer>(); 332 List<I_CmsHistoryResource> entries = new ArrayList<I_CmsHistoryResource>(); 333 try { 334 conn = m_sqlManager.getConnection(dbc); 335 // get all not-deleted historical entries that may come in question 336 stmt = m_sqlManager.getPreparedStatement(conn, "C_STRUCTURE_HISTORY_READ_DELETED"); 337 res = stmt.executeQuery(); 338 while (res.next()) { 339 CmsUUID structureId = new CmsUUID(res.getString(1)); 340 int version = res.getInt(2); 341 tmpEntrieis.put(structureId, Integer.valueOf(version)); 342 } 343 } catch (SQLException e) { 344 throw new CmsDbSqlException( 345 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 346 e); 347 } finally { 348 m_sqlManager.closeAll(dbc, conn, stmt, res); 349 } 350 for (Map.Entry<CmsUUID, Integer> entry : tmpEntrieis.entrySet()) { 351 entries.add(readResource(dbc, entry.getKey(), entry.getValue().intValue())); 352 } 353 return entries; 354 } 355 356 /** 357 * @see org.opencms.db.I_CmsHistoryDriver#getAllNotDeletedEntries(org.opencms.db.CmsDbContext) 358 */ 359 public List<I_CmsHistoryResource> getAllNotDeletedEntries(CmsDbContext dbc) throws CmsDataAccessException { 360 361 Connection conn = null; 362 PreparedStatement stmt = null; 363 ResultSet res = null; 364 365 Map<CmsUUID, Integer> tmpEntrieis = new HashMap<CmsUUID, Integer>(); 366 367 List<I_CmsHistoryResource> entries = new ArrayList<I_CmsHistoryResource>(); 368 try { 369 conn = m_sqlManager.getConnection(dbc); 370 371 // get all not-deleted historical entries that may come in question 372 stmt = m_sqlManager.getPreparedStatement(conn, "C_STRUCTURE_HISTORY_READ_NOTDELETED"); 373 res = stmt.executeQuery(); 374 while (res.next()) { 375 CmsUUID structureId = new CmsUUID(res.getString(1)); 376 int version = res.getInt(2); 377 tmpEntrieis.put(structureId, Integer.valueOf(version)); 378 } 379 } catch (SQLException e) { 380 throw new CmsDbSqlException( 381 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 382 e); 383 } finally { 384 m_sqlManager.closeAll(dbc, conn, stmt, res); 385 } 386 387 for (Map.Entry<CmsUUID, Integer> entry : tmpEntrieis.entrySet()) { 388 entries.add(readResource(dbc, entry.getKey(), entry.getValue().intValue())); 389 } 390 return entries; 391 } 392 393 /** 394 * @see org.opencms.db.I_CmsHistoryDriver#getSqlManager() 395 */ 396 public CmsSqlManager getSqlManager() { 397 398 return m_sqlManager; 399 } 400 401 /** 402 * @see org.opencms.db.I_CmsDriver#init(org.opencms.db.CmsDbContext, org.opencms.configuration.CmsConfigurationManager, java.util.List, org.opencms.db.CmsDriverManager) 403 */ 404 public void init( 405 CmsDbContext dbc, 406 CmsConfigurationManager configurationManager, 407 List<String> successiveDrivers, 408 CmsDriverManager driverManager) { 409 410 CmsParameterConfiguration configuration = configurationManager.getConfiguration(); 411 412 String poolUrl; 413 if (configuration.get("db.history.pool") != null) { 414 poolUrl = configuration.get("db.history.pool").toString(); 415 } else { 416 // TODO: deprecated, remove as soon as possible 417 poolUrl = configuration.get("db.backup.pool").toString(); 418 } 419 420 String classname; 421 if (configuration.get("db.history.sqlmanager") != null) { 422 classname = configuration.get("db.history.sqlmanager").toString(); 423 } else { 424 // TODO: deprecated, remove as soon as possible 425 classname = configuration.get("db.backup.sqlmanager").toString(); 426 } 427 428 m_sqlManager = initSqlManager(classname); 429 m_sqlManager.init(I_CmsHistoryDriver.DRIVER_TYPE_ID, poolUrl); 430 431 m_driverManager = driverManager; 432 433 if (CmsLog.INIT.isInfoEnabled()) { 434 CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_ASSIGNED_POOL_1, poolUrl)); 435 } 436 437 if ((successiveDrivers != null) && !successiveDrivers.isEmpty()) { 438 if (LOG.isWarnEnabled()) { 439 LOG.warn( 440 Messages.get().getBundle().key( 441 Messages.LOG_SUCCESSIVE_DRIVERS_UNSUPPORTED_1, 442 getClass().getName())); 443 } 444 } 445 } 446 447 /** 448 * @see org.opencms.db.I_CmsHistoryDriver#initSqlManager(String) 449 */ 450 public org.opencms.db.generic.CmsSqlManager initSqlManager(String classname) { 451 452 return CmsSqlManager.getInstance(classname); 453 } 454 455 /** 456 * @see org.opencms.db.I_CmsHistoryDriver#readAllAvailableVersions(CmsDbContext, CmsUUID) 457 */ 458 public List<I_CmsHistoryResource> readAllAvailableVersions(CmsDbContext dbc, CmsUUID structureId) 459 throws CmsDataAccessException { 460 461 ResultSet res = null; 462 List<I_CmsHistoryResource> result = new ArrayList<I_CmsHistoryResource>(); 463 PreparedStatement stmt = null; 464 Connection conn = null; 465 466 try { 467 conn = m_sqlManager.getConnection(dbc); 468 469 // get all direct versions (where the structure entry has been written) 470 // sorted from the NEWEST to the OLDEST version (publish tag descendant) 471 List<I_CmsHistoryResource> historyResources = new ArrayList<I_CmsHistoryResource>(); 472 stmt = m_sqlManager.getPreparedStatement(conn, "C_RESOURCES_HISTORY_READ_ALL_VERSIONS"); 473 stmt.setString(1, structureId.toString()); 474 res = stmt.executeQuery(); 475 while (res.next()) { 476 historyResources.add(internalCreateResource(res)); 477 } 478 m_sqlManager.closeAll(dbc, null, stmt, res); 479 480 if (!historyResources.isEmpty()) { 481 // look for newer versions 482 // this is the NEWEST version, with the HIGHEST publish tag 483 I_CmsHistoryResource histRes = historyResources.get(0); 484 485 // look for later resource entries 486 stmt = m_sqlManager.getPreparedStatement(conn, "C_RESOURCES_HISTORY_READ_NEW_VERSIONS"); 487 stmt.setString(1, histRes.getResourceId().toString()); 488 stmt.setInt(2, histRes.getPublishTag()); 489 res = stmt.executeQuery(); 490 491 I_CmsHistoryResource lastHistRes = histRes; 492 // these are sorted from the oldest to the newest version (publish tag ascendent) 493 while (res.next()) { 494 int resVersion = res.getInt(m_sqlManager.readQuery("C_RESOURCES_VERSION")); 495 if (resVersion == lastHistRes.getResourceVersion()) { 496 // skip not interesting versions 497 continue; 498 } 499 I_CmsHistoryResource newHistRes = internalMergeResource(histRes, res, 0); 500 // add interesting versions, in the right order 501 result.add(0, newHistRes); 502 lastHistRes = newHistRes; 503 } 504 m_sqlManager.closeAll(dbc, null, stmt, res); 505 } 506 // iterate from the NEWEST to the OLDEST versions (publish tag descendant) 507 for (int i = 0; i < historyResources.size(); i++) { 508 I_CmsHistoryResource histRes = historyResources.get(i); 509 result.add(histRes); 510 if (i < (historyResources.size() - 1)) { 511 // this is one older direct version than histRes (histRes.getPublishTag() > histRes2.getPublishTag()) 512 I_CmsHistoryResource histRes2 = historyResources.get(i + 1); 513 514 // look for resource changes in between of the direct versions in ascendent order 515 stmt = m_sqlManager.getPreparedStatement(conn, "C_RESOURCES_HISTORY_READ_BTW_VERSIONS"); 516 stmt.setString(1, histRes.getResourceId().toString()); 517 stmt.setInt(2, histRes2.getPublishTag()); // lower limit 518 stmt.setInt(3, histRes.getPublishTag()); // upper limit 519 res = stmt.executeQuery(); 520 521 int pos = result.size(); 522 I_CmsHistoryResource lastHistRes = histRes2; 523 while (res.next()) { 524 int resVersion = res.getInt(m_sqlManager.readQuery("C_RESOURCES_VERSION")); 525 if (resVersion == lastHistRes.getResourceVersion()) { 526 // skip not interesting versions 527 continue; 528 } 529 I_CmsHistoryResource newHistRes = internalMergeResource(histRes2, res, 0); 530 // add interesting versions, in the right order 531 result.add(pos, newHistRes); 532 lastHistRes = newHistRes; 533 } 534 m_sqlManager.closeAll(dbc, null, stmt, res); 535 } 536 } 537 if (!result.isEmpty()) { 538 // get the oldest version 539 I_CmsHistoryResource histRes = result.get(result.size() - 1); 540 541 if (histRes.getVersion() > 1) { 542 // look for older resource versions, in descendant order 543 stmt = m_sqlManager.getPreparedStatement(conn, "C_RESOURCES_HISTORY_READ_OLD_VERSIONS"); 544 stmt.setString(1, histRes.getResourceId().toString()); 545 stmt.setInt(2, histRes.getPublishTag()); 546 res = stmt.executeQuery(); 547 548 int offset = (histRes.getStructureVersion() > 0 ? 1 : 0); 549 550 I_CmsHistoryResource lastHistRes = histRes; 551 while (res.next()) { 552 I_CmsHistoryResource newHistRes = internalMergeResource(histRes, res, offset); 553 if (newHistRes.getResourceVersion() != lastHistRes.getResourceVersion()) { 554 // only add interesting versions 555 if (offset == 1) { 556 if (histRes != lastHistRes) { 557 result.add(lastHistRes); 558 } 559 } else { 560 result.add(newHistRes); 561 } 562 } 563 lastHistRes = newHistRes; 564 } 565 // add the last one if there is one 566 if ((offset == 1) && (lastHistRes != histRes)) { 567 result.add(lastHistRes); 568 } 569 m_sqlManager.closeAll(dbc, null, stmt, res); 570 } 571 } 572 } catch (SQLException e) { 573 throw new CmsDbSqlException( 574 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 575 e); 576 } finally { 577 m_sqlManager.closeAll(dbc, conn, stmt, res); 578 } 579 580 return result; 581 } 582 583 /** 584 * @see org.opencms.db.I_CmsHistoryDriver#readContent(org.opencms.db.CmsDbContext, org.opencms.util.CmsUUID, int) 585 */ 586 public byte[] readContent(CmsDbContext dbc, CmsUUID resourceId, int publishTag) throws CmsDataAccessException { 587 588 Connection conn = null; 589 PreparedStatement stmt = null; 590 ResultSet res = null; 591 byte[] content = null; 592 593 try { 594 conn = m_sqlManager.getConnection(dbc); 595 stmt = m_sqlManager.getPreparedStatement(conn, "C_HISTORY_READ_CONTENT"); 596 stmt.setString(1, resourceId.toString()); 597 stmt.setInt(2, publishTag); 598 stmt.setInt(3, publishTag); 599 res = stmt.executeQuery(); 600 601 if (res.next()) { 602 content = m_sqlManager.getBytes(res, m_sqlManager.readQuery("C_RESOURCES_FILE_CONTENT")); 603 while (res.next()) { 604 // do nothing only move through all rows because of mssql odbc driver 605 } 606 } 607 } catch (SQLException e) { 608 throw new CmsDbSqlException( 609 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 610 e); 611 } finally { 612 m_sqlManager.closeAll(dbc, conn, stmt, res); 613 } 614 return content; 615 } 616 617 /** 618 * @see org.opencms.db.I_CmsHistoryDriver#readDeletedResources(CmsDbContext, CmsUUID, CmsUUID) 619 */ 620 public List<I_CmsHistoryResource> readDeletedResources(CmsDbContext dbc, CmsUUID structureId, CmsUUID userId) 621 throws CmsDataAccessException { 622 623 Connection conn = null; 624 PreparedStatement stmt = null; 625 ResultSet res = null; 626 List<I_CmsHistoryResource> result = new ArrayList<I_CmsHistoryResource>(); 627 List<I_CmsHistoryResource> tmpHistRes = new ArrayList<I_CmsHistoryResource>(); 628 629 try { 630 conn = m_sqlManager.getConnection(dbc); 631 if (userId == null) { 632 stmt = m_sqlManager.getPreparedStatement(conn, "C_RESOURCES_HISTORY_READ_DELETED"); 633 } else { 634 stmt = m_sqlManager.getPreparedStatement(conn, "C_RESOURCES_HISTORY_READ_DELETED_RESTRICTED"); 635 } 636 stmt.setString(1, structureId.toString()); 637 if (userId != null) { 638 stmt.setString(2, userId.toString()); 639 } 640 res = stmt.executeQuery(); 641 while (res.next()) { 642 // store the result into a temporary list 643 tmpHistRes.add(internalCreateResource(res)); 644 } 645 } catch (SQLException e) { 646 throw new CmsDbSqlException( 647 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 648 e); 649 } finally { 650 m_sqlManager.closeAll(dbc, conn, stmt, res); 651 } 652 I_CmsVfsDriver vfsDriver = m_driverManager.getVfsDriver(dbc); 653 for (I_CmsHistoryResource histRes : tmpHistRes) { 654 if (vfsDriver.validateStructureIdExists(dbc, dbc.currentProject().getUuid(), histRes.getStructureId())) { 655 // only add resources that are really deleted 656 continue; 657 } 658 result.add(histRes); 659 } 660 661 if (!result.isEmpty() 662 || (dbc.getRequestContext() == null) 663 || (dbc.getRequestContext().getAttribute("ATTR_RESOURCE_NAME") == null)) { 664 return result; 665 } 666 try { 667 conn = m_sqlManager.getConnection(dbc); 668 if (userId == null) { 669 stmt = m_sqlManager.getPreparedStatement(conn, "C_RESOURCES_HISTORY_READ_DELETED_NAME"); 670 } else { 671 stmt = m_sqlManager.getPreparedStatement(conn, "C_RESOURCES_HISTORY_READ_DELETED_NAME_RESTRICTED"); 672 } 673 String path = dbc.getRequestContext().getAttribute("ATTR_RESOURCE_NAME").toString(); 674 stmt.setString(1, path + '%'); 675 stmt.setString(2, path); 676 if (userId != null) { 677 stmt.setString(3, userId.toString()); 678 } 679 res = stmt.executeQuery(); 680 // clear the temporary list 681 tmpHistRes.clear(); 682 while (res.next()) { 683 // store the result into a temporary list 684 tmpHistRes.add(internalCreateResource(res)); 685 } 686 } catch (SQLException e) { 687 throw new CmsDbSqlException( 688 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 689 e); 690 } finally { 691 m_sqlManager.closeAll(dbc, conn, stmt, res); 692 } 693 for (I_CmsHistoryResource histRes : tmpHistRes) { 694 if (vfsDriver.validateStructureIdExists(dbc, dbc.currentProject().getUuid(), histRes.getStructureId())) { 695 // only add resources that are really deleted 696 continue; 697 } 698 result.add(histRes); 699 } 700 return result; 701 } 702 703 /** 704 * @see org.opencms.db.I_CmsHistoryDriver#readLastVersion(org.opencms.db.CmsDbContext, org.opencms.util.CmsUUID) 705 */ 706 public int readLastVersion(CmsDbContext dbc, CmsUUID structureId) throws CmsDataAccessException { 707 708 PreparedStatement stmt = null; 709 Connection conn = null; 710 ResultSet res = null; 711 int lastVersion = 0; 712 713 try { 714 conn = m_sqlManager.getConnection(dbc); 715 stmt = m_sqlManager.getPreparedStatement(conn, "C_STRUCTURE_HISTORY_MAXVER"); 716 stmt.setString(1, structureId.toString()); 717 res = stmt.executeQuery(); 718 719 if (res.next()) { 720 lastVersion = res.getInt(1); 721 while (res.next()) { 722 // do nothing only move through all rows because of mssql odbc driver 723 } 724 } else { 725 lastVersion = 0; 726 } 727 } catch (SQLException e) { 728 throw new CmsDbSqlException( 729 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 730 e); 731 } finally { 732 m_sqlManager.closeAll(dbc, conn, stmt, res); 733 } 734 735 return lastVersion; 736 } 737 738 /** 739 * @see org.opencms.db.I_CmsHistoryDriver#readMaxPublishTag(CmsDbContext, CmsUUID) 740 */ 741 public int readMaxPublishTag(CmsDbContext dbc, CmsUUID resourceId) throws CmsDataAccessException { 742 743 PreparedStatement stmt = null; 744 Connection conn = null; 745 ResultSet res = null; 746 int result = 0; 747 748 try { 749 conn = m_sqlManager.getConnection(dbc); 750 stmt = m_sqlManager.getPreparedStatement(conn, "C_RESOURCES_READ_MAX_PUBLISH_TAG"); 751 stmt.setString(1, resourceId.toString()); 752 res = stmt.executeQuery(); 753 754 if (res.next()) { 755 result = res.getInt(1); 756 while (res.next()) { 757 // do nothing only move through all rows because of mssql odbc driver 758 } 759 } 760 } catch (SQLException e) { 761 throw new CmsDbSqlException( 762 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 763 e); 764 } finally { 765 m_sqlManager.closeAll(dbc, conn, stmt, res); 766 } 767 768 return result; 769 } 770 771 /** 772 * @see org.opencms.db.I_CmsHistoryDriver#readNextPublishTag(org.opencms.db.CmsDbContext) 773 */ 774 public int readNextPublishTag(CmsDbContext dbc) { 775 776 PreparedStatement stmt = null; 777 Connection conn = null; 778 ResultSet res = null; 779 int projectPublishTag = 1; 780 int resourcePublishTag = 1; 781 782 try { 783 // get the max publish tag from project history 784 conn = m_sqlManager.getConnection(dbc); 785 stmt = m_sqlManager.getPreparedStatement(conn, "C_PROJECTS_HISTORY_MAXTAG"); 786 res = stmt.executeQuery(); 787 788 if (res.next()) { 789 projectPublishTag = res.getInt(1) + 1; 790 while (res.next()) { 791 // do nothing only move through all rows because of mssql odbc driver 792 } 793 } 794 } catch (SQLException exc) { 795 LOG.error(Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), exc); 796 } finally { 797 m_sqlManager.closeAll(dbc, null, stmt, res); 798 } 799 800 try { 801 // get the max publish tag from resource history 802 stmt = m_sqlManager.getPreparedStatement(conn, "C_RESOURCES_HISTORY_MAXTAG"); 803 res = stmt.executeQuery(); 804 805 if (res.next()) { 806 resourcePublishTag = res.getInt(1) + 1; 807 while (res.next()) { 808 // do nothing only move through all rows because of mssql odbc driver 809 } 810 } 811 } catch (SQLException exc) { 812 LOG.error(Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), exc); 813 } finally { 814 m_sqlManager.closeAll(dbc, null, stmt, res); 815 } 816 817 // keep the biggest 818 if (resourcePublishTag > projectPublishTag) { 819 projectPublishTag = resourcePublishTag; 820 } 821 822 try { 823 // get the max publish tag from contents 824 stmt = m_sqlManager.getPreparedStatement(conn, "C_CONTENT_PUBLISH_MAXTAG"); 825 res = stmt.executeQuery(); 826 827 if (res.next()) { 828 resourcePublishTag = res.getInt(1) + 1; 829 while (res.next()) { 830 // do nothing only move through all rows because of mssql odbc driver 831 } 832 } 833 } catch (SQLException exc) { 834 LOG.error(Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), exc); 835 } finally { 836 m_sqlManager.closeAll(dbc, conn, stmt, res); 837 } 838 839 // return the biggest 840 if (resourcePublishTag > projectPublishTag) { 841 projectPublishTag = resourcePublishTag; 842 } 843 844 return projectPublishTag; 845 } 846 847 /** 848 * @see org.opencms.db.I_CmsHistoryDriver#readPrincipal(org.opencms.db.CmsDbContext, org.opencms.util.CmsUUID) 849 */ 850 public CmsHistoryPrincipal readPrincipal(CmsDbContext dbc, CmsUUID principalId) throws CmsDataAccessException { 851 852 Connection conn = null; 853 PreparedStatement stmt = null; 854 ResultSet res = null; 855 CmsHistoryPrincipal historyPrincipal = null; 856 857 try { 858 conn = m_sqlManager.getConnection(dbc); 859 stmt = m_sqlManager.getPreparedStatement(conn, "C_HISTORY_PRINCIPAL_READ"); 860 stmt.setString(1, principalId.toString()); 861 res = stmt.executeQuery(); 862 if (res.next()) { 863 String userName = res.getString(m_sqlManager.readQuery("C_PRINCIPALS_HISTORY_NAME")); 864 String ou = CmsOrganizationalUnit.removeLeadingSeparator( 865 res.getString(m_sqlManager.readQuery("C_PRINCIPALS_HISTORY_OU"))); 866 historyPrincipal = new CmsHistoryPrincipal( 867 principalId, 868 ou + userName, 869 res.getString(m_sqlManager.readQuery("C_PRINCIPALS_HISTORY_DESCRIPTION")), 870 res.getString(m_sqlManager.readQuery("C_PRINCIPALS_HISTORY_EMAIL")), 871 res.getString(m_sqlManager.readQuery("C_PRINCIPALS_HISTORY_TYPE")), 872 new CmsUUID(res.getString(m_sqlManager.readQuery("C_PRINCIPALS_HISTORY_USERDELETED"))), 873 res.getLong(m_sqlManager.readQuery("C_PRINCIPALS_HISTORY_DATEDELETED"))); 874 while (res.next()) { 875 // do nothing only move through all rows because of mssql odbc driver 876 } 877 } else { 878 throw new CmsDbEntryNotFoundException( 879 Messages.get().container(Messages.ERR_HISTORY_PRINCIPAL_NOT_FOUND_1, principalId)); 880 } 881 } catch (SQLException e) { 882 throw new CmsDbSqlException( 883 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 884 e); 885 } finally { 886 m_sqlManager.closeAll(dbc, conn, stmt, res); 887 } 888 return historyPrincipal; 889 } 890 891 /** 892 * @see org.opencms.db.I_CmsHistoryDriver#readProject(org.opencms.db.CmsDbContext, CmsUUID) 893 */ 894 public CmsHistoryProject readProject(CmsDbContext dbc, CmsUUID projectId) throws CmsDataAccessException { 895 896 PreparedStatement stmt = null; 897 CmsHistoryProject project = null; 898 ResultSet res = null; 899 Connection conn = null; 900 901 int tmpTag; 902 903 try { 904 conn = m_sqlManager.getConnection(dbc); 905 stmt = m_sqlManager.getPreparedStatement(conn, "C_PROJECTS_HISTORY_READ_BYID"); 906 907 stmt.setString(1, projectId.toString()); 908 res = stmt.executeQuery(); 909 910 if (res.next()) { 911 tmpTag = res.getInt(m_sqlManager.readQuery("C_PROJECTS_PUBLISH_TAG_0")); 912 project = internalCreateProject(res, null); 913 while (res.next()) { 914 // do nothing only move through all rows because of mssql odbc driver 915 } 916 } else { 917 throw new CmsDbEntryNotFoundException( 918 Messages.get().container(Messages.ERR_NO_HISTORY_PROJECT_WITH_ID_1, projectId)); 919 } 920 } catch (SQLException e) { 921 throw new CmsDbSqlException( 922 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 923 e); 924 } finally { 925 m_sqlManager.closeAll(dbc, conn, stmt, res); 926 } 927 928 List<String> projectresources = readProjectResources(dbc, tmpTag); 929 project.setProjectResources(projectresources); 930 931 return project; 932 } 933 934 /** 935 * @see org.opencms.db.I_CmsHistoryDriver#readProject(org.opencms.db.CmsDbContext, int) 936 */ 937 public CmsHistoryProject readProject(CmsDbContext dbc, int publishTag) throws CmsDataAccessException { 938 939 PreparedStatement stmt = null; 940 CmsHistoryProject project = null; 941 ResultSet res = null; 942 Connection conn = null; 943 try { 944 conn = m_sqlManager.getConnection(dbc); 945 stmt = m_sqlManager.getPreparedStatement(conn, "C_PROJECTS_HISTORY_READ"); 946 947 stmt.setInt(1, publishTag); 948 res = stmt.executeQuery(); 949 950 if (res.next()) { 951 project = internalCreateProject(res, null); 952 while (res.next()) { 953 // do nothing only move through all rows because of mssql odbc driver 954 } 955 } else { 956 throw new CmsDbEntryNotFoundException( 957 Messages.get().container( 958 Messages.ERR_NO_HISTORY_PROJECT_WITH_TAG_ID_1, 959 Integer.valueOf(publishTag))); 960 } 961 } catch (SQLException e) { 962 throw new CmsDbSqlException( 963 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 964 e); 965 } finally { 966 m_sqlManager.closeAll(dbc, conn, stmt, res); 967 } 968 969 List<String> projectresources = readProjectResources(dbc, publishTag); 970 project.setProjectResources(projectresources); 971 972 return project; 973 } 974 975 /** 976 * @see org.opencms.db.I_CmsHistoryDriver#readProjectResources(org.opencms.db.CmsDbContext, int) 977 */ 978 public List<String> readProjectResources(CmsDbContext dbc, int publishTag) throws CmsDataAccessException { 979 980 PreparedStatement stmt = null; 981 Connection conn = null; 982 ResultSet res = null; 983 List<String> projectResources = new ArrayList<String>(); 984 985 try { 986 conn = m_sqlManager.getConnection(dbc); 987 stmt = m_sqlManager.getPreparedStatement(conn, "C_PROJECTRESOURCES_HISTORY_READ"); 988 stmt.setInt(1, publishTag); 989 res = stmt.executeQuery(); 990 while (res.next()) { 991 projectResources.add(res.getString("RESOURCE_PATH")); 992 } 993 } catch (SQLException e) { 994 throw new CmsDbSqlException( 995 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 996 e); 997 } finally { 998 m_sqlManager.closeAll(dbc, conn, stmt, res); 999 } 1000 1001 return projectResources; 1002 } 1003 1004 /** 1005 * @see org.opencms.db.I_CmsHistoryDriver#readProjects(org.opencms.db.CmsDbContext) 1006 */ 1007 public List<CmsHistoryProject> readProjects(CmsDbContext dbc) throws CmsDataAccessException { 1008 1009 List<CmsHistoryProject> projects = new ArrayList<CmsHistoryProject>(); 1010 ResultSet res = null; 1011 PreparedStatement stmt = null; 1012 Connection conn = null; 1013 1014 Map<Integer, CmsHistoryProject> tmpProjects = new HashMap<Integer, CmsHistoryProject>(); 1015 1016 try { 1017 // create the statement 1018 conn = m_sqlManager.getConnection(dbc); 1019 stmt = m_sqlManager.getPreparedStatement(conn, "C_PROJECTS_HISTORY_READ_ALL"); 1020 res = stmt.executeQuery(); 1021 1022 // this is not really efficient 1023 // but it is overriden in all db specific implementations, including mysql 1024 int i = 0; 1025 int max = 300; 1026 1027 while (res.next() && (i < max)) { 1028 tmpProjects.put(Integer.valueOf(res.getInt("PUBLISH_TAG")), internalCreateProject(res, null)); 1029 i++; 1030 } 1031 } catch (SQLException e) { 1032 throw new CmsDbSqlException( 1033 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 1034 e); 1035 } finally { 1036 m_sqlManager.closeAll(dbc, conn, stmt, res); 1037 } 1038 1039 for (Map.Entry<Integer, CmsHistoryProject> entry : tmpProjects.entrySet()) { 1040 List<String> resources = readProjectResources(dbc, entry.getKey().intValue()); 1041 entry.getValue().setProjectResources(resources); 1042 projects.add(entry.getValue()); 1043 } 1044 1045 return projects; 1046 } 1047 1048 /** 1049 * @see org.opencms.db.I_CmsHistoryDriver#readProperties(org.opencms.db.CmsDbContext, org.opencms.file.history.I_CmsHistoryResource) 1050 */ 1051 public List<CmsProperty> readProperties(CmsDbContext dbc, I_CmsHistoryResource resource) 1052 throws CmsDataAccessException { 1053 1054 ResultSet res = null; 1055 PreparedStatement stmt = null; 1056 Connection conn = null; 1057 1058 Map<String, CmsProperty> propertyMap = new HashMap<String, CmsProperty>(); 1059 1060 try { 1061 conn = m_sqlManager.getConnection(dbc); 1062 1063 // get the latest properties for this sibling 1064 int pubTag = -1; 1065 stmt = m_sqlManager.getPreparedStatement(conn, "C_PROPERTIES_HISTORY_READ_PUBTAG"); 1066 stmt.setString(1, resource.getStructureId().toString()); 1067 stmt.setInt(2, resource.getPublishTag()); 1068 res = stmt.executeQuery(); 1069 if (res.next()) { 1070 pubTag = res.getInt(1); 1071 while (res.next()) { 1072 // do nothing only move through all rows because of mssql odbc driver 1073 } 1074 } 1075 m_sqlManager.closeAll(dbc, null, stmt, res); 1076 1077 if (pubTag > 0) { 1078 // add the siblings props 1079 stmt = m_sqlManager.getPreparedStatement(conn, "C_PROPERTIES_HISTORY_READALL_STR"); 1080 stmt.setString(1, resource.getStructureId().toString()); 1081 stmt.setInt(2, pubTag); 1082 res = stmt.executeQuery(); 1083 1084 while (res.next()) { 1085 String propertyKey = res.getString(1); 1086 String propertyValue = res.getString(2); 1087 int mappingType = res.getInt(3); 1088 1089 internalAddToPropMap(propertyMap, resource, propertyKey, propertyValue, mappingType); 1090 } 1091 m_sqlManager.closeAll(dbc, null, stmt, res); 1092 } 1093 1094 if (pubTag != resource.getPublishTag()) { 1095 // check if there were newer shared properties modifications 1096 stmt = m_sqlManager.getPreparedStatement(conn, "C_PROPERTIES_HISTORY_READALL_RES"); 1097 stmt.setString(1, resource.getStructureId().toString()); 1098 stmt.setInt(2, resource.getPublishTag()); 1099 res = stmt.executeQuery(); 1100 1101 while (res.next()) { 1102 String propertyKey = res.getString(1); 1103 String propertyValue = res.getString(2); 1104 int mappingType = res.getInt(3); 1105 1106 internalAddToPropMap(propertyMap, resource, propertyKey, propertyValue, mappingType); 1107 } 1108 m_sqlManager.closeAll(dbc, null, stmt, res); 1109 } 1110 } catch (SQLException e) { 1111 throw new CmsDbSqlException( 1112 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 1113 e); 1114 } finally { 1115 m_sqlManager.closeAll(dbc, conn, stmt, res); 1116 } 1117 1118 return new ArrayList<CmsProperty>(propertyMap.values()); 1119 } 1120 1121 /** 1122 * @see org.opencms.db.I_CmsHistoryDriver#readPropertyDefinition(org.opencms.db.CmsDbContext, java.lang.String) 1123 */ 1124 public CmsPropertyDefinition readPropertyDefinition(CmsDbContext dbc, String name) throws CmsDataAccessException { 1125 1126 CmsPropertyDefinition propDef = null; 1127 ResultSet res = null; 1128 PreparedStatement stmt = null; 1129 Connection conn = null; 1130 1131 try { 1132 conn = m_sqlManager.getConnection(dbc); 1133 stmt = m_sqlManager.getPreparedStatement(conn, "C_PROPERTYDEF_READ_HISTORY"); 1134 stmt.setString(1, name); 1135 res = stmt.executeQuery(); 1136 1137 if (res.next()) { 1138 propDef = new CmsPropertyDefinition( 1139 new CmsUUID(res.getString(m_sqlManager.readQuery("C_PROPERTYDEF_ID"))), 1140 res.getString(m_sqlManager.readQuery("C_PROPERTYDEF_NAME")), 1141 CmsPropertyDefinition.CmsPropertyType.valueOf( 1142 res.getInt(m_sqlManager.readQuery("C_PROPERTYDEF_TYPE")))); 1143 while (res.next()) { 1144 // do nothing only move through all rows because of mssql odbc driver 1145 } 1146 } else { 1147 throw new CmsDbEntryNotFoundException( 1148 Messages.get().container(Messages.ERR_NO_PROPERTYDEF_WITH_NAME_1, name)); 1149 } 1150 } catch (SQLException e) { 1151 throw new CmsDbSqlException( 1152 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 1153 e); 1154 } finally { 1155 m_sqlManager.closeAll(dbc, conn, stmt, res); 1156 } 1157 1158 return propDef; 1159 } 1160 1161 /** 1162 * @see org.opencms.db.I_CmsHistoryDriver#readPublishTag(org.opencms.db.CmsDbContext, long) 1163 */ 1164 public int readPublishTag(CmsDbContext dbc, long maxdate) throws CmsDataAccessException { 1165 1166 ResultSet res = null; 1167 PreparedStatement stmt = null; 1168 Connection conn = null; 1169 int maxVersion = 0; 1170 1171 try { 1172 conn = m_sqlManager.getConnection(dbc); 1173 stmt = m_sqlManager.getPreparedStatement(conn, "C_PROJECTS_HISTORY_READ_TAG_FOR_DATE"); 1174 stmt.setLong(1, maxdate); 1175 res = stmt.executeQuery(); 1176 if (res.next()) { 1177 maxVersion = res.getInt(1); 1178 while (res.next()) { 1179 // do nothing only move through all rows because of mssql odbc driver 1180 } 1181 } 1182 } catch (SQLException e) { 1183 throw new CmsDbSqlException( 1184 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 1185 e); 1186 } finally { 1187 m_sqlManager.closeAll(dbc, conn, stmt, res); 1188 } 1189 return maxVersion; 1190 } 1191 1192 /** 1193 * @see org.opencms.db.I_CmsHistoryDriver#readResource(CmsDbContext, CmsUUID, int) 1194 */ 1195 public I_CmsHistoryResource readResource(CmsDbContext dbc, CmsUUID structureId, int version) 1196 throws CmsDataAccessException { 1197 1198 I_CmsHistoryResource resource = null; 1199 PreparedStatement stmt = null; 1200 ResultSet res = null; 1201 Connection conn = null; 1202 1203 try { 1204 conn = m_sqlManager.getConnection(dbc); 1205 stmt = m_sqlManager.getPreparedStatement(conn, "C_RESOURCES_HISTORY_READ_VERSION"); 1206 stmt.setString(1, structureId.toString()); 1207 stmt.setInt(2, version); 1208 res = stmt.executeQuery(); 1209 if (res.next()) { 1210 resource = internalCreateResource(res); 1211 while (res.next()) { 1212 // do nothing only move through all rows because of mssql odbc driver 1213 } 1214 } else { 1215 throw new CmsVfsResourceNotFoundException( 1216 Messages.get().container(Messages.ERR_HISTORY_FILE_NOT_FOUND_1, structureId)); 1217 } 1218 } catch (SQLException e) { 1219 throw new CmsDbSqlException( 1220 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 1221 e); 1222 } finally { 1223 m_sqlManager.closeAll(dbc, conn, stmt, res); 1224 } 1225 return resource; 1226 } 1227 1228 /** 1229 * @see org.opencms.db.I_CmsHistoryDriver#setDriverManager(org.opencms.db.CmsDriverManager) 1230 */ 1231 public void setDriverManager(CmsDriverManager driverManager) { 1232 1233 m_driverManager = driverManager; 1234 } 1235 1236 /** 1237 * @see org.opencms.db.I_CmsHistoryDriver#setSqlManager(org.opencms.db.CmsSqlManager) 1238 */ 1239 public void setSqlManager(org.opencms.db.CmsSqlManager sqlManager) { 1240 1241 m_sqlManager = (CmsSqlManager)sqlManager; 1242 } 1243 1244 /** 1245 * @see org.opencms.db.I_CmsHistoryDriver#writePrincipal(CmsDbContext, org.opencms.security.I_CmsPrincipal) 1246 */ 1247 public void writePrincipal(CmsDbContext dbc, I_CmsPrincipal principal) throws CmsDataAccessException { 1248 1249 Connection conn = null; 1250 PreparedStatement stmt = null; 1251 1252 try { 1253 // check if the principal was already saved 1254 readPrincipal(dbc, principal.getId()); 1255 return; 1256 } catch (CmsDbEntryNotFoundException e) { 1257 // ok 1258 } 1259 try { 1260 conn = m_sqlManager.getConnection(dbc); 1261 stmt = m_sqlManager.getPreparedStatement(conn, "C_HISTORY_PRINCIPAL_CREATE"); 1262 stmt.setString(1, principal.getId().toString()); 1263 stmt.setString(2, principal.getSimpleName()); 1264 String desc = principal.getDescription(); 1265 desc = CmsStringUtil.isEmptyOrWhitespaceOnly(desc) ? "-" : desc; 1266 stmt.setString(3, desc); 1267 stmt.setString(4, CmsOrganizationalUnit.SEPARATOR + principal.getOuFqn()); 1268 if (principal instanceof CmsUser) { 1269 String email = ((CmsUser)principal).getEmail(); 1270 email = CmsStringUtil.isEmptyOrWhitespaceOnly(email) ? "-" : email; 1271 stmt.setString(5, email); 1272 stmt.setString(6, I_CmsPrincipal.PRINCIPAL_USER); 1273 } else { 1274 stmt.setString(5, "-"); 1275 stmt.setString(6, I_CmsPrincipal.PRINCIPAL_GROUP); 1276 } 1277 stmt.setString(7, dbc.currentUser().getId().toString()); 1278 stmt.setLong(8, System.currentTimeMillis()); 1279 1280 stmt.executeUpdate(); 1281 } catch (SQLException e) { 1282 throw new CmsDbSqlException( 1283 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 1284 e); 1285 } finally { 1286 m_sqlManager.closeAll(dbc, conn, stmt, null); 1287 } 1288 } 1289 1290 /** 1291 * @see org.opencms.db.I_CmsHistoryDriver#writeProject(org.opencms.db.CmsDbContext, int, long) 1292 */ 1293 public void writeProject(CmsDbContext dbc, int publishTag, long publishDate) throws CmsDataAccessException { 1294 1295 CmsProject currentProject = dbc.currentProject(); 1296 CmsUser currentUser = dbc.currentUser(); 1297 1298 List<String> projectresources = m_driverManager.getProjectDriver(dbc).readProjectResources(dbc, currentProject); 1299 1300 // write historical project to the database 1301 Connection conn = null; 1302 PreparedStatement stmt = null; 1303 try { 1304 conn = m_sqlManager.getConnection(dbc); 1305 1306 stmt = m_sqlManager.getPreparedStatement(conn, "C_PROJECTS_HISTORY_CREATE"); 1307 // first write the project 1308 stmt.setInt(1, publishTag); 1309 stmt.setString(2, currentProject.getUuid().toString()); 1310 stmt.setString(3, currentProject.getSimpleName()); 1311 stmt.setLong(4, publishDate); 1312 stmt.setString(5, currentUser.getId().toString()); 1313 stmt.setString(6, currentProject.getOwnerId().toString()); 1314 stmt.setString(7, currentProject.getGroupId().toString()); 1315 stmt.setString(8, currentProject.getManagerGroupId().toString()); 1316 stmt.setString(9, currentProject.getDescription()); 1317 stmt.setLong(10, currentProject.getDateCreated()); 1318 stmt.setInt(11, currentProject.getType().getMode()); 1319 stmt.setString(12, CmsOrganizationalUnit.SEPARATOR + currentProject.getOuFqn()); 1320 stmt.executeUpdate(); 1321 1322 m_sqlManager.closeAll(dbc, null, stmt, null); 1323 1324 // now write the projectresources 1325 stmt = m_sqlManager.getPreparedStatement(conn, "C_PROJECTRESOURCES_HISTORY_CREATE"); 1326 Iterator<String> i = projectresources.iterator(); 1327 while (i.hasNext()) { 1328 stmt.setInt(1, publishTag); 1329 stmt.setString(2, currentProject.getUuid().toString()); 1330 stmt.setString(3, i.next()); 1331 stmt.executeUpdate(); 1332 stmt.clearParameters(); 1333 } 1334 } catch (SQLException e) { 1335 throw new CmsDbSqlException( 1336 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 1337 e); 1338 } finally { 1339 m_sqlManager.closeAll(dbc, conn, stmt, null); 1340 } 1341 } 1342 1343 /** 1344 * @see org.opencms.db.I_CmsHistoryDriver#writeProperties(org.opencms.db.CmsDbContext, org.opencms.file.CmsResource, java.util.List, int) 1345 */ 1346 public void writeProperties(CmsDbContext dbc, CmsResource resource, List<CmsProperty> properties, int publishTag) 1347 throws CmsDataAccessException { 1348 1349 Connection conn = null; 1350 PreparedStatement stmt = null; 1351 1352 Map<CmsProperty, CmsPropertyDefinition> propDefs = new HashMap<CmsProperty, CmsPropertyDefinition>(); 1353 1354 try { 1355 for (CmsProperty property : properties) { 1356 CmsPropertyDefinition propDef = null; 1357 try { 1358 propDef = readPropertyDefinition(dbc, property.getName()); 1359 } catch (CmsDbEntryNotFoundException e) { 1360 // create if missing 1361 propDef = createPropertyDefinition(dbc, property.getName(), CmsPropertyDefinition.TYPE_NORMAL); 1362 } 1363 propDefs.put(property, propDef); 1364 } 1365 } catch (CmsDataAccessException e) { 1366 throw new CmsDbSqlException( 1367 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 1368 e); 1369 } finally { 1370 m_sqlManager.closeAll(dbc, conn, stmt, null); 1371 } 1372 1373 try { 1374 conn = m_sqlManager.getConnection(dbc); 1375 for (Map.Entry<CmsProperty, CmsPropertyDefinition> entry : propDefs.entrySet()) { 1376 1377 for (int i = 0; i < 2; i++) { 1378 int mappingType; 1379 String value; 1380 CmsUUID id; 1381 if (i == 0) { 1382 // write the structure value on the first cycle 1383 value = entry.getKey().getStructureValue(); 1384 mappingType = CmsProperty.STRUCTURE_RECORD_MAPPING; 1385 id = resource.getStructureId(); 1386 if (CmsStringUtil.isEmpty(value)) { 1387 continue; 1388 } 1389 } else { 1390 // write the resource value on the second cycle 1391 value = entry.getKey().getResourceValue(); 1392 mappingType = CmsProperty.RESOURCE_RECORD_MAPPING; 1393 id = resource.getResourceId(); 1394 if (CmsStringUtil.isEmpty(value)) { 1395 break; 1396 } 1397 } 1398 1399 stmt = m_sqlManager.getPreparedStatement(conn, "C_PROPERTIES_HISTORY_CREATE"); 1400 1401 stmt.setString(1, resource.getStructureId().toString()); 1402 stmt.setString(2, entry.getValue().getId().toString()); 1403 stmt.setString(3, id.toString()); 1404 stmt.setInt(4, mappingType); 1405 stmt.setString(5, m_sqlManager.validateEmpty(value)); 1406 stmt.setInt(6, publishTag); 1407 1408 stmt.executeUpdate(); 1409 m_sqlManager.closeAll(dbc, null, stmt, null); 1410 } 1411 } 1412 } catch (SQLException e) { 1413 throw new CmsDbSqlException( 1414 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 1415 e); 1416 } finally { 1417 m_sqlManager.closeAll(dbc, conn, stmt, null); 1418 } 1419 } 1420 1421 /** 1422 * @see org.opencms.db.I_CmsHistoryDriver#writeResource(org.opencms.db.CmsDbContext, org.opencms.file.CmsResource, java.util.List, int) 1423 */ 1424 public void writeResource(CmsDbContext dbc, CmsResource resource, List<CmsProperty> properties, int publishTag) 1425 throws CmsDataAccessException { 1426 1427 Connection conn = null; 1428 PreparedStatement stmt = null; 1429 1430 try { 1431 boolean valResource = internalValidateResource(dbc, resource, publishTag); 1432 int sibCount = resource.getSiblingCount(); 1433 1434 // if deleted 1435 if (resource.getState().isDeleted()) { 1436 // if it is a file 1437 if (resource instanceof CmsFile) { 1438 if (!valResource) { 1439 if (sibCount < 2) { 1440 // copy from offline content to content tables 1441 // so that the history contains the last state of the file 1442 m_driverManager.getVfsDriver(dbc).createOnlineContent( 1443 dbc, 1444 resource.getResourceId(), 1445 ((CmsFile)resource).getContents(), 1446 publishTag, 1447 false, 1448 true); 1449 } else { 1450 @SuppressWarnings("unchecked") 1451 Set<CmsUUID> changedAndDeleted = (Set<CmsUUID>)dbc.getAttribute( 1452 CmsDriverManager.KEY_CHANGED_AND_DELETED); 1453 if ((changedAndDeleted == null) || !changedAndDeleted.contains(resource.getResourceId())) { 1454 // put the content definitively in the history if no sibling is left 1455 // (unless another sibling with status "changed" or "new" is published) 1456 m_driverManager.getVfsDriver(dbc).createOnlineContent( 1457 dbc, 1458 resource.getResourceId(), 1459 ((CmsFile)resource).getContents(), 1460 publishTag, 1461 true, 1462 false); 1463 } 1464 } 1465 } 1466 } 1467 1468 // update version numbers 1469 m_driverManager.getVfsDriver(dbc).publishVersions(dbc, resource, !valResource); 1470 } 1471 1472 // read the version numbers 1473 Map<String, Integer> versions = m_driverManager.getVfsDriver(dbc).readVersions( 1474 dbc, 1475 CmsProject.ONLINE_PROJECT_ID, 1476 resource.getResourceId(), 1477 resource.getStructureId()); 1478 int structureVersion = (versions.get("structure")).intValue(); 1479 int resourceVersion = (versions.get("resource")).intValue(); 1480 1481 CmsUUID parentId = CmsUUID.getNullUUID(); 1482 CmsFolder parent = m_driverManager.getVfsDriver(dbc).readParentFolder( 1483 dbc, 1484 CmsProject.ONLINE_PROJECT_ID, 1485 resource.getStructureId()); 1486 if (parent != null) { 1487 parentId = parent.getStructureId(); 1488 } 1489 1490 conn = m_sqlManager.getConnection(dbc); 1491 if (!valResource) { 1492 // write the resource 1493 stmt = m_sqlManager.getPreparedStatement(conn, "C_RESOURCES_HISTORY_WRITE"); 1494 stmt.setString(1, resource.getResourceId().toString()); 1495 stmt.setInt(2, resource.getTypeId()); 1496 stmt.setInt(3, resource.getFlags()); 1497 stmt.setLong(4, resource.getDateCreated()); 1498 stmt.setString(5, resource.getUserCreated().toString()); 1499 stmt.setLong(6, resource.getDateLastModified()); 1500 stmt.setString(7, resource.getUserLastModified().toString()); 1501 stmt.setInt(8, resource.getState().getState()); 1502 stmt.setInt(9, resource.getLength()); 1503 stmt.setLong(10, resource.getDateContent()); 1504 stmt.setString(11, dbc.currentProject().getUuid().toString()); 1505 stmt.setInt(12, resource.getSiblingCount()); 1506 stmt.setInt(13, resourceVersion); 1507 stmt.setInt(14, publishTag); 1508 stmt.executeUpdate(); 1509 m_sqlManager.closeAll(dbc, null, stmt, null); 1510 } 1511 // write the structure 1512 stmt = m_sqlManager.getPreparedStatement(conn, "C_STRUCTURE_HISTORY_WRITE"); 1513 stmt.setString(1, resource.getStructureId().toString()); 1514 stmt.setString(2, resource.getResourceId().toString()); 1515 stmt.setString(3, resource.getRootPath()); 1516 stmt.setInt(4, resource.getState().getState()); 1517 stmt.setLong(5, resource.getDateReleased()); 1518 stmt.setLong(6, resource.getDateExpired()); 1519 stmt.setInt(7, structureVersion); 1520 stmt.setString(8, parentId.toString()); 1521 stmt.setInt(9, publishTag); 1522 stmt.setInt(10, resource.getVersion()); 1523 stmt.executeUpdate(); 1524 } catch (SQLException e) { 1525 throw new CmsDbSqlException( 1526 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 1527 e); 1528 } finally { 1529 m_sqlManager.closeAll(dbc, conn, stmt, null); 1530 } 1531 1532 writeProperties(dbc, resource, properties, publishTag); 1533 } 1534 1535 /** 1536 * Updates the property map for the given resource with the given property data.<p> 1537 * 1538 * @param propertyMap the map to update 1539 * @param resource the resource the properties belong to 1540 * @param propertyKey the property key 1541 * @param propertyValue the property value 1542 * @param mappingType the mapping type 1543 * 1544 * @throws CmsDbConsistencyException if the mapping type is wrong 1545 */ 1546 protected void internalAddToPropMap( 1547 Map<String, CmsProperty> propertyMap, 1548 I_CmsHistoryResource resource, 1549 String propertyKey, 1550 String propertyValue, 1551 int mappingType) 1552 throws CmsDbConsistencyException { 1553 1554 CmsProperty property = propertyMap.get(propertyKey); 1555 if (property != null) { 1556 // there exists already a property for this key in the result 1557 switch (mappingType) { 1558 case CmsProperty.STRUCTURE_RECORD_MAPPING: 1559 // this property value is mapped to a structure record 1560 property.setStructureValue(propertyValue); 1561 break; 1562 case CmsProperty.RESOURCE_RECORD_MAPPING: 1563 // this property value is mapped to a resource record 1564 property.setResourceValue(propertyValue); 1565 break; 1566 default: 1567 throw new CmsDbConsistencyException( 1568 Messages.get().container( 1569 Messages.ERR_UNKNOWN_PROPERTY_VALUE_MAPPING_3, 1570 resource.getRootPath(), 1571 Integer.valueOf(mappingType), 1572 propertyKey)); 1573 } 1574 } else { 1575 // there doesn't exist a property for this key yet 1576 property = new CmsProperty(); 1577 property.setName(propertyKey); 1578 1579 switch (mappingType) { 1580 case CmsProperty.STRUCTURE_RECORD_MAPPING: 1581 // this property value is mapped to a structure record 1582 property.setStructureValue(propertyValue); 1583 property.setResourceValue(null); 1584 break; 1585 case CmsProperty.RESOURCE_RECORD_MAPPING: 1586 // this property value is mapped to a resource record 1587 property.setStructureValue(null); 1588 property.setResourceValue(propertyValue); 1589 break; 1590 default: 1591 throw new CmsDbConsistencyException( 1592 Messages.get().container( 1593 Messages.ERR_UNKNOWN_PROPERTY_VALUE_MAPPING_3, 1594 resource.getRootPath(), 1595 Integer.valueOf(mappingType), 1596 propertyKey)); 1597 } 1598 propertyMap.put(propertyKey, property); 1599 } 1600 } 1601 1602 /** 1603 * Deletes all historical entries of subresources of a folder without any historical netry left.<p> 1604 * 1605 * @param dbc the current database context 1606 * @param resource the resource to check 1607 * 1608 * @throws CmsDataAccessException if something goes wrong 1609 */ 1610 protected void internalCleanup(CmsDbContext dbc, I_CmsHistoryResource resource) throws CmsDataAccessException { 1611 1612 Connection conn = null; 1613 PreparedStatement stmt = null; 1614 ResultSet res = null; 1615 Map<CmsUUID, Integer> tmpSubResources = new HashMap<CmsUUID, Integer>(); 1616 1617 // if is folder and if no versions left 1618 boolean isFolderAndNoVersionLeft = resource.getRootPath().endsWith("/") 1619 && (readLastVersion(dbc, resource.getStructureId()) == 0); 1620 1621 // if the resource is a folder 1622 if (isFolderAndNoVersionLeft) { 1623 try { 1624 conn = m_sqlManager.getConnection(dbc); 1625 // get all direct subresources 1626 stmt = m_sqlManager.getPreparedStatement(conn, "C_STRUCTURE_HISTORY_READ_SUBRESOURCES"); 1627 stmt.setString(1, resource.getStructureId().toString()); 1628 res = stmt.executeQuery(); 1629 while (res.next()) { 1630 CmsUUID structureId = new CmsUUID(res.getString(1)); 1631 int version = res.getInt(2); 1632 tmpSubResources.put(structureId, Integer.valueOf(version)); 1633 } 1634 } catch (SQLException e) { 1635 throw new CmsDbSqlException( 1636 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 1637 e); 1638 } finally { 1639 m_sqlManager.closeAll(dbc, conn, stmt, res); 1640 } 1641 } 1642 // delete all subresource versions 1643 for (Map.Entry<CmsUUID, Integer> entry : tmpSubResources.entrySet()) { 1644 I_CmsHistoryResource histResource = readResource(dbc, entry.getKey(), entry.getValue().intValue()); 1645 deleteEntries(dbc, histResource, 0, -1); 1646 } 1647 } 1648 1649 /** 1650 * Returns the amount of properties for a propertydefinition.<p> 1651 * 1652 * @param dbc the current database context 1653 * @param metadef the propertydefinition to test 1654 * @param projectId the ID of the current project 1655 * 1656 * @return the amount of properties for a propertydefinition 1657 * @throws CmsDataAccessException if something goes wrong 1658 */ 1659 protected int internalCountProperties(CmsDbContext dbc, CmsPropertyDefinition metadef, CmsUUID projectId) 1660 throws CmsDataAccessException { 1661 1662 ResultSet res = null; 1663 PreparedStatement stmt = null; 1664 Connection conn = null; 1665 1666 int returnValue; 1667 try { 1668 // create statement 1669 conn = m_sqlManager.getConnection(dbc); 1670 stmt = m_sqlManager.getPreparedStatement(conn, projectId, "C_PROPERTIES_READALL_COUNT"); 1671 stmt.setString(1, metadef.getId().toString()); 1672 res = stmt.executeQuery(); 1673 1674 if (res.next()) { 1675 returnValue = res.getInt(1); 1676 while (res.next()) { 1677 // do nothing only move through all rows because of mssql odbc driver 1678 } 1679 } else { 1680 throw new CmsDbConsistencyException( 1681 Messages.get().container(Messages.ERR_NO_PROPERTIES_FOR_PROPERTYDEF_1, metadef.getName())); 1682 } 1683 } catch (SQLException e) { 1684 throw new CmsDbSqlException( 1685 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 1686 e); 1687 } finally { 1688 m_sqlManager.closeAll(dbc, conn, stmt, res); 1689 } 1690 return returnValue; 1691 } 1692 1693 /** 1694 * Creates a historical project from the given result set and resources.<p> 1695 * @param res the resource set 1696 * @param resources the historical resources 1697 * 1698 * @return the historical project 1699 * 1700 * @throws SQLException if something goes wrong 1701 */ 1702 protected CmsHistoryProject internalCreateProject(ResultSet res, List<String> resources) throws SQLException { 1703 1704 String ou = CmsOrganizationalUnit.removeLeadingSeparator( 1705 res.getString(m_sqlManager.readQuery("C_PROJECTS_PROJECT_OU_0"))); 1706 CmsUUID publishedById = new CmsUUID(res.getString(m_sqlManager.readQuery("C_PROJECT_PUBLISHED_BY_0"))); 1707 CmsUUID userId = new CmsUUID(res.getString(m_sqlManager.readQuery("C_PROJECTS_USER_ID_0"))); 1708 return new CmsHistoryProject( 1709 res.getInt(m_sqlManager.readQuery("C_PROJECTS_PUBLISH_TAG_0")), 1710 new CmsUUID(res.getString(m_sqlManager.readQuery("C_PROJECTS_PROJECT_ID_0"))), 1711 ou + res.getString(m_sqlManager.readQuery("C_PROJECTS_PROJECT_NAME_0")), 1712 res.getString(m_sqlManager.readQuery("C_PROJECTS_PROJECT_DESCRIPTION_0")), 1713 userId, 1714 new CmsUUID(res.getString(m_sqlManager.readQuery("C_PROJECTS_GROUP_ID_0"))), 1715 new CmsUUID(res.getString(m_sqlManager.readQuery("C_PROJECTS_MANAGERGROUP_ID_0"))), 1716 res.getLong(m_sqlManager.readQuery("C_PROJECTS_DATE_CREATED_0")), 1717 CmsProject.CmsProjectType.valueOf(res.getInt(m_sqlManager.readQuery("C_PROJECTS_PROJECT_TYPE_0"))), 1718 res.getLong(m_sqlManager.readQuery("C_PROJECT_PUBLISHDATE_0")), 1719 publishedById, 1720 resources); 1721 } 1722 1723 /** 1724 * Creates a valid {@link I_CmsHistoryResource} instance from a JDBC ResultSet.<p> 1725 * 1726 * @param res the JDBC result set 1727 * 1728 * @return the new historical resource instance 1729 * 1730 * @throws SQLException if a requested attribute was not found in the result set 1731 */ 1732 protected I_CmsHistoryResource internalCreateResource(ResultSet res) throws SQLException { 1733 1734 int resourceVersion = res.getInt(m_sqlManager.readQuery("C_RESOURCES_VERSION")); 1735 int structureVersion = res.getInt(m_sqlManager.readQuery("C_RESOURCES_STRUCTURE_VERSION")); 1736 int tagId = res.getInt(m_sqlManager.readQuery("C_RESOURCES_PUBLISH_TAG")); 1737 CmsUUID structureId = new CmsUUID(res.getString(m_sqlManager.readQuery("C_RESOURCES_STRUCTURE_ID"))); 1738 CmsUUID resourceId = new CmsUUID(res.getString(m_sqlManager.readQuery("C_RESOURCES_RESOURCE_ID"))); 1739 String resourcePath = res.getString(m_sqlManager.readQuery("C_RESOURCES_RESOURCE_PATH")); 1740 int resourceType = res.getInt(m_sqlManager.readQuery("C_RESOURCES_RESOURCE_TYPE")); 1741 int resourceFlags = res.getInt(m_sqlManager.readQuery("C_RESOURCES_RESOURCE_FLAGS")); 1742 CmsUUID projectLastModified = new CmsUUID( 1743 res.getString(m_sqlManager.readQuery("C_RESOURCES_PROJECT_LASTMODIFIED"))); 1744 int state = Math.max( 1745 res.getInt(m_sqlManager.readQuery("C_RESOURCES_STATE")), 1746 res.getInt(m_sqlManager.readQuery("C_RESOURCES_STRUCTURE_STATE"))); 1747 long dateCreated = res.getLong(m_sqlManager.readQuery("C_RESOURCES_DATE_CREATED")); 1748 long dateLastModified = res.getLong(m_sqlManager.readQuery("C_RESOURCES_DATE_LASTMODIFIED")); 1749 long dateReleased = res.getLong(m_sqlManager.readQuery("C_RESOURCES_DATE_RELEASED")); 1750 long dateExpired = res.getLong(m_sqlManager.readQuery("C_RESOURCES_DATE_EXPIRED")); 1751 int resourceSize = res.getInt(m_sqlManager.readQuery("C_RESOURCES_SIZE")); 1752 CmsUUID userLastModified = new CmsUUID(res.getString(m_sqlManager.readQuery("C_RESOURCES_USER_LASTMODIFIED"))); 1753 CmsUUID userCreated = new CmsUUID(res.getString(m_sqlManager.readQuery("C_RESOURCES_USER_CREATED"))); 1754 CmsUUID parentId = new CmsUUID(res.getString(m_sqlManager.readQuery("C_RESOURCES_HISTORY_PARENTID"))); 1755 long dateContent = res.getLong(m_sqlManager.readQuery("C_RESOURCES_DATE_CONTENT")); 1756 1757 boolean isFolder = resourcePath.endsWith("/"); 1758 if (isFolder) { 1759 return new CmsHistoryFolder( 1760 tagId, 1761 structureId, 1762 resourceId, 1763 resourcePath, 1764 resourceType, 1765 resourceFlags, 1766 projectLastModified, 1767 CmsResourceState.valueOf(state), 1768 dateCreated, 1769 userCreated, 1770 dateLastModified, 1771 userLastModified, 1772 dateReleased, 1773 dateExpired, 1774 resourceVersion + structureVersion, 1775 parentId, 1776 resourceVersion, 1777 structureVersion); 1778 } else { 1779 return new CmsHistoryFile( 1780 tagId, 1781 structureId, 1782 resourceId, 1783 resourcePath, 1784 resourceType, 1785 resourceFlags, 1786 projectLastModified, 1787 CmsResourceState.valueOf(state), 1788 dateCreated, 1789 userCreated, 1790 dateLastModified, 1791 userLastModified, 1792 dateReleased, 1793 dateExpired, 1794 resourceSize, 1795 dateContent, 1796 resourceVersion + structureVersion, 1797 parentId, 1798 null, 1799 resourceVersion, 1800 structureVersion); 1801 } 1802 } 1803 1804 /** 1805 * Merges an historical entry for a sibling, based on the structure data from the given historical resource 1806 * and result set for the resource entry.<p> 1807 * 1808 * @param histRes the original historical entry 1809 * @param res the result set of the resource entry 1810 * @param versionOffset the offset for the structure version 1811 * 1812 * @return a merged historical entry for the sibling 1813 * 1814 * @throws SQLException if something goes wrong 1815 */ 1816 protected I_CmsHistoryResource internalMergeResource(I_CmsHistoryResource histRes, ResultSet res, int versionOffset) 1817 throws SQLException { 1818 1819 int resourceVersion = res.getInt(m_sqlManager.readQuery("C_RESOURCES_VERSION")); 1820 int structureVersion = histRes.getStructureVersion() - versionOffset; 1821 int tagId = res.getInt(m_sqlManager.readQuery("C_RESOURCES_PUBLISH_TAG")); 1822 CmsUUID structureId = histRes.getStructureId(); 1823 CmsUUID resourceId = new CmsUUID(res.getString(m_sqlManager.readQuery("C_RESOURCES_RESOURCE_ID"))); 1824 int resourceType = res.getInt(m_sqlManager.readQuery("C_RESOURCES_RESOURCE_TYPE")); 1825 int resourceFlags = res.getInt(m_sqlManager.readQuery("C_RESOURCES_RESOURCE_FLAGS")); 1826 CmsUUID projectLastModified = new CmsUUID( 1827 res.getString(m_sqlManager.readQuery("C_RESOURCES_PROJECT_LASTMODIFIED"))); 1828 int state = histRes.getState().getState(); // may be we have to compute something here? 1829 long dateCreated = res.getLong(m_sqlManager.readQuery("C_RESOURCES_DATE_CREATED")); 1830 long dateLastModified = res.getLong(m_sqlManager.readQuery("C_RESOURCES_DATE_LASTMODIFIED")); 1831 long dateReleased = histRes.getDateReleased(); 1832 long dateExpired = histRes.getDateExpired(); 1833 int resourceSize = res.getInt(m_sqlManager.readQuery("C_RESOURCES_SIZE")); 1834 CmsUUID userLastModified = new CmsUUID(res.getString(m_sqlManager.readQuery("C_RESOURCES_USER_LASTMODIFIED"))); 1835 CmsUUID userCreated = new CmsUUID(res.getString(m_sqlManager.readQuery("C_RESOURCES_USER_CREATED"))); 1836 // here we could use the path/parent id for the sibling where the modification really occurred 1837 String resourcePath = histRes.getRootPath(); 1838 CmsUUID parentId = histRes.getParentId(); 1839 long dateContent = res.getLong(m_sqlManager.readQuery("C_RESOURCES_DATE_CONTENT")); 1840 1841 if (histRes.isFolder()) { 1842 return new CmsHistoryFolder( 1843 tagId, 1844 structureId, 1845 resourceId, 1846 resourcePath, 1847 resourceType, 1848 resourceFlags, 1849 projectLastModified, 1850 CmsResourceState.valueOf(state), 1851 dateCreated, 1852 userCreated, 1853 dateLastModified, 1854 userLastModified, 1855 dateReleased, 1856 dateExpired, 1857 resourceVersion + structureVersion, 1858 parentId, 1859 resourceVersion, 1860 structureVersion); 1861 } else { 1862 return new CmsHistoryFile( 1863 tagId, 1864 structureId, 1865 resourceId, 1866 resourcePath, 1867 resourceType, 1868 resourceFlags, 1869 projectLastModified, 1870 CmsResourceState.valueOf(state), 1871 dateCreated, 1872 userCreated, 1873 dateLastModified, 1874 userLastModified, 1875 dateReleased, 1876 dateExpired, 1877 resourceSize, 1878 dateContent, 1879 resourceVersion + structureVersion, 1880 parentId, 1881 null, 1882 resourceVersion, 1883 structureVersion); 1884 } 1885 } 1886 1887 /** 1888 * Tests if a history resource does exist.<p> 1889 * 1890 * @param dbc the current database context 1891 * @param resource the resource to test 1892 * @param publishTag the publish tag of the resource to test 1893 * 1894 * @return <code>true</code> if the resource already exists, <code>false</code> otherwise 1895 * 1896 * @throws CmsDataAccessException if something goes wrong 1897 */ 1898 protected boolean internalValidateResource(CmsDbContext dbc, CmsResource resource, int publishTag) 1899 throws CmsDataAccessException { 1900 1901 Connection conn = null; 1902 PreparedStatement stmt = null; 1903 ResultSet res = null; 1904 boolean exists = false; 1905 1906 try { 1907 conn = m_sqlManager.getConnection(dbc); 1908 stmt = m_sqlManager.getPreparedStatement(conn, "C_HISTORY_EXISTS_RESOURCE"); 1909 stmt.setString(1, resource.getResourceId().toString()); 1910 stmt.setInt(2, publishTag); 1911 res = stmt.executeQuery(); 1912 1913 exists = res.next(); 1914 } catch (SQLException e) { 1915 throw new CmsDbSqlException( 1916 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 1917 e); 1918 } finally { 1919 m_sqlManager.closeAll(dbc, conn, stmt, res); 1920 } 1921 return exists; 1922 } 1923 1924}