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