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