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.CmsAlias; 033import org.opencms.db.CmsAliasFilter; 034import org.opencms.db.CmsDbConsistencyException; 035import org.opencms.db.CmsDbContext; 036import org.opencms.db.CmsDbEntryNotFoundException; 037import org.opencms.db.CmsDbSqlException; 038import org.opencms.db.CmsDbUtil; 039import org.opencms.db.CmsDriverManager; 040import org.opencms.db.CmsPreparedStatementIntParameter; 041import org.opencms.db.CmsPreparedStatementStringParameter; 042import org.opencms.db.CmsResourceState; 043import org.opencms.db.CmsRewriteAlias; 044import org.opencms.db.CmsRewriteAliasFilter; 045import org.opencms.db.CmsVfsOnlineResourceAlreadyExistsException; 046import org.opencms.db.I_CmsDriver; 047import org.opencms.db.I_CmsPreparedStatementParameter; 048import org.opencms.db.I_CmsProjectDriver; 049import org.opencms.db.I_CmsVfsDriver; 050import org.opencms.db.urlname.CmsUrlNameMappingEntry; 051import org.opencms.db.urlname.CmsUrlNameMappingFilter; 052import org.opencms.file.CmsDataAccessException; 053import org.opencms.file.CmsFile; 054import org.opencms.file.CmsFolder; 055import org.opencms.file.CmsProject; 056import org.opencms.file.CmsProperty; 057import org.opencms.file.CmsPropertyDefinition; 058import org.opencms.file.CmsResource; 059import org.opencms.file.CmsResourceFilter; 060import org.opencms.file.CmsVfsException; 061import org.opencms.file.CmsVfsResourceAlreadyExistsException; 062import org.opencms.file.CmsVfsResourceNotFoundException; 063import org.opencms.file.I_CmsResource; 064import org.opencms.file.history.I_CmsHistoryResource; 065import org.opencms.file.quota.CmsFolderSizeEntry; 066import org.opencms.file.quota.CmsFolderSizeOptions; 067import org.opencms.file.types.CmsResourceTypeJsp; 068import org.opencms.gwt.shared.alias.CmsAliasMode; 069import org.opencms.main.CmsEvent; 070import org.opencms.main.CmsException; 071import org.opencms.main.CmsLog; 072import org.opencms.main.I_CmsEventListener; 073import org.opencms.main.OpenCms; 074import org.opencms.relations.CmsRelation; 075import org.opencms.relations.CmsRelationFilter; 076import org.opencms.relations.CmsRelationType; 077import org.opencms.security.CmsOrganizationalUnit; 078import org.opencms.security.CmsPermissionSet; 079import org.opencms.util.CmsFileUtil; 080import org.opencms.util.CmsPair; 081import org.opencms.util.CmsStringUtil; 082import org.opencms.util.CmsUUID; 083 084import java.io.ByteArrayInputStream; 085import java.sql.Connection; 086import java.sql.PreparedStatement; 087import java.sql.ResultSet; 088import java.sql.SQLException; 089import java.util.ArrayList; 090import java.util.Collection; 091import java.util.Collections; 092import java.util.HashMap; 093import java.util.HashSet; 094import java.util.Iterator; 095import java.util.List; 096import java.util.Map; 097import java.util.Set; 098 099import org.apache.commons.logging.Log; 100 101/** 102 * Generic (ANSI-SQL) database server implementation of the VFS driver methods.<p> 103 * 104 * @since 6.0.0 105 */ 106public class CmsVfsDriver implements I_CmsDriver, I_CmsVfsDriver { 107 108 /** 109 * Used to distinguish the different contexts in which relation conditions are assembled. 110 */ 111 protected static enum RelationConditionMode { 112 /** For reading relations. */ 113 read, 114 /** For deleting relations. */ 115 delete 116 } 117 118 /** Contains the macro replacement value for the offline project. */ 119 protected static final String OFFLINE = "OFFLINE"; 120 121 /** Contains the macro replacement value for the online project. */ 122 protected static final String ONLINE = "ONLINE"; 123 124 /** The log object for this class. */ 125 private static final Log LOG = CmsLog.getLog(org.opencms.db.generic.CmsVfsDriver.class); 126 127 /** The driver manager. */ 128 protected CmsDriverManager m_driverManager; 129 130 /** 131 * This field is temporarily used to compute the versions during publishing.<p> 132 * 133 * @see #publishVersions(CmsDbContext, CmsResource, boolean) 134 */ 135 protected List<CmsUUID> m_resOp = new ArrayList<CmsUUID>(); 136 137 /** The sql manager. */ 138 protected CmsSqlManager m_sqlManager; 139 140 /** 141 * This method prepares the SQL conditions for mapping entries for a given URL name mapping filter.<p> 142 * 143 * @param filter the filter from which the SQL conditions should be generated 144 * 145 * @return a pair consisting of an SQL string and a list of the prepared statement parameters for the SQL 146 */ 147 public static CmsPair<String, List<I_CmsPreparedStatementParameter>> prepareUrlNameMappingConditions( 148 CmsUrlNameMappingFilter filter) { 149 150 List<String> sqlConditions = new ArrayList<String>(); 151 List<I_CmsPreparedStatementParameter> parameters = new ArrayList<I_CmsPreparedStatementParameter>(); 152 if (filter.getName() != null) { 153 sqlConditions.add("NAME = ?"); 154 parameters.add(new CmsPreparedStatementStringParameter(filter.getName())); 155 } 156 157 if (filter.getStructureId() != null) { 158 sqlConditions.add("STRUCTURE_ID = ?"); 159 parameters.add(new CmsPreparedStatementStringParameter(filter.getStructureId().toString())); 160 } 161 162 if (filter.getNamePattern() != null) { 163 sqlConditions.add(" NAME LIKE ? "); 164 parameters.add(new CmsPreparedStatementStringParameter(filter.getNamePattern())); 165 } 166 167 if ((filter.getStates() != null) && (filter.getStates().length > 0)) { 168 List<String> stateConditions = new ArrayList<String>(); 169 stateConditions.add("1 = 0"); 170 for (int i = 0; i < filter.getStates().length; i++) { 171 stateConditions.add("STATE = ?"); 172 parameters.add(new CmsPreparedStatementIntParameter(filter.getStates()[i])); 173 } 174 sqlConditions.add("( " + CmsStringUtil.listAsString(stateConditions, " OR ") + ")"); 175 176 } 177 178 if (filter.getRejectStructureId() != null) { 179 sqlConditions.add(" STRUCTURE_ID <> ? "); 180 parameters.add(new CmsPreparedStatementStringParameter(filter.getRejectStructureId().toString())); 181 } 182 183 if (filter.getLocale() != null) { 184 sqlConditions.add(" LOCALE = ? "); 185 parameters.add(new CmsPreparedStatementStringParameter(filter.getLocale())); 186 } 187 188 String conditionString = CmsStringUtil.listAsString(sqlConditions, " AND "); 189 return CmsPair.create(conditionString, parameters); 190 } 191 192 /** 193 * Escapes the database wildcards within the resource path.<p> 194 * 195 * This method is required to ensure chars in the resource path that have a special 196 * meaning in SQL (for example "_", which is the "any char" operator) are escaped.<p> 197 * 198 * It will escape the following chars: 199 * <ul> 200 * <li>"_" to "|_"</li> 201 * </ul> 202 * 203 * @param path the resource path 204 * @return the escaped resource path 205 */ 206 protected static String escapeDbWildcard(String path) { 207 208 return CmsStringUtil.substitute(path, "_", "|_"); 209 } 210 211 /** 212 * @see org.opencms.db.I_CmsVfsDriver#addUrlNameMappingEntry(org.opencms.db.CmsDbContext, boolean, org.opencms.db.urlname.CmsUrlNameMappingEntry) 213 */ 214 public void addUrlNameMappingEntry(CmsDbContext dbc, boolean online, CmsUrlNameMappingEntry entry) 215 throws CmsDataAccessException { 216 217 Connection conn = null; 218 PreparedStatement stmt = null; 219 String query = m_sqlManager.readQuery("C_ADD_URLNAME_MAPPING"); 220 query = replaceProject(query, online); 221 try { 222 conn = m_sqlManager.getConnection(dbc); 223 stmt = m_sqlManager.getPreparedStatementForSql(conn, query); 224 stmt.setString(1, entry.getName()); 225 stmt.setString(2, entry.getStructureId().toString()); 226 stmt.setInt(3, entry.getState()); 227 stmt.setLong(4, entry.getDateChanged()); 228 stmt.setString(5, entry.getLocale()); 229 stmt.executeUpdate(); 230 } catch (SQLException e) { 231 throw wrapException(stmt, e); 232 } finally { 233 m_sqlManager.closeAll(dbc, conn, stmt, null); 234 } 235 } 236 237 /** 238 * Counts the number of siblings of a resource.<p> 239 * 240 * @param dbc the current database context 241 * @param projectId the current project id 242 * @param resourceId the resource id to count the number of siblings from 243 * 244 * @return number of siblings 245 * @throws CmsDataAccessException if something goes wrong 246 */ 247 public int countSiblings(CmsDbContext dbc, CmsUUID projectId, CmsUUID resourceId) throws CmsDataAccessException { 248 249 Connection conn = null; 250 PreparedStatement stmt = null; 251 ResultSet res = null; 252 int count = 0; 253 254 try { 255 conn = m_sqlManager.getConnection(dbc); 256 257 stmt = m_sqlManager.getPreparedStatement(conn, projectId, "C_RESOURCES_COUNT_SIBLINGS"); 258 stmt.setString(1, resourceId.toString()); 259 res = stmt.executeQuery(); 260 261 if (res.next()) { 262 count = res.getInt(1); 263 while (res.next()) { 264 // do nothing only move through all rows because of mssql odbc driver 265 } 266 } 267 } catch (SQLException e) { 268 throw new CmsDbSqlException( 269 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 270 e); 271 } finally { 272 m_sqlManager.closeAll(dbc, conn, stmt, res); 273 } 274 275 return count; 276 } 277 278 /** 279 * @see org.opencms.db.I_CmsVfsDriver#createContent(CmsDbContext, CmsUUID, CmsResource, byte[]) 280 */ 281 public void createContent(CmsDbContext dbc, CmsUUID projectId, CmsResource resource, byte[] content) 282 throws CmsDataAccessException { 283 284 Connection conn = null; 285 PreparedStatement stmt = null; 286 287 try { 288 conn = m_sqlManager.getConnection(dbc); 289 // create new offline content 290 stmt = m_sqlManager.getPreparedStatement(conn, "C_OFFLINE_CONTENTS_WRITE"); 291 stmt.setString(1, resource.getResourceId().toString()); 292 if (content.length < 2000) { 293 stmt.setBytes(2, content); 294 } else { 295 stmt.setBinaryStream(2, new ByteArrayInputStream(content), content.length); 296 } 297 stmt.executeUpdate(); 298 } catch (SQLException e) { 299 throw new CmsDbSqlException( 300 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 301 e); 302 } finally { 303 m_sqlManager.closeAll(dbc, conn, stmt, null); 304 } 305 } 306 307 /** 308 * @see org.opencms.db.I_CmsVfsDriver#createFile(CmsDbContext, java.sql.ResultSet, CmsUUID) 309 */ 310 public CmsFile createFile(CmsDbContext dbc, ResultSet res, CmsUUID projectId) 311 throws CmsDataAccessException, SQLException { 312 313 CmsUUID structureId = new CmsUUID(res.getString(m_sqlManager.readQuery("C_RESOURCES_STRUCTURE_ID"))); 314 CmsUUID resourceId = new CmsUUID(res.getString(m_sqlManager.readQuery("C_RESOURCES_RESOURCE_ID"))); 315 int resourceType = res.getInt(m_sqlManager.readQuery("C_RESOURCES_RESOURCE_TYPE")); 316 String resourcePath = res.getString(m_sqlManager.readQuery("C_RESOURCES_RESOURCE_PATH")); 317 int resourceFlags = res.getInt(m_sqlManager.readQuery("C_RESOURCES_RESOURCE_FLAGS")); 318 int resourceState = res.getInt(m_sqlManager.readQuery("C_RESOURCES_STATE")); 319 int structureState = res.getInt(m_sqlManager.readQuery("C_RESOURCES_STRUCTURE_STATE")); 320 long dateCreated = res.getLong(m_sqlManager.readQuery("C_RESOURCES_DATE_CREATED")); 321 long dateLastModified = res.getLong(m_sqlManager.readQuery("C_RESOURCES_DATE_LASTMODIFIED")); 322 long dateReleased = res.getLong(m_sqlManager.readQuery("C_RESOURCES_DATE_RELEASED")); 323 long dateExpired = res.getLong(m_sqlManager.readQuery("C_RESOURCES_DATE_EXPIRED")); 324 int resourceSize = res.getInt(m_sqlManager.readQuery("C_RESOURCES_SIZE")); 325 CmsUUID userCreated = new CmsUUID(res.getString(m_sqlManager.readQuery("C_RESOURCES_USER_CREATED"))); 326 CmsUUID userLastModified = new CmsUUID(res.getString(m_sqlManager.readQuery("C_RESOURCES_USER_LASTMODIFIED"))); 327 byte[] content = m_sqlManager.getBytes(res, m_sqlManager.readQuery("C_RESOURCES_FILE_CONTENT")); 328 int siblingCount = res.getInt(m_sqlManager.readQuery("C_RESOURCES_SIBLING_COUNT")); 329 long dateContent = res.getLong(m_sqlManager.readQuery("C_RESOURCES_DATE_CONTENT")); 330 int resourceVersion = res.getInt(m_sqlManager.readQuery("C_RESOURCES_VERSION")); 331 int structureVersion = res.getInt(m_sqlManager.readQuery("C_RESOURCES_STRUCTURE_VERSION")); 332 333 // calculate the overall state 334 int newState = (structureState > resourceState) ? structureState : resourceState; 335 336 // in case of folder type ensure, that the root path has a trailing slash 337 if (CmsFolder.isFolderType(resourceType)) { 338 resourcePath = CmsFileUtil.addTrailingSeparator(resourcePath); 339 } 340 341 return new CmsFile( 342 structureId, 343 resourceId, 344 resourcePath, 345 resourceType, 346 resourceFlags, 347 projectId, 348 CmsResourceState.valueOf(newState), 349 dateCreated, 350 userCreated, 351 dateLastModified, 352 userLastModified, 353 dateReleased, 354 dateExpired, 355 siblingCount, 356 resourceSize, 357 dateContent, 358 resourceVersion + structureVersion, 359 content); 360 } 361 362 /** 363 * @see org.opencms.db.I_CmsVfsDriver#createFile(CmsDbContext, java.sql.ResultSet, CmsUUID, boolean) 364 */ 365 public CmsFile createFile(CmsDbContext dbc, ResultSet res, CmsUUID projectId, boolean hasFileContentInResultSet) 366 throws CmsDataAccessException, SQLException { 367 368 byte[] content = null; 369 370 CmsUUID resProjectId = null; 371 372 CmsUUID structureId = new CmsUUID(res.getString(m_sqlManager.readQuery("C_RESOURCES_STRUCTURE_ID"))); 373 CmsUUID resourceId = new CmsUUID(res.getString(m_sqlManager.readQuery("C_RESOURCES_RESOURCE_ID"))); 374 String resourcePath = res.getString(m_sqlManager.readQuery("C_RESOURCES_RESOURCE_PATH")); 375 int resourceType = res.getInt(m_sqlManager.readQuery("C_RESOURCES_RESOURCE_TYPE")); 376 int resourceFlags = res.getInt(m_sqlManager.readQuery("C_RESOURCES_RESOURCE_FLAGS")); 377 int resourceState = res.getInt(m_sqlManager.readQuery("C_RESOURCES_STATE")); 378 int structureState = res.getInt(m_sqlManager.readQuery("C_RESOURCES_STRUCTURE_STATE")); 379 long dateCreated = res.getLong(m_sqlManager.readQuery("C_RESOURCES_DATE_CREATED")); 380 long dateLastModified = res.getLong(m_sqlManager.readQuery("C_RESOURCES_DATE_LASTMODIFIED")); 381 long dateReleased = res.getLong(m_sqlManager.readQuery("C_RESOURCES_DATE_RELEASED")); 382 long dateExpired = res.getLong(m_sqlManager.readQuery("C_RESOURCES_DATE_EXPIRED")); 383 int resourceSize = res.getInt(m_sqlManager.readQuery("C_RESOURCES_SIZE")); 384 CmsUUID userCreated = new CmsUUID(res.getString(m_sqlManager.readQuery("C_RESOURCES_USER_CREATED"))); 385 CmsUUID userLastModified = new CmsUUID(res.getString(m_sqlManager.readQuery("C_RESOURCES_USER_LASTMODIFIED"))); 386 CmsUUID lockedInProject = new CmsUUID(res.getString("LOCKED_IN_PROJECT")); 387 int siblingCount = res.getInt(m_sqlManager.readQuery("C_RESOURCES_SIBLING_COUNT")); 388 long dateContent = res.getLong(m_sqlManager.readQuery("C_RESOURCES_DATE_CONTENT")); 389 int resourceVersion = res.getInt(m_sqlManager.readQuery("C_RESOURCES_VERSION")); 390 int structureVersion = res.getInt(m_sqlManager.readQuery("C_RESOURCES_STRUCTURE_VERSION")); 391 392 // in case of folder type ensure, that the root path has a trailing slash 393 if (CmsFolder.isFolderType(resourceType)) { 394 resourcePath = CmsFileUtil.addTrailingSeparator(resourcePath); 395 } 396 if (hasFileContentInResultSet) { 397 content = m_sqlManager.getBytes(res, m_sqlManager.readQuery("C_RESOURCES_FILE_CONTENT")); 398 } 399 resProjectId = lockedInProject; 400 int newState = (structureState > resourceState) ? structureState : resourceState; 401 402 return new CmsFile( 403 structureId, 404 resourceId, 405 resourcePath, 406 resourceType, 407 resourceFlags, 408 resProjectId, 409 CmsResourceState.valueOf(newState), 410 dateCreated, 411 userCreated, 412 dateLastModified, 413 userLastModified, 414 dateReleased, 415 dateExpired, 416 siblingCount, 417 resourceSize, 418 dateContent, 419 resourceVersion + structureVersion, 420 content); 421 } 422 423 /** 424 * @see org.opencms.db.I_CmsVfsDriver#createFolder(java.sql.ResultSet, CmsUUID, boolean) 425 */ 426 public CmsFolder createFolder(ResultSet res, CmsUUID projectId, boolean hasProjectIdInResultSet) 427 throws SQLException { 428 429 CmsUUID structureId = new CmsUUID(res.getString(m_sqlManager.readQuery("C_RESOURCES_STRUCTURE_ID"))); 430 CmsUUID resourceId = new CmsUUID(res.getString(m_sqlManager.readQuery("C_RESOURCES_RESOURCE_ID"))); 431 String resourcePath = res.getString(m_sqlManager.readQuery("C_RESOURCES_RESOURCE_PATH")); 432 int resourceType = res.getInt(m_sqlManager.readQuery("C_RESOURCES_RESOURCE_TYPE")); 433 int resourceFlags = res.getInt(m_sqlManager.readQuery("C_RESOURCES_RESOURCE_FLAGS")); 434 int resourceState = res.getInt(m_sqlManager.readQuery("C_RESOURCES_STATE")); 435 int structureState = res.getInt(m_sqlManager.readQuery("C_RESOURCES_STRUCTURE_STATE")); 436 long dateCreated = res.getLong(m_sqlManager.readQuery("C_RESOURCES_DATE_CREATED")); 437 long dateLastModified = res.getLong(m_sqlManager.readQuery("C_RESOURCES_DATE_LASTMODIFIED")); 438 long dateReleased = res.getLong(m_sqlManager.readQuery("C_RESOURCES_DATE_RELEASED")); 439 long dateExpired = res.getLong(m_sqlManager.readQuery("C_RESOURCES_DATE_EXPIRED")); 440 CmsUUID userCreated = new CmsUUID(res.getString(m_sqlManager.readQuery("C_RESOURCES_USER_CREATED"))); 441 CmsUUID userLastModified = new CmsUUID(res.getString(m_sqlManager.readQuery("C_RESOURCES_USER_LASTMODIFIED"))); 442 CmsUUID resProjectId = new CmsUUID(res.getString("LOCKED_IN_PROJECT")); 443 int resourceVersion = res.getInt(m_sqlManager.readQuery("C_RESOURCES_VERSION")); 444 int structureVersion = res.getInt(m_sqlManager.readQuery("C_RESOURCES_STRUCTURE_VERSION")); 445 int resourceSize = res.getInt(m_sqlManager.readQuery("C_RESOURCES_SIZE")); 446 447 // in case of folder type ensure, that the root path has a trailing slash 448 if (CmsFolder.isFolderSize(resourceSize)) { 449 resourcePath = CmsFileUtil.addTrailingSeparator(resourcePath); 450 } 451 452 int newState = (structureState > resourceState) ? structureState : resourceState; 453 454 return new CmsFolder( 455 structureId, 456 resourceId, 457 resourcePath, 458 resourceType, 459 resourceFlags, 460 resProjectId, 461 CmsResourceState.valueOf(newState), 462 dateCreated, 463 userCreated, 464 dateLastModified, 465 userLastModified, 466 dateReleased, 467 dateExpired, 468 resourceVersion + structureVersion); 469 } 470 471 /** 472 * @see org.opencms.db.I_CmsVfsDriver#createOnlineContent(org.opencms.db.CmsDbContext, org.opencms.util.CmsUUID, byte[], int, boolean, boolean) 473 */ 474 public void createOnlineContent( 475 CmsDbContext dbc, 476 CmsUUID resourceId, 477 byte[] contents, 478 int publishTag, 479 boolean keepOnline, 480 boolean needToUpdateContent) 481 throws CmsDataAccessException { 482 483 Connection conn = null; 484 PreparedStatement stmt = null; 485 486 try { 487 conn = m_sqlManager.getConnection(dbc); 488 boolean dbcHasProjectId = (dbc.getProjectId() != null) && !dbc.getProjectId().isNullUUID(); 489 490 if (needToUpdateContent || dbcHasProjectId) { 491 if (dbcHasProjectId || !OpenCms.getSystemInfo().isHistoryEnabled()) { 492 // remove the online content for this resource id 493 stmt = m_sqlManager.getPreparedStatement(conn, "C_ONLINE_CONTENTS_DELETE"); 494 stmt.setString(1, resourceId.toString()); 495 stmt.executeUpdate(); 496 m_sqlManager.closeAll(dbc, null, stmt, null); 497 } else { 498 // put the online content in the history, only if explicit requested 499 stmt = m_sqlManager.getPreparedStatement(conn, "C_ONLINE_CONTENTS_HISTORY"); 500 stmt.setString(1, resourceId.toString()); 501 stmt.executeUpdate(); 502 m_sqlManager.closeAll(dbc, null, stmt, null); 503 } 504 505 // create new online content 506 stmt = m_sqlManager.getPreparedStatement(conn, "C_ONLINE_CONTENTS_WRITE"); 507 508 stmt.setString(1, resourceId.toString()); 509 if (contents.length < 2000) { 510 stmt.setBytes(2, contents); 511 } else { 512 stmt.setBinaryStream(2, new ByteArrayInputStream(contents), contents.length); 513 } 514 stmt.setInt(3, publishTag); 515 stmt.setInt(4, publishTag); 516 stmt.setInt(5, keepOnline ? 1 : 0); 517 stmt.executeUpdate(); 518 m_sqlManager.closeAll(dbc, null, stmt, null); 519 } else { 520 // update old content entry 521 stmt = m_sqlManager.getPreparedStatement(conn, "C_HISTORY_CONTENTS_UPDATE"); 522 stmt.setInt(1, publishTag); 523 stmt.setString(2, resourceId.toString()); 524 stmt.executeUpdate(); 525 m_sqlManager.closeAll(dbc, null, stmt, null); 526 527 if (!keepOnline) { 528 // put the online content in the history 529 stmt = m_sqlManager.getPreparedStatement(conn, "C_ONLINE_CONTENTS_HISTORY"); 530 stmt.setString(1, resourceId.toString()); 531 stmt.executeUpdate(); 532 m_sqlManager.closeAll(dbc, null, stmt, null); 533 } 534 } 535 } catch (SQLException e) { 536 throw new CmsDbSqlException( 537 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 538 e); 539 } finally { 540 m_sqlManager.closeAll(dbc, conn, stmt, null); 541 } 542 } 543 544 /** 545 * @see org.opencms.db.I_CmsVfsDriver#createPropertyDefinition(org.opencms.db.CmsDbContext, org.opencms.util.CmsUUID, java.lang.String, org.opencms.file.CmsPropertyDefinition.CmsPropertyType) 546 */ 547 public CmsPropertyDefinition createPropertyDefinition( 548 CmsDbContext dbc, 549 CmsUUID projectId, 550 String name, 551 CmsPropertyDefinition.CmsPropertyType type) 552 throws CmsDataAccessException { 553 554 Connection conn = null; 555 PreparedStatement stmt = null; 556 557 try { 558 conn = m_sqlManager.getConnection(dbc); 559 stmt = m_sqlManager.getPreparedStatement(conn, projectId, "C_PROPERTYDEF_CREATE"); 560 stmt.setString(1, new CmsUUID().toString()); 561 stmt.setString(2, name); 562 stmt.setInt(3, type.getMode()); 563 stmt.executeUpdate(); 564 } catch (SQLException e) { 565 throw new CmsDbSqlException( 566 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 567 e); 568 } finally { 569 m_sqlManager.closeAll(dbc, conn, stmt, null); 570 } 571 572 return readPropertyDefinition(dbc, name, projectId); 573 } 574 575 /** 576 * @see org.opencms.db.I_CmsVfsDriver#createRelation(org.opencms.db.CmsDbContext, CmsUUID, org.opencms.relations.CmsRelation) 577 */ 578 public void createRelation(CmsDbContext dbc, CmsUUID projectId, CmsRelation relation) 579 throws CmsDataAccessException { 580 581 Connection conn = null; 582 PreparedStatement stmt = null; 583 584 try { 585 conn = m_sqlManager.getConnection(dbc); 586 stmt = m_sqlManager.getPreparedStatement(conn, projectId, "C_CREATE_RELATION"); 587 stmt.setString(1, relation.getSourceId().toString()); 588 stmt.setString(2, relation.getSourcePath()); 589 stmt.setString(3, relation.getTargetId().toString()); 590 stmt.setString(4, relation.getTargetPath()); 591 stmt.setInt(5, relation.getType().getId()); 592 593 if (LOG.isDebugEnabled()) { 594 LOG.debug( 595 Messages.get().getBundle().key( 596 Messages.LOG_CREATE_RELATION_2, 597 String.valueOf(projectId), 598 relation)); 599 } 600 stmt.executeUpdate(); 601 } catch (SQLException e) { 602 throw new CmsDbSqlException( 603 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 604 e); 605 } finally { 606 m_sqlManager.closeAll(dbc, conn, stmt, null); 607 } 608 609 if (relation.getType().getId() == CmsRelationType.LOCALE_VARIANT.getId()) { 610 try { 611 612 // Normalizes locale relations after creating a relation. 613 // After creating a locale variant relation from A to B, this statment 614 // removes all locale variant relations which are either 615 // - from A to somewhere else than B, 616 // - from B to some other resource 617 // - to A from some other resources 618 conn = m_sqlManager.getConnection(dbc); 619 stmt = m_sqlManager.getPreparedStatement(conn, projectId, "C_RELATIONS_NORMALIZE_LOCALE_RELATIONS"); 620 stmt.setString(1, relation.getSourceId().toString()); 621 stmt.setString(2, relation.getTargetId().toString()); 622 stmt.setString(3, relation.getSourceId().toString()); 623 stmt.setString(4, relation.getTargetId().toString()); 624 if (LOG.isDebugEnabled()) { 625 LOG.debug( 626 Messages.get().getBundle().key( 627 Messages.LOG_CREATE_RELATION_2, 628 String.valueOf(projectId), 629 relation)); 630 } 631 stmt.executeUpdate(); 632 } catch (SQLException e) { 633 throw new CmsDbSqlException( 634 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 635 e); 636 } finally { 637 m_sqlManager.closeAll(dbc, conn, stmt, null); 638 } 639 } 640 } 641 642 /** 643 * @see org.opencms.db.I_CmsVfsDriver#createResource(org.opencms.db.CmsDbContext, CmsUUID, org.opencms.file.CmsResource, byte[]) 644 */ 645 public CmsResource createResource(CmsDbContext dbc, CmsUUID projectId, CmsResource resource, byte[] content) 646 throws CmsDataAccessException { 647 648 CmsUUID newStructureId = null; 649 Connection conn = null; 650 PreparedStatement stmt = null; 651 652 // check the resource path 653 String resourcePath = CmsFileUtil.removeTrailingSeparator(resource.getRootPath()); 654 if (resourcePath.length() > CmsDriverManager.MAX_VFS_RESOURCE_PATH_LENGTH) { 655 throw new CmsDataAccessException( 656 Messages.get().container( 657 Messages.ERR_RESOURCENAME_TOO_LONG_2, 658 resourcePath, 659 Integer.valueOf(CmsDriverManager.MAX_VFS_RESOURCE_PATH_LENGTH))); 660 } 661 662 // check if the parent folder of the resource exists and if is not deleted 663 if (!resource.getRootPath().equals("/")) { 664 String parentFolderName = CmsResource.getParentFolder(resource.getRootPath()); 665 CmsFolder parentFolder = m_driverManager.getVfsDriver(dbc).readFolder(dbc, projectId, parentFolderName); 666 if (parentFolder.getState().isDeleted()) { 667 throw new CmsDbEntryNotFoundException( 668 Messages.get().container(Messages.ERR_PARENT_FOLDER_DELETED_1, resource.getRootPath())); 669 } 670 } 671 672 // validate the resource length 673 internalValidateResourceLength(resource); 674 675 // set the resource state and modification dates 676 CmsResourceState newState; 677 long dateModified; 678 long dateCreated; 679 long dateContent = System.currentTimeMillis(); 680 681 if (projectId.equals(CmsProject.ONLINE_PROJECT_ID)) { 682 newState = CmsResource.STATE_UNCHANGED; 683 dateCreated = resource.getDateCreated(); 684 dateModified = resource.getDateLastModified(); 685 } else { 686 newState = CmsResource.STATE_NEW; 687 if (resource.isTouched()) { 688 dateCreated = resource.getDateCreated(); 689 dateModified = resource.getDateLastModified(); 690 } else { 691 dateCreated = System.currentTimeMillis(); 692 dateModified = dateCreated; 693 } 694 } 695 696 // check if the resource already exists 697 newStructureId = resource.getStructureId(); 698 699 try { 700 CmsResource existingResource = m_driverManager.getVfsDriver(dbc).readResource( 701 dbc, 702 ((dbc.getProjectId() == null) || dbc.getProjectId().isNullUUID()) ? projectId : dbc.getProjectId(), 703 resourcePath, 704 true); 705 if (existingResource.getState().isDeleted()) { 706 // if an existing resource is deleted, it will be finally removed now. 707 // but we have to reuse its id in order to avoid orphans in the online project 708 newStructureId = existingResource.getStructureId(); 709 newState = CmsResource.STATE_CHANGED; 710 711 // remove the existing file and it's properties 712 List<CmsResource> modifiedResources = m_driverManager.getVfsDriver( 713 dbc).readSiblings(dbc, projectId, existingResource, false); 714 int propertyDeleteOption = (existingResource.getSiblingCount() > 1) 715 ? CmsProperty.DELETE_OPTION_DELETE_STRUCTURE_VALUES 716 : CmsProperty.DELETE_OPTION_DELETE_STRUCTURE_AND_RESOURCE_VALUES; 717 deletePropertyObjects(dbc, projectId, existingResource, propertyDeleteOption); 718 removeFile(dbc, projectId, existingResource); 719 720 OpenCms.fireCmsEvent( 721 new CmsEvent( 722 I_CmsEventListener.EVENT_RESOURCES_MODIFIED, 723 Collections.<String, Object> singletonMap( 724 I_CmsEventListener.KEY_RESOURCES, 725 modifiedResources))); 726 OpenCms.fireCmsEvent( 727 new CmsEvent( 728 I_CmsEventListener.EVENT_RESOURCE_AND_PROPERTIES_MODIFIED, 729 Collections.<String, Object> singletonMap(I_CmsEventListener.KEY_RESOURCE, existingResource))); 730 } else { 731 // we have a collision: there exists already a resource with the same path/name which cannot be removed 732 throw new CmsVfsResourceAlreadyExistsException( 733 Messages.get().container( 734 Messages.ERR_RESOURCE_WITH_NAME_ALREADY_EXISTS_1, 735 dbc.removeSiteRoot(resource.getRootPath()))); 736 } 737 } catch (CmsVfsResourceNotFoundException e) { 738 // that's what we want in the best case- anything else should be thrown 739 } 740 741 try { 742 // read the parent id 743 String parentId = internalReadParentId(dbc, projectId, resourcePath); 744 745 // use consistent version numbers if the file is being restored 746 int lastVersion = m_driverManager.getHistoryDriver(dbc).readLastVersion(dbc, newStructureId); 747 int newStrVersion = 0; 748 int newResVersion = 0; 749 if (lastVersion > 0) { 750 I_CmsHistoryResource histRes = m_driverManager.getHistoryDriver(dbc).readResource( 751 dbc, 752 newStructureId, 753 lastVersion); 754 newStrVersion = histRes.getStructureVersion(); 755 newResVersion = histRes.getResourceVersion(); 756 } 757 758 // write the structure 759 conn = m_sqlManager.getConnection(dbc); 760 stmt = m_sqlManager.getPreparedStatement(conn, projectId, "C_STRUCTURE_WRITE"); 761 stmt.setString(1, newStructureId.toString()); 762 stmt.setString(2, resource.getResourceId().toString()); 763 stmt.setString(3, resourcePath); 764 stmt.setInt(4, newState.getState()); 765 stmt.setLong(5, resource.getDateReleased()); 766 stmt.setLong(6, resource.getDateExpired()); 767 stmt.setString(7, parentId); 768 stmt.setInt(8, newStrVersion); // starting version number 769 stmt.executeUpdate(); 770 m_sqlManager.closeAll(dbc, conn, stmt, null); 771 772 if (!validateResourceIdExists(dbc, projectId, resource.getResourceId())) { 773 try { 774 // create the resource record 775 conn = m_sqlManager.getConnection(dbc); 776 stmt = m_sqlManager.getPreparedStatement(conn, projectId, "C_RESOURCES_WRITE"); 777 stmt.setString(1, resource.getResourceId().toString()); 778 stmt.setInt(2, resource.getTypeId()); 779 stmt.setInt(3, resource.getFlags()); 780 stmt.setLong(4, dateCreated); 781 stmt.setString(5, resource.getUserCreated().toString()); 782 stmt.setLong(6, dateModified); 783 stmt.setString(7, resource.getUserLastModified().toString()); 784 stmt.setInt(8, newState.getState()); 785 stmt.setInt(9, resource.getLength()); 786 stmt.setLong(10, dateContent); 787 stmt.setString(11, projectId.toString()); 788 stmt.setInt(12, 1); // sibling count 789 stmt.setInt(13, newResVersion); // version number 790 stmt.executeUpdate(); 791 } finally { 792 m_sqlManager.closeAll(dbc, conn, stmt, null); 793 } 794 795 if (resource.isFile() && (content != null)) { 796 // create the file content 797 createContent(dbc, projectId, resource, content); 798 } 799 } else { 800 if ((content != null) || !resource.getState().isKeep()) { 801 CmsUUID projLastMod = projectId; 802 CmsResourceState state = CmsResource.STATE_CHANGED; 803 if (projectId.equals(CmsProject.ONLINE_PROJECT_ID)) { 804 // in case a sibling is being published 805 projLastMod = resource.getProjectLastModified(); 806 state = CmsResource.STATE_UNCHANGED; 807 } 808 // update the resource record only if state has changed or new content is provided 809 int sibCount = countSiblings(dbc, projectId, resource.getResourceId()); 810 conn = m_sqlManager.getConnection(dbc); 811 stmt = m_sqlManager.getPreparedStatement(conn, projectId, "C_RESOURCES_UPDATE_RESOURCES"); 812 stmt.setInt(1, resource.getTypeId()); 813 stmt.setInt(2, resource.getFlags()); 814 stmt.setLong(3, dateModified); 815 stmt.setString(4, resource.getUserLastModified().toString()); 816 stmt.setInt(5, state.getState()); 817 stmt.setInt(6, resource.getLength()); 818 stmt.setLong(7, resource.getDateContent()); 819 stmt.setString(8, projLastMod.toString()); 820 stmt.setInt(9, sibCount); 821 stmt.setString(10, resource.getResourceId().toString()); 822 stmt.executeUpdate(); 823 824 m_sqlManager.closeAll(dbc, conn, stmt, null); 825 } 826 827 if (resource.isFile()) { 828 if (content != null) { 829 // update the file content 830 writeContent(dbc, resource, content); 831 } else if (resource.getState().isKeep()) { 832 // special case sibling creation - update the link Count 833 int sibCount = countSiblings(dbc, projectId, resource.getResourceId()); 834 conn = m_sqlManager.getConnection(dbc); 835 stmt = m_sqlManager.getPreparedStatement(conn, projectId, "C_RESOURCES_UPDATE_SIBLING_COUNT"); 836 stmt.setInt(1, sibCount); 837 stmt.setString(2, resource.getResourceId().toString()); 838 stmt.executeUpdate(); 839 m_sqlManager.closeAll(dbc, null, stmt, null); 840 841 // update the resource flags 842 stmt = m_sqlManager.getPreparedStatement(conn, projectId, "C_RESOURCES_UPDATE_FLAGS"); 843 stmt.setInt(1, resource.getFlags()); 844 stmt.setString(2, resource.getResourceId().toString()); 845 stmt.executeUpdate(); 846 m_sqlManager.closeAll(dbc, conn, stmt, null); 847 } 848 } 849 } 850 } catch (SQLException e) { 851 throw new CmsDbSqlException( 852 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 853 e); 854 } finally { 855 m_sqlManager.closeAll(dbc, conn, stmt, null); 856 } 857 repairBrokenRelations(dbc, projectId, resource.getStructureId(), resource.getRootPath()); 858 return readResource(dbc, projectId, newStructureId, false); 859 } 860 861 /** 862 * @see org.opencms.db.I_CmsVfsDriver#createResource(java.sql.ResultSet, CmsUUID) 863 */ 864 public CmsResource createResource(ResultSet res, CmsUUID projectId) throws SQLException { 865 866 CmsUUID structureId = new CmsUUID(res.getString(m_sqlManager.readQuery("C_RESOURCES_STRUCTURE_ID"))); 867 CmsUUID resourceId = new CmsUUID(res.getString(m_sqlManager.readQuery("C_RESOURCES_RESOURCE_ID"))); 868 String resourcePath = res.getString(m_sqlManager.readQuery("C_RESOURCES_RESOURCE_PATH")); 869 int resourceType = res.getInt(m_sqlManager.readQuery("C_RESOURCES_RESOURCE_TYPE")); 870 int resourceFlags = res.getInt(m_sqlManager.readQuery("C_RESOURCES_RESOURCE_FLAGS")); 871 CmsUUID resourceProjectLastModified = new CmsUUID( 872 res.getString(m_sqlManager.readQuery("C_RESOURCES_PROJECT_LASTMODIFIED"))); 873 int resourceState = res.getInt(m_sqlManager.readQuery("C_RESOURCES_STATE")); 874 int structureState = res.getInt(m_sqlManager.readQuery("C_RESOURCES_STRUCTURE_STATE")); 875 long dateCreated = res.getLong(m_sqlManager.readQuery("C_RESOURCES_DATE_CREATED")); 876 long dateLastModified = res.getLong(m_sqlManager.readQuery("C_RESOURCES_DATE_LASTMODIFIED")); 877 long dateReleased = res.getLong(m_sqlManager.readQuery("C_RESOURCES_DATE_RELEASED")); 878 long dateExpired = res.getLong(m_sqlManager.readQuery("C_RESOURCES_DATE_EXPIRED")); 879 int resourceSize = res.getInt(m_sqlManager.readQuery("C_RESOURCES_SIZE")); 880 boolean isFolder = CmsFolder.isFolderSize(resourceSize); 881 if (isFolder) { 882 // in case of folder type ensure, that the root path has a trailing slash 883 resourcePath = CmsFileUtil.addTrailingSeparator(resourcePath); 884 } 885 long dateContent = isFolder ? -1 : res.getLong(m_sqlManager.readQuery("C_RESOURCES_DATE_CONTENT")); 886 CmsUUID userCreated = new CmsUUID(res.getString(m_sqlManager.readQuery("C_RESOURCES_USER_CREATED"))); 887 CmsUUID userLastModified = new CmsUUID(res.getString(m_sqlManager.readQuery("C_RESOURCES_USER_LASTMODIFIED"))); 888 int siblingCount = res.getInt(m_sqlManager.readQuery("C_RESOURCES_SIBLING_COUNT")); 889 int resourceVersion = res.getInt(m_sqlManager.readQuery("C_RESOURCES_VERSION")); 890 int structureVersion = res.getInt(m_sqlManager.readQuery("C_RESOURCES_STRUCTURE_VERSION")); 891 892 int newState = (structureState > resourceState) ? structureState : resourceState; 893 // if there is a change increase the version number 894 int newVersion = resourceVersion + structureVersion + (newState > 0 ? 1 : 0); 895 896 CmsResource newResource = new CmsResource( 897 structureId, 898 resourceId, 899 resourcePath, 900 resourceType, 901 isFolder, 902 resourceFlags, 903 resourceProjectLastModified, 904 CmsResourceState.valueOf(newState), 905 dateCreated, 906 userCreated, 907 dateLastModified, 908 userLastModified, 909 dateReleased, 910 dateExpired, 911 siblingCount, 912 resourceSize, 913 dateContent, 914 newVersion); 915 916 return newResource; 917 } 918 919 /** 920 * @see org.opencms.db.I_CmsVfsDriver#createSibling(org.opencms.db.CmsDbContext, org.opencms.file.CmsProject, org.opencms.file.CmsResource) 921 */ 922 public void createSibling(CmsDbContext dbc, CmsProject project, CmsResource resource) 923 throws CmsDataAccessException { 924 925 if (!project.getUuid().equals(CmsProject.ONLINE_PROJECT_ID)) { 926 // this method is only intended to be used during publishing 927 return; 928 } 929 930 // check if the resource already exists 931 CmsResource existingSibling = null; 932 CmsUUID newStructureId = resource.getStructureId(); 933 934 Connection conn = null; 935 PreparedStatement stmt = null; 936 try { 937 existingSibling = readResource(dbc, project.getUuid(), resource.getRootPath(), true); 938 939 if (existingSibling.getState().isDeleted()) { 940 // if an existing resource is deleted, it will be finally removed now. 941 // but we have to reuse its id in order to avoid orphans in the online project. 942 newStructureId = existingSibling.getStructureId(); 943 944 // remove the existing file and it's properties 945 List<CmsResource> modifiedResources = readSiblings(dbc, project.getUuid(), existingSibling, false); 946 int propertyDeleteOption = (existingSibling.getSiblingCount() > 1) 947 ? CmsProperty.DELETE_OPTION_DELETE_STRUCTURE_VALUES 948 : CmsProperty.DELETE_OPTION_DELETE_STRUCTURE_AND_RESOURCE_VALUES; 949 deletePropertyObjects(dbc, project.getUuid(), existingSibling, propertyDeleteOption); 950 removeFile(dbc, project.getUuid(), existingSibling); 951 952 OpenCms.fireCmsEvent( 953 new CmsEvent( 954 I_CmsEventListener.EVENT_RESOURCES_MODIFIED, 955 Collections.<String, Object> singletonMap( 956 I_CmsEventListener.KEY_RESOURCES, 957 modifiedResources))); 958 OpenCms.fireCmsEvent( 959 new CmsEvent( 960 I_CmsEventListener.EVENT_RESOURCE_AND_PROPERTIES_MODIFIED, 961 Collections.<String, Object> singletonMap(I_CmsEventListener.KEY_RESOURCE, existingSibling))); 962 } else { 963 // we have a collision: there exists already a resource with the same path/name which could not be removed 964 throw new CmsVfsResourceAlreadyExistsException( 965 Messages.get().container( 966 Messages.ERR_RESOURCE_WITH_NAME_ALREADY_EXISTS_1, 967 dbc.removeSiteRoot(resource.getRootPath()))); 968 } 969 } catch (CmsVfsResourceNotFoundException e) { 970 // that's what we want in the best case- anything else should be thrown 971 } 972 973 // check if a resource with the specified ID already exists 974 if (!validateResourceIdExists(dbc, project.getUuid(), resource.getResourceId())) { 975 throw new CmsVfsResourceNotFoundException( 976 Messages.get().container( 977 Messages.ERR_CREATE_SIBLING_FILE_NOT_FOUND_1, 978 dbc.removeSiteRoot(resource.getRootPath()))); 979 } 980 981 // write a new structure referring to the resource 982 try { 983 // use consistent version numbers if the file is being restored 984 int lastVersion = m_driverManager.getHistoryDriver(dbc).readLastVersion(dbc, newStructureId); 985 int newStrVersion = 0; 986 if (lastVersion > 0) { 987 I_CmsHistoryResource histRes = m_driverManager.getHistoryDriver(dbc).readResource( 988 dbc, 989 newStructureId, 990 lastVersion); 991 newStrVersion = histRes.getStructureVersion(); 992 } 993 994 // read the parent id 995 String parentId = internalReadParentId(dbc, project.getUuid(), resource.getRootPath()); 996 997 conn = m_sqlManager.getConnection(dbc); 998 999 // write the structure 1000 stmt = m_sqlManager.getPreparedStatement(conn, project, "C_STRUCTURE_WRITE"); 1001 stmt.setString(1, newStructureId.toString()); 1002 stmt.setString(2, resource.getResourceId().toString()); 1003 stmt.setString(3, resource.getRootPath()); 1004 stmt.setInt(4, CmsResource.STATE_UNCHANGED.getState()); 1005 stmt.setLong(5, resource.getDateReleased()); 1006 stmt.setLong(6, resource.getDateExpired()); 1007 stmt.setString(7, parentId); 1008 stmt.setInt(8, newStrVersion); // initial structure version number 1009 stmt.executeUpdate(); 1010 m_sqlManager.closeAll(dbc, conn, stmt, null); 1011 1012 int sibCount = countSiblings(dbc, project.getUuid(), resource.getResourceId()); 1013 conn = m_sqlManager.getConnection(dbc); 1014 1015 // update the link Count 1016 stmt = m_sqlManager.getPreparedStatement(conn, project, "C_RESOURCES_UPDATE_SIBLING_COUNT"); 1017 stmt.setInt(1, sibCount); 1018 stmt.setString(2, resource.getResourceId().toString()); 1019 stmt.executeUpdate(); 1020 1021 m_sqlManager.closeAll(dbc, null, stmt, null); 1022 1023 // update the project last modified and flags 1024 stmt = m_sqlManager.getPreparedStatement(conn, project, "C_RESOURCES_UPDATE_RESOURCE_PROJECT"); 1025 stmt.setInt(1, resource.getFlags()); 1026 stmt.setString(2, resource.getProjectLastModified().toString()); 1027 stmt.setString(3, resource.getResourceId().toString()); 1028 stmt.executeUpdate(); 1029 } catch (SQLException e) { 1030 throw new CmsDbSqlException( 1031 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 1032 e); 1033 } finally { 1034 m_sqlManager.closeAll(dbc, conn, stmt, null); 1035 } 1036 repairBrokenRelations(dbc, project.getUuid(), resource.getStructureId(), resource.getRootPath()); 1037 } 1038 1039 /** 1040 * @see org.opencms.db.I_CmsVfsDriver#deleteAliases(org.opencms.db.CmsDbContext, org.opencms.file.CmsProject, org.opencms.db.CmsAliasFilter) 1041 */ 1042 public void deleteAliases(CmsDbContext dbc, CmsProject project, CmsAliasFilter filter) 1043 throws CmsDataAccessException { 1044 1045 Connection conn = null; 1046 PreparedStatement stmt = null; 1047 ResultSet res = null; 1048 if (filter.isNullFilter()) { 1049 throw new IllegalArgumentException("Trivial filter is not allowed for deleting aliases."); 1050 } 1051 try { 1052 conn = m_sqlManager.getConnection(dbc); 1053 CmsPair<String, List<String>> filterData = buildAliasConditions(filter); 1054 String sql = "DELETE FROM CMS_ALIASES WHERE " + filterData.getFirst(); 1055 stmt = m_sqlManager.getPreparedStatementForSql(conn, sql); 1056 List<String> conditionParams = filterData.getSecond(); 1057 for (int i = 0; i < conditionParams.size(); i++) { 1058 stmt.setString(1 + i, conditionParams.get(i)); 1059 } 1060 stmt.executeUpdate(); 1061 } catch (SQLException e) { 1062 throw new CmsDbSqlException( 1063 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 1064 e); 1065 } finally { 1066 m_sqlManager.closeAll(dbc, conn, stmt, res); 1067 } 1068 } 1069 1070 /** 1071 * @see org.opencms.db.I_CmsVfsDriver#deleteHistoryContent(org.opencms.db.CmsDbContext, org.opencms.util.CmsUUID, int) 1072 */ 1073 public void deleteHistoryContent(CmsDbContext dbc, CmsUUID resourceId, int publishTagToKeep) 1074 throws CmsDataAccessException { 1075 1076 Connection conn = null; 1077 PreparedStatement stmt = null; 1078 try { 1079 conn = m_sqlManager.getConnection(dbc); 1080 stmt = m_sqlManager.getPreparedStatement(conn, "C_CONTENT_HISTORY_DELETE"); 1081 stmt.setString(1, resourceId.toString()); 1082 stmt.setInt(2, publishTagToKeep); 1083 stmt.executeUpdate(); 1084 } catch (SQLException e) { 1085 throw new CmsDbSqlException( 1086 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 1087 e); 1088 } finally { 1089 m_sqlManager.closeAll(dbc, conn, stmt, null); 1090 } 1091 } 1092 1093 /** 1094 * @see org.opencms.db.I_CmsVfsDriver#deletePropertyDefinition(org.opencms.db.CmsDbContext, org.opencms.file.CmsPropertyDefinition) 1095 */ 1096 public void deletePropertyDefinition(CmsDbContext dbc, CmsPropertyDefinition metadef) 1097 throws CmsDataAccessException { 1098 1099 Connection conn = null; 1100 PreparedStatement stmt = null; 1101 1102 try { 1103 if ((internalCountProperties(dbc, metadef, CmsProject.ONLINE_PROJECT_ID) != 0) 1104 || (internalCountProperties(dbc, metadef, CmsUUID.getOpenCmsUUID()) != 0)) { // HACK: to get an offline project 1105 1106 throw new CmsDataAccessException( 1107 Messages.get().container(Messages.ERR_DELETE_USED_PROPERTY_1, metadef.getName())); 1108 } 1109 1110 conn = m_sqlManager.getConnection(dbc); 1111 1112 for (int i = 0; i < 2; i++) { 1113 if (i == 0) { 1114 // delete the offline property definition 1115 stmt = m_sqlManager.getPreparedStatement(conn, CmsUUID.getOpenCmsUUID(), "C_PROPERTYDEF_DELETE"); // HACK: to get an offline project 1116 } else { 1117 // delete the online property definition 1118 stmt = m_sqlManager.getPreparedStatement( 1119 conn, 1120 CmsProject.ONLINE_PROJECT_ID, 1121 "C_PROPERTYDEF_DELETE"); 1122 } 1123 1124 stmt.setString(1, metadef.getId().toString()); 1125 stmt.executeUpdate(); 1126 m_sqlManager.closeAll(dbc, null, stmt, null); 1127 } 1128 } catch (SQLException e) { 1129 throw new CmsDbSqlException( 1130 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 1131 e); 1132 } finally { 1133 m_sqlManager.closeAll(dbc, conn, stmt, null); 1134 } 1135 } 1136 1137 /** 1138 * @see org.opencms.db.I_CmsVfsDriver#deletePropertyObjects(org.opencms.db.CmsDbContext, CmsUUID, org.opencms.file.CmsResource, int) 1139 */ 1140 public void deletePropertyObjects(CmsDbContext dbc, CmsUUID projectId, CmsResource resource, int deleteOption) 1141 throws CmsDataAccessException { 1142 1143 Connection conn = null; 1144 PreparedStatement stmt = null; 1145 1146 try { 1147 conn = m_sqlManager.getConnection(dbc); 1148 1149 if (deleteOption == CmsProperty.DELETE_OPTION_DELETE_STRUCTURE_AND_RESOURCE_VALUES) { 1150 // delete both the structure and resource property values mapped to the specified resource 1151 stmt = m_sqlManager.getPreparedStatement( 1152 conn, 1153 projectId, 1154 "C_PROPERTIES_DELETE_ALL_STRUCTURE_AND_RESOURCE_VALUES"); 1155 stmt.setString(1, resource.getResourceId().toString()); 1156 stmt.setInt(2, CmsProperty.RESOURCE_RECORD_MAPPING); 1157 stmt.setString(3, resource.getStructureId().toString()); 1158 stmt.setInt(4, CmsProperty.STRUCTURE_RECORD_MAPPING); 1159 } else if (deleteOption == CmsProperty.DELETE_OPTION_DELETE_STRUCTURE_VALUES) { 1160 // delete the structure values mapped to the specified resource 1161 stmt = m_sqlManager.getPreparedStatement( 1162 conn, 1163 projectId, 1164 "C_PROPERTIES_DELETE_ALL_VALUES_FOR_MAPPING_TYPE"); 1165 stmt.setString(1, resource.getStructureId().toString()); 1166 stmt.setInt(2, CmsProperty.STRUCTURE_RECORD_MAPPING); 1167 } else if (deleteOption == CmsProperty.DELETE_OPTION_DELETE_RESOURCE_VALUES) { 1168 // delete the resource property values mapped to the specified resource 1169 stmt = m_sqlManager.getPreparedStatement( 1170 conn, 1171 projectId, 1172 "C_PROPERTIES_DELETE_ALL_VALUES_FOR_MAPPING_TYPE"); 1173 stmt.setString(1, resource.getResourceId().toString()); 1174 stmt.setInt(2, CmsProperty.RESOURCE_RECORD_MAPPING); 1175 } else { 1176 throw new CmsDataAccessException(Messages.get().container(Messages.ERR_INVALID_DELETE_OPTION_1)); 1177 } 1178 1179 stmt.executeUpdate(); 1180 } catch (SQLException e) { 1181 throw new CmsDbSqlException( 1182 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 1183 e); 1184 } finally { 1185 m_sqlManager.closeAll(dbc, conn, stmt, null); 1186 } 1187 } 1188 1189 /** 1190 * @see org.opencms.db.I_CmsVfsDriver#deleteRelations(org.opencms.db.CmsDbContext, CmsUUID, CmsResource, org.opencms.relations.CmsRelationFilter) 1191 */ 1192 public void deleteRelations(CmsDbContext dbc, CmsUUID projectId, CmsResource resource, CmsRelationFilter filter) 1193 throws CmsDataAccessException { 1194 1195 Connection conn = null; 1196 PreparedStatement stmt = null; 1197 1198 try { 1199 conn = m_sqlManager.getConnection(dbc); 1200 1201 if (filter.isSource()) { 1202 List<Object> params = new ArrayList<Object>(7); 1203 1204 StringBuffer queryBuf = new StringBuffer(256); 1205 queryBuf.append(m_sqlManager.readQuery(projectId, "C_DELETE_RELATIONS")); 1206 queryBuf.append( 1207 prepareRelationConditions(RelationConditionMode.delete, projectId, filter, resource, params, true)); 1208 1209 stmt = m_sqlManager.getPreparedStatementForSql(conn, queryBuf.toString()); 1210 for (int i = 0; i < params.size(); i++) { 1211 if (params.get(i) instanceof Integer) { 1212 stmt.setInt(i + 1, ((Integer)params.get(i)).intValue()); 1213 } else { 1214 stmt.setString(i + 1, (String)params.get(i)); 1215 } 1216 } 1217 stmt.executeUpdate(); 1218 m_sqlManager.closeAll(dbc, null, stmt, null); 1219 } 1220 if (filter.isTarget()) { 1221 List<Object> params = new ArrayList<Object>(7); 1222 1223 StringBuffer queryBuf = new StringBuffer(256); 1224 queryBuf.append(m_sqlManager.readQuery(projectId, "C_DELETE_RELATIONS")); 1225 queryBuf.append( 1226 prepareRelationConditions( 1227 RelationConditionMode.delete, 1228 projectId, 1229 filter, 1230 resource, 1231 params, 1232 false)); 1233 1234 stmt = m_sqlManager.getPreparedStatementForSql(conn, queryBuf.toString()); 1235 for (int i = 0; i < params.size(); i++) { 1236 if (params.get(i) instanceof Integer) { 1237 stmt.setInt(i + 1, ((Integer)params.get(i)).intValue()); 1238 } else { 1239 stmt.setString(i + 1, (String)params.get(i)); 1240 } 1241 } 1242 stmt.executeUpdate(); 1243 m_sqlManager.closeAll(dbc, null, stmt, null); 1244 } 1245 } catch (SQLException e) { 1246 throw new CmsDbSqlException( 1247 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 1248 e); 1249 } finally { 1250 m_sqlManager.closeAll(dbc, conn, stmt, null); 1251 } 1252 // update broken remaining relations 1253 updateBrokenRelations(dbc, projectId, resource.getRootPath()); 1254 } 1255 1256 /** 1257 * @see org.opencms.db.I_CmsVfsDriver#deleteRewriteAliases(org.opencms.db.CmsDbContext, org.opencms.db.CmsRewriteAliasFilter) 1258 */ 1259 public void deleteRewriteAliases(CmsDbContext dbc, CmsRewriteAliasFilter filter) throws CmsDataAccessException { 1260 1261 Connection conn = null; 1262 PreparedStatement stmt = null; 1263 try { 1264 conn = m_sqlManager.getConnection(dbc); 1265 CmsPair<String, List<Object>> conditionAndParams = prepareRewriteAliasConditions(filter); 1266 String condition = conditionAndParams.getFirst(); 1267 List<Object> params = conditionAndParams.getSecond(); 1268 String query = "DELETE FROM CMS_REWRITES WHERE " + condition; 1269 stmt = m_sqlManager.getPreparedStatementForSql(conn, query); 1270 CmsDbUtil.fillParameters(stmt, params); 1271 stmt.execute(); 1272 } catch (SQLException e) { 1273 throw wrapException(stmt, e); 1274 } finally { 1275 m_sqlManager.closeAll(dbc, conn, stmt, null); 1276 } 1277 } 1278 1279 /** 1280 * @see org.opencms.db.I_CmsVfsDriver#deleteUrlNameMappingEntries(org.opencms.db.CmsDbContext, boolean, org.opencms.db.urlname.CmsUrlNameMappingFilter) 1281 */ 1282 public void deleteUrlNameMappingEntries(CmsDbContext dbc, boolean online, CmsUrlNameMappingFilter filter) 1283 throws CmsDataAccessException { 1284 1285 Connection conn = null; 1286 PreparedStatement stmt = null; 1287 try { 1288 conn = m_sqlManager.getConnection(dbc); 1289 String query = m_sqlManager.readQuery("C_DELETE_URLNAME_MAPPINGS"); 1290 query = replaceProject(query, online); 1291 stmt = getPreparedStatementForFilter(conn, query, filter); 1292 stmt.executeUpdate(); 1293 } catch (SQLException e) { 1294 throw wrapException(stmt, e); 1295 } finally { 1296 m_sqlManager.closeAll(dbc, conn, stmt, null); 1297 } 1298 } 1299 1300 /** 1301 * @see org.opencms.db.I_CmsVfsDriver#destroy() 1302 */ 1303 public void destroy() throws Throwable { 1304 1305 m_sqlManager = null; 1306 m_driverManager = null; 1307 1308 if (CmsLog.INIT.isInfoEnabled()) { 1309 CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_SHUTDOWN_DRIVER_1, getClass().getName())); 1310 } 1311 } 1312 1313 /** 1314 * Returns all organizational units for the given resource.<p> 1315 * 1316 * @param dbc the database context 1317 * @param projectId the id of the project 1318 * @param resource the resource 1319 * 1320 * @return a list of {@link org.opencms.security.CmsOrganizationalUnit} objects 1321 * 1322 * @throws CmsDbSqlException if something goes wrong 1323 */ 1324 public List<CmsOrganizationalUnit> getResourceOus(CmsDbContext dbc, CmsUUID projectId, CmsResource resource) 1325 throws CmsDbSqlException { 1326 1327 List<CmsOrganizationalUnit> ous = new ArrayList<CmsOrganizationalUnit>(); 1328 String resName = resource.getRootPath(); 1329 if (resource.isFolder() && !resName.endsWith("/")) { 1330 resName += "/"; 1331 } 1332 1333 Connection conn = null; 1334 PreparedStatement stmt = null; 1335 ResultSet res = null; 1336 List<CmsRelation> rels = new ArrayList<CmsRelation>(); 1337 1338 try { 1339 conn = m_sqlManager.getConnection(dbc); 1340 stmt = m_sqlManager.getPreparedStatementForSql( 1341 conn, 1342 m_sqlManager.readQuery(projectId, "C_READ_RESOURCE_OUS")); 1343 stmt.setInt(1, CmsRelationType.OU_RESOURCE.getId()); 1344 stmt.setString(2, resName); 1345 res = stmt.executeQuery(); 1346 while (res.next()) { 1347 rels.add(internalReadRelation(res)); 1348 } 1349 } catch (SQLException e) { 1350 throw new CmsDbSqlException( 1351 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 1352 e); 1353 } finally { 1354 m_sqlManager.closeAll(dbc, conn, stmt, res); 1355 } 1356 1357 for (CmsRelation rel : rels) { 1358 try { 1359 ous.add( 1360 m_driverManager.readOrganizationalUnit( 1361 dbc, 1362 rel.getSourcePath().substring(CmsUserDriver.ORGUNIT_BASE_FOLDER.length()))); 1363 } catch (CmsException e) { 1364 // should never happen 1365 if (LOG.isErrorEnabled()) { 1366 LOG.error(e.getLocalizedMessage(), e); 1367 } 1368 } 1369 } 1370 return ous; 1371 } 1372 1373 /** 1374 * @see org.opencms.db.I_CmsVfsDriver#getSqlManager() 1375 */ 1376 public CmsSqlManager getSqlManager() { 1377 1378 return m_sqlManager; 1379 } 1380 1381 /** 1382 * @see org.opencms.db.I_CmsVfsDriver#incrementCounter(org.opencms.db.CmsDbContext, java.lang.String) 1383 */ 1384 public int incrementCounter(CmsDbContext dbc, String name) throws CmsDataAccessException { 1385 1386 Integer counterObj = internalReadCounter(dbc, name); 1387 int result; 1388 if (counterObj == null) { 1389 internalCreateCounter(dbc, name, 1); 1390 result = 0; 1391 } else { 1392 result = counterObj.intValue(); 1393 internalIncrementCounter(dbc, name); 1394 } 1395 return result; 1396 } 1397 1398 /** 1399 * @see org.opencms.db.I_CmsDriver#init(org.opencms.db.CmsDbContext, org.opencms.configuration.CmsConfigurationManager, java.util.List, org.opencms.db.CmsDriverManager) 1400 */ 1401 public void init( 1402 CmsDbContext dbc, 1403 CmsConfigurationManager configurationManager, 1404 List<String> successiveDrivers, 1405 CmsDriverManager driverManager) { 1406 1407 CmsParameterConfiguration configuration = configurationManager.getConfiguration(); 1408 String poolUrl = configuration.get("db.vfs.pool"); 1409 String classname = configuration.get("db.vfs.sqlmanager"); 1410 m_sqlManager = initSqlManager(classname, getAdditionalSqlQueryProperties(configuration)); 1411 m_sqlManager.init(I_CmsVfsDriver.DRIVER_TYPE_ID, poolUrl); 1412 1413 m_driverManager = driverManager; 1414 1415 if (CmsLog.INIT.isInfoEnabled()) { 1416 CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_ASSIGNED_POOL_1, poolUrl)); 1417 } 1418 1419 if ((successiveDrivers != null) && !successiveDrivers.isEmpty()) { 1420 if (LOG.isWarnEnabled()) { 1421 LOG.warn( 1422 Messages.get().getBundle().key( 1423 Messages.LOG_SUCCESSIVE_DRIVERS_UNSUPPORTED_1, 1424 getClass().getName())); 1425 } 1426 } 1427 } 1428 1429 /** 1430 * @see org.opencms.db.I_CmsVfsDriver#initSqlManager(String) 1431 */ 1432 public org.opencms.db.generic.CmsSqlManager initSqlManager(String classname) { 1433 1434 return CmsSqlManager.getInstance(classname); 1435 } 1436 1437 /** 1438 * Initializes the SQL manager for this driver and loads additional SQL query property files.<p> 1439 * 1440 * @param classname the class name of the SQL manager 1441 * @param additionalQueryProperties the additional SQL query property files to load 1442 * 1443 * @return the SQL manager for this driver 1444 */ 1445 public org.opencms.db.generic.CmsSqlManager initSqlManager( 1446 String classname, 1447 List<String> additionalQueryProperties) { 1448 1449 return CmsSqlManager.getInstance(classname, additionalQueryProperties); 1450 } 1451 1452 /** 1453 * @see org.opencms.db.I_CmsVfsDriver#insertAlias(org.opencms.db.CmsDbContext, org.opencms.file.CmsProject, org.opencms.db.CmsAlias) 1454 */ 1455 public void insertAlias(CmsDbContext dbc, CmsProject project, CmsAlias alias) throws CmsDataAccessException { 1456 1457 Connection conn = null; 1458 PreparedStatement stmt = null; 1459 ResultSet res = null; 1460 try { 1461 conn = m_sqlManager.getConnection(dbc); 1462 stmt = m_sqlManager.getPreparedStatement(conn, project, "C_ALIAS_ADD_4"); 1463 stmt.setString(1, alias.getSiteRoot()); 1464 stmt.setString(2, alias.getAliasPath()); 1465 stmt.setInt(3, alias.getMode().toInt()); 1466 stmt.setString(4, alias.getStructureId().toString()); 1467 stmt.executeUpdate(); 1468 1469 } catch (SQLException e) { 1470 throw new CmsDbSqlException( 1471 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 1472 e); 1473 } finally { 1474 m_sqlManager.closeAll(dbc, conn, stmt, res); 1475 } 1476 } 1477 1478 /** 1479 * @see org.opencms.db.I_CmsVfsDriver#insertRewriteAliases(org.opencms.db.CmsDbContext, java.util.Collection) 1480 */ 1481 public void insertRewriteAliases(CmsDbContext dbc, Collection<CmsRewriteAlias> rewriteAliases) 1482 throws CmsDataAccessException { 1483 1484 Connection conn = null; 1485 PreparedStatement stmt = null; 1486 ResultSet res = null; 1487 if (!rewriteAliases.isEmpty()) { 1488 try { 1489 conn = m_sqlManager.getConnection(dbc); 1490 stmt = m_sqlManager.getPreparedStatement(conn, dbc.currentProject(), "C_REWRITE_ALIAS_INSERT_5"); 1491 for (CmsRewriteAlias alias : rewriteAliases) { 1492 stmt.setString(1, alias.getId().toString()); 1493 stmt.setString(2, alias.getSiteRoot()); 1494 stmt.setString(3, alias.getPatternString()); 1495 stmt.setString(4, alias.getReplacementString()); 1496 stmt.setInt(5, alias.getMode().toInt()); 1497 stmt.addBatch(); 1498 } 1499 stmt.executeBatch(); 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, res); 1506 } 1507 } 1508 } 1509 1510 /** 1511 * @see org.opencms.db.I_CmsVfsDriver#moveResource(CmsDbContext, CmsUUID, CmsResource, String) 1512 */ 1513 public void moveResource(CmsDbContext dbc, CmsUUID projectId, CmsResource source, String destinationPath) 1514 throws CmsDataAccessException { 1515 1516 if ((dbc.getRequestContext() != null) 1517 && (dbc.getRequestContext().getAttribute(REQ_ATTR_CHECK_PERMISSIONS) != null)) { 1518 // only check write permissions 1519 checkWritePermissionsInFolder(dbc, source); 1520 return; 1521 } 1522 1523 // determine destination folder 1524 String destinationFoldername = CmsResource.getParentFolder(destinationPath); 1525 1526 // read the destination folder (will also check read permissions) 1527 CmsFolder destinationFolder = m_driverManager.readFolder(dbc, destinationFoldername, CmsResourceFilter.ALL); 1528 1529 if (!projectId.equals(CmsProject.ONLINE_PROJECT_ID)) { 1530 // check online resource 1531 try { 1532 CmsResource onlineResource = m_driverManager.getVfsDriver( 1533 dbc).readResource(dbc, CmsProject.ONLINE_PROJECT_ID, destinationPath, true); 1534 1535 if (!onlineResource.getStructureId().equals(source.getStructureId())) { 1536 // source resource has been moved and it is not the 1537 // same as the resource that is being trying to move back 1538 CmsResource offlineResource = null; 1539 try { 1540 // read new location in offline project 1541 offlineResource = readResource( 1542 dbc, 1543 dbc.getRequestContext().getCurrentProject().getUuid(), 1544 onlineResource.getStructureId(), 1545 true); 1546 } catch (CmsException e) { 1547 // should never happen 1548 if (LOG.isErrorEnabled()) { 1549 LOG.error(e.getMessage(), e); 1550 } 1551 } 1552 1553 throw new CmsVfsOnlineResourceAlreadyExistsException( 1554 Messages.get().container( 1555 Messages.ERR_OVERWRITE_MOVED_RESOURCE_3, 1556 dbc.removeSiteRoot(source.getRootPath()), 1557 dbc.removeSiteRoot(destinationPath), 1558 dbc.removeSiteRoot(offlineResource == null ? "__ERROR__" : offlineResource.getRootPath()))); 1559 } 1560 } catch (CmsVfsResourceNotFoundException e) { 1561 // ok, no online resource 1562 } 1563 } 1564 1565 Connection conn = null; 1566 PreparedStatement stmt = null; 1567 ResultSet res = null; 1568 1569 try { 1570 conn = m_sqlManager.getConnection(dbc); 1571 1572 stmt = m_sqlManager.getPreparedStatement(conn, projectId, "C_RESOURCES_MOVE"); 1573 stmt.setString(1, CmsFileUtil.removeTrailingSeparator(destinationPath)); // must remove trailing slash 1574 stmt.setString(2, destinationFolder.getStructureId().toString()); 1575 stmt.setString(3, source.getStructureId().toString()); 1576 stmt.executeUpdate(); 1577 } catch (SQLException e) { 1578 throw new CmsDbSqlException( 1579 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 1580 e); 1581 } finally { 1582 m_sqlManager.closeAll(dbc, conn, stmt, res); 1583 } 1584 1585 moveRelations(dbc, projectId, source.getStructureId(), destinationPath); 1586 repairBrokenRelations(dbc, projectId, source.getStructureId(), destinationPath); 1587 // repair project resources 1588 if (!projectId.equals(CmsProject.ONLINE_PROJECT_ID) && (dbc.getRequestContext() != null)) { 1589 String deletedResourceRootPath = source.getRootPath(); 1590 dbc.getRequestContext().setAttribute(CmsProjectDriver.DBC_ATTR_READ_PROJECT_FOR_RESOURCE, Boolean.TRUE); 1591 I_CmsProjectDriver projectDriver = m_driverManager.getProjectDriver(dbc); 1592 Iterator<CmsProject> itProjects = projectDriver.readProjects(dbc, deletedResourceRootPath).iterator(); 1593 while (itProjects.hasNext()) { 1594 CmsProject project = itProjects.next(); 1595 projectDriver.deleteProjectResource(dbc, project.getUuid(), deletedResourceRootPath); 1596 projectDriver.createProjectResource(dbc, project.getUuid(), destinationPath); 1597 } 1598 } 1599 } 1600 1601 /** 1602 * @see org.opencms.db.I_CmsVfsDriver#publishResource(org.opencms.db.CmsDbContext, org.opencms.file.CmsProject, org.opencms.file.CmsResource, org.opencms.file.CmsResource) 1603 */ 1604 public void publishResource( 1605 CmsDbContext dbc, 1606 CmsProject onlineProject, 1607 CmsResource onlineResource, 1608 CmsResource offlineResource) 1609 throws CmsDataAccessException { 1610 1611 Connection conn = null; 1612 PreparedStatement stmt = null; 1613 1614 // validate the resource length 1615 internalValidateResourceLength(offlineResource); 1616 int resourceSize = offlineResource.getLength(); 1617 1618 String resourcePath = CmsFileUtil.removeTrailingSeparator(offlineResource.getRootPath()); 1619 1620 try { 1621 int sibCount = countSiblings(dbc, onlineProject.getUuid(), onlineResource.getResourceId()); 1622 boolean resourceExists = validateResourceIdExists( 1623 dbc, 1624 onlineProject.getUuid(), 1625 offlineResource.getResourceId()); 1626 conn = m_sqlManager.getConnection(dbc); 1627 if (resourceExists) { 1628 // the resource record exists online already 1629 // update the online resource record 1630 stmt = m_sqlManager.getPreparedStatement(conn, onlineProject, "C_RESOURCES_UPDATE_RESOURCES"); 1631 stmt.setInt(1, offlineResource.getTypeId()); 1632 stmt.setInt(2, offlineResource.getFlags()); 1633 stmt.setLong(3, offlineResource.getDateLastModified()); 1634 stmt.setString(4, offlineResource.getUserLastModified().toString()); 1635 stmt.setInt(5, CmsResource.STATE_UNCHANGED.getState()); 1636 stmt.setInt(6, resourceSize); 1637 stmt.setLong(7, offlineResource.getDateContent()); 1638 stmt.setString(8, offlineResource.getProjectLastModified().toString()); 1639 stmt.setInt(9, sibCount); 1640 stmt.setString(10, offlineResource.getResourceId().toString()); 1641 stmt.executeUpdate(); 1642 m_sqlManager.closeAll(dbc, conn, stmt, null); 1643 } else { 1644 // the resource record does NOT exist online yet 1645 // create the resource record online 1646 stmt = m_sqlManager.getPreparedStatement(conn, onlineProject, "C_RESOURCES_WRITE"); 1647 stmt.setString(1, offlineResource.getResourceId().toString()); 1648 stmt.setInt(2, offlineResource.getTypeId()); 1649 stmt.setInt(3, offlineResource.getFlags()); 1650 stmt.setLong(4, offlineResource.getDateCreated()); 1651 stmt.setString(5, offlineResource.getUserCreated().toString()); 1652 stmt.setLong(6, offlineResource.getDateLastModified()); 1653 stmt.setString(7, offlineResource.getUserLastModified().toString()); 1654 stmt.setInt(8, CmsResource.STATE_UNCHANGED.getState()); 1655 stmt.setInt(9, resourceSize); 1656 stmt.setLong(10, offlineResource.getDateContent()); 1657 stmt.setString(11, offlineResource.getProjectLastModified().toString()); 1658 stmt.setInt(12, 1); // initial siblings count 1659 stmt.setInt(13, 1); // initial resource version 1660 stmt.executeUpdate(); 1661 m_sqlManager.closeAll(dbc, conn, stmt, null); 1662 } 1663 1664 // read the parent id 1665 String parentId = internalReadParentId(dbc, onlineProject.getUuid(), resourcePath); 1666 boolean structureExists = validateStructureIdExists( 1667 dbc, 1668 onlineProject.getUuid(), 1669 offlineResource.getStructureId()); 1670 conn = m_sqlManager.getConnection(dbc); 1671 if (structureExists) { 1672 // update the online structure record 1673 stmt = m_sqlManager.getPreparedStatement(conn, onlineProject, "C_RESOURCES_UPDATE_STRUCTURE"); 1674 stmt.setString(1, offlineResource.getResourceId().toString()); 1675 stmt.setString(2, resourcePath); 1676 stmt.setInt(3, CmsResource.STATE_UNCHANGED.getState()); 1677 stmt.setLong(4, offlineResource.getDateReleased()); 1678 stmt.setLong(5, offlineResource.getDateExpired()); 1679 stmt.setString(6, parentId); 1680 stmt.setString(7, offlineResource.getStructureId().toString()); 1681 stmt.executeUpdate(); 1682 m_sqlManager.closeAll(dbc, null, stmt, null); 1683 } else { 1684 // create the structure record online 1685 stmt = m_sqlManager.getPreparedStatement(conn, onlineProject, "C_STRUCTURE_WRITE"); 1686 stmt.setString(1, offlineResource.getStructureId().toString()); 1687 stmt.setString(2, offlineResource.getResourceId().toString()); 1688 stmt.setString(3, resourcePath); 1689 stmt.setInt(4, CmsResource.STATE_UNCHANGED.getState()); 1690 stmt.setLong(5, offlineResource.getDateReleased()); 1691 stmt.setLong(6, offlineResource.getDateExpired()); 1692 stmt.setString(7, parentId); 1693 stmt.setInt(8, resourceExists ? 1 : 0); // new resources start with 0, new siblings with 1 1694 stmt.executeUpdate(); 1695 m_sqlManager.closeAll(dbc, null, stmt, null); 1696 } 1697 } catch (SQLException e) { 1698 throw new CmsDbSqlException( 1699 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 1700 e); 1701 } finally { 1702 m_sqlManager.closeAll(dbc, conn, stmt, null); 1703 } 1704 1705 try (Connection conn2 = m_sqlManager.getConnection(dbc)) { 1706 stmt = m_sqlManager.getPreparedStatement(conn2, onlineProject, "C_RELATIONS_REPAIR_BROKEN"); 1707 stmt.setString(1, offlineResource.getStructureId().toString()); 1708 stmt.setString(2, offlineResource.getRootPath()); 1709 stmt.executeUpdate(); 1710 } catch (SQLException e) { 1711 throw new CmsDbSqlException( 1712 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 1713 e); 1714 } 1715 } 1716 1717 /** 1718 * @see org.opencms.db.I_CmsVfsDriver#publishVersions(org.opencms.db.CmsDbContext, org.opencms.file.CmsResource, boolean) 1719 */ 1720 public void publishVersions(CmsDbContext dbc, CmsResource resource, boolean firstSibling) 1721 throws CmsDataAccessException { 1722 1723 // if resource is null just flush the internal cache 1724 if (resource == null) { 1725 m_resOp.clear(); 1726 return; 1727 } 1728 1729 if (!dbc.getProjectId().isNullUUID() || dbc.currentProject().isOnlineProject()) { 1730 // this method is supposed to be used only in the offline project 1731 return; 1732 } 1733 1734 if (firstSibling) { 1735 // reset the resource operation flag 1736 m_resOp.remove(resource.getResourceId()); 1737 } 1738 1739 boolean resOp = false; // assume structure operation 1740 1741 CmsResourceState resState = internalReadResourceState(dbc, dbc.currentProject().getUuid(), resource); 1742 CmsResourceState strState = internalReadStructureState(dbc, dbc.currentProject().getUuid(), resource); 1743 1744 if (!resState.isUnchanged()) { 1745 if (strState.isDeleted()) { 1746 resOp = (resState.isDeleted() 1747 || (resource.getSiblingCount() == 1) 1748 || (countSiblings(dbc, dbc.currentProject().getUuid(), resource.getResourceId()) == 1)); 1749 } else { 1750 resOp = true; 1751 } 1752 } 1753 1754 if (!firstSibling) { 1755 if (resOp) { 1756 return; 1757 } 1758 if (m_resOp.contains(resource.getResourceId())) { 1759 return; 1760 } 1761 } 1762 1763 // read the offline version numbers 1764 Map<String, Integer> versions = readVersions( 1765 dbc, 1766 dbc.currentProject().getUuid(), 1767 resource.getResourceId(), 1768 resource.getStructureId()); 1769 int strVersion = versions.get("structure").intValue(); 1770 int resVersion = versions.get("resource").intValue(); 1771 1772 if (resOp) { 1773 if (resource.getSiblingCount() > 1) { 1774 m_resOp.add(resource.getResourceId()); 1775 } 1776 resVersion++; 1777 } 1778 if (!resOp) { 1779 strVersion++; 1780 } 1781 1782 Connection conn = null; 1783 PreparedStatement stmt = null; 1784 ResultSet res = null; 1785 1786 try { 1787 conn = m_sqlManager.getConnection(dbc); 1788 1789 if (resOp) { 1790 // update the resource version 1791 stmt = m_sqlManager.getPreparedStatement( 1792 conn, 1793 CmsProject.ONLINE_PROJECT_ID, 1794 "C_RESOURCES_UPDATE_RESOURCE_VERSION"); 1795 stmt.setInt(1, resVersion); 1796 stmt.setString(2, resource.getResourceId().toString()); 1797 stmt.executeUpdate(); 1798 m_sqlManager.closeAll(dbc, null, stmt, null); 1799 } 1800 if (!resOp || strState.isNew()) { 1801 // update the structure version 1802 stmt = m_sqlManager.getPreparedStatement( 1803 conn, 1804 CmsProject.ONLINE_PROJECT_ID, 1805 "C_RESOURCES_UPDATE_STRUCTURE_VERSION"); 1806 stmt.setInt(1, strVersion); 1807 stmt.setString(2, resource.getStructureId().toString()); 1808 stmt.executeUpdate(); 1809 m_sqlManager.closeAll(dbc, null, stmt, null); 1810 } 1811 } catch (SQLException e) { 1812 throw new CmsDbSqlException( 1813 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 1814 e); 1815 } finally { 1816 m_sqlManager.closeAll(dbc, conn, stmt, res); 1817 } 1818 } 1819 1820 /** 1821 * @see org.opencms.db.I_CmsVfsDriver#readAliases(org.opencms.db.CmsDbContext, org.opencms.file.CmsProject, org.opencms.db.CmsAliasFilter) 1822 */ 1823 public List<CmsAlias> readAliases(CmsDbContext dbc, CmsProject project, CmsAliasFilter filter) 1824 throws CmsDataAccessException { 1825 1826 Connection conn = null; 1827 PreparedStatement stmt = null; 1828 ResultSet res = null; 1829 try { 1830 conn = m_sqlManager.getConnection(dbc); 1831 CmsPair<String, List<String>> conditionPair = buildAliasConditions(filter); 1832 String conditionString = conditionPair.getFirst(); 1833 List<String> conditionParams = conditionPair.getSecond(); 1834 String sql = "SELECT site_root, path, alias_mode, structure_id FROM CMS_ALIASES WHERE " + conditionString; 1835 stmt = m_sqlManager.getPreparedStatementForSql(conn, sql); 1836 for (int i = 0; i < conditionParams.size(); i++) { 1837 stmt.setString(1 + i, conditionParams.get(i)); 1838 } 1839 res = stmt.executeQuery(); 1840 List<CmsAlias> result = new ArrayList<CmsAlias>(); 1841 while (res.next()) { 1842 CmsAlias alias = internalReadAlias(res); 1843 result.add(alias); 1844 } 1845 return result; 1846 } catch (SQLException e) { 1847 throw new CmsDbSqlException( 1848 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 1849 e); 1850 } finally { 1851 m_sqlManager.closeAll(dbc, conn, stmt, res); 1852 } 1853 1854 } 1855 1856 /** 1857 * @see org.opencms.db.I_CmsVfsDriver#readChildResources(org.opencms.db.CmsDbContext, org.opencms.file.CmsProject, org.opencms.file.CmsResource, boolean, boolean) 1858 */ 1859 public List<CmsResource> readChildResources( 1860 CmsDbContext dbc, 1861 CmsProject currentProject, 1862 CmsResource resource, 1863 boolean getFolders, 1864 boolean getFiles) 1865 throws CmsDataAccessException { 1866 1867 List<CmsResource> result = new ArrayList<CmsResource>(); 1868 CmsUUID projectId = currentProject.getUuid(); 1869 1870 String resourceTypeClause; 1871 if (getFolders && getFiles) { 1872 resourceTypeClause = null; 1873 } else if (getFolders) { 1874 resourceTypeClause = m_sqlManager.readQuery(projectId, "C_RESOURCES_GET_SUBRESOURCES_GET_FOLDERS"); 1875 } else { 1876 resourceTypeClause = m_sqlManager.readQuery(projectId, "C_RESOURCES_GET_SUBRESOURCES_GET_FILES"); 1877 } 1878 StringBuffer query = new StringBuffer(); 1879 query.append(m_sqlManager.readQuery(projectId, "C_RESOURCES_GET_SUBRESOURCES")); 1880 if (resourceTypeClause != null) { 1881 query.append(' '); 1882 query.append(resourceTypeClause); 1883 } 1884 1885 String sizeColumn = m_sqlManager.readQuery("C_RESOURCES_SIZE"); 1886 1887 Connection conn = null; 1888 PreparedStatement stmt = null; 1889 ResultSet res = null; 1890 try { 1891 conn = m_sqlManager.getConnection(dbc); 1892 stmt = m_sqlManager.getPreparedStatementForSql(conn, query.toString()); 1893 stmt.setString(1, resource.getStructureId().toString()); 1894 res = stmt.executeQuery(); 1895 1896 while (res.next()) { 1897 long size = res.getInt(sizeColumn); 1898 if (CmsFolder.isFolderSize(size)) { 1899 result.add(createFolder(res, projectId, false)); 1900 } else { 1901 result.add(createFile(dbc, res, projectId, false)); 1902 } 1903 } 1904 } catch (SQLException e) { 1905 throw new CmsDbSqlException( 1906 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 1907 e); 1908 } finally { 1909 m_sqlManager.closeAll(dbc, conn, stmt, res); 1910 } 1911 1912 // sort result in memory, this is to avoid DB dependencies in the result order 1913 Collections.sort(result, I_CmsResource.COMPARE_ROOT_PATH_IGNORE_CASE_FOLDERS_FIRST); 1914 return result; 1915 } 1916 1917 /** 1918 * @see org.opencms.db.I_CmsVfsDriver#readContent(org.opencms.db.CmsDbContext, CmsUUID, org.opencms.util.CmsUUID) 1919 */ 1920 public byte[] readContent(CmsDbContext dbc, CmsUUID projectId, CmsUUID resourceId) throws CmsDataAccessException { 1921 1922 PreparedStatement stmt = null; 1923 ResultSet res = null; 1924 Connection conn = null; 1925 byte[] byteRes = null; 1926 1927 try { 1928 conn = m_sqlManager.getConnection(dbc); 1929 if (projectId.equals(CmsProject.ONLINE_PROJECT_ID)) { 1930 stmt = m_sqlManager.getPreparedStatement(conn, projectId, "C_ONLINE_FILES_CONTENT"); 1931 } else { 1932 stmt = m_sqlManager.getPreparedStatement(conn, projectId, "C_OFFLINE_FILES_CONTENT"); 1933 } 1934 stmt.setString(1, resourceId.toString()); 1935 res = stmt.executeQuery(); 1936 1937 if (res.next()) { 1938 //query to read Array of bytes for the attribute FILE_CONTENT 1939 byteRes = m_sqlManager.getBytes(res, m_sqlManager.readQuery("C_RESOURCES_FILE_CONTENT")); 1940 while (res.next()) { 1941 // do nothing only move through all rows because of mssql odbc driver 1942 } 1943 } else { 1944 throw new CmsVfsResourceNotFoundException( 1945 Messages.get().container( 1946 Messages.ERR_READ_CONTENT_WITH_RESOURCE_ID_2, 1947 resourceId, 1948 Boolean.valueOf(projectId.equals(CmsProject.ONLINE_PROJECT_ID)))); 1949 } 1950 } catch (SQLException e) { 1951 throw new CmsDbSqlException( 1952 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 1953 e); 1954 } finally { 1955 m_sqlManager.closeAll(dbc, conn, stmt, res); 1956 } 1957 return byteRes; 1958 } 1959 1960 /** 1961 * @see org.opencms.db.I_CmsVfsDriver#readFolder(org.opencms.db.CmsDbContext, CmsUUID, org.opencms.util.CmsUUID) 1962 */ 1963 public CmsFolder readFolder(CmsDbContext dbc, CmsUUID projectId, CmsUUID folderId) throws CmsDataAccessException { 1964 1965 CmsFolder folder = null; 1966 ResultSet res = null; 1967 PreparedStatement stmt = null; 1968 Connection conn = null; 1969 1970 try { 1971 conn = m_sqlManager.getConnection(dbc); 1972 stmt = m_sqlManager.getPreparedStatement(conn, projectId, "C_RESOURCES_READBYID"); 1973 stmt.setString(1, folderId.toString()); 1974 res = stmt.executeQuery(); 1975 1976 if (res.next()) { 1977 folder = createFolder(res, projectId, true); 1978 while (res.next()) { 1979 // do nothing only move through all rows because of mssql odbc driver 1980 } 1981 } else { 1982 throw new CmsVfsResourceNotFoundException( 1983 Messages.get().container(Messages.ERR_READ_FOLDER_WITH_ID_1, folderId)); 1984 } 1985 } catch (SQLException e) { 1986 throw new CmsDbSqlException( 1987 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 1988 e); 1989 } finally { 1990 m_sqlManager.closeAll(dbc, conn, stmt, res); 1991 } 1992 1993 return folder; 1994 } 1995 1996 /** 1997 * @see org.opencms.db.I_CmsVfsDriver#readFolder(org.opencms.db.CmsDbContext, CmsUUID, java.lang.String) 1998 */ 1999 public CmsFolder readFolder(CmsDbContext dbc, CmsUUID projectId, String folderPath) throws CmsDataAccessException { 2000 2001 CmsFolder folder = null; 2002 ResultSet res = null; 2003 PreparedStatement stmt = null; 2004 Connection conn = null; 2005 2006 folderPath = CmsFileUtil.removeTrailingSeparator(folderPath); 2007 try { 2008 conn = m_sqlManager.getConnection(dbc); 2009 stmt = m_sqlManager.getPreparedStatement(conn, projectId, "C_RESOURCES_READ"); 2010 2011 stmt.setString(1, folderPath); 2012 res = stmt.executeQuery(); 2013 2014 if (res.next()) { 2015 folder = createFolder(res, projectId, true); 2016 while (res.next()) { 2017 // do nothing only move through all rows because of mssql odbc driver 2018 } 2019 } else { 2020 throw new CmsVfsResourceNotFoundException( 2021 Messages.get().container(Messages.ERR_READ_FOLDER_1, dbc.removeSiteRoot(folderPath))); 2022 } 2023 } catch (SQLException e) { 2024 throw new CmsDbSqlException( 2025 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 2026 e); 2027 } finally { 2028 m_sqlManager.closeAll(dbc, conn, stmt, res); 2029 } 2030 2031 return folder; 2032 2033 } 2034 2035 public List<CmsFolderSizeEntry> readFolderSizeStats(CmsDbContext dbc, boolean online, CmsFolderSizeOptions options) 2036 throws CmsDataAccessException { 2037 2038 PreparedStatement stmt = null; 2039 List<CmsFolderSizeEntry> result = new ArrayList<>(); 2040 try (Connection conn = m_sqlManager.getConnection(dbc)) { 2041 ResultSet res; 2042 if (options.isTree()) { 2043 String query = m_sqlManager.readQuery("C_FOLDER_SIZE_STATS"); 2044 query = replaceProject(query, online); 2045 stmt = m_sqlManager.getPreparedStatementForSql(conn, query); 2046 stmt.setString(1, escapeDbWildcard(options.getRootPath()) + "%"); 2047 res = stmt.executeQuery(); 2048 } else { 2049 String query = m_sqlManager.readQuery("C_FOLDER_SIZE_STATS_SINGLE"); 2050 query = replaceProject(query, online); 2051 stmt = m_sqlManager.getPreparedStatementForSql(conn, query); 2052 String path = options.getRootPath(); 2053 if (!"/".equals(path)) { 2054 path = CmsFileUtil.removeTrailingSeparator(path); 2055 } 2056 stmt.setString(1, path); 2057 res = stmt.executeQuery(); 2058 } 2059 while (res.next()) { 2060 long size = res.getLong(1); 2061 String path = res.getString(2); 2062 String idStr = res.getString(3); 2063 int type = res.getInt(4); 2064 if (CmsUUID.isValidUUID(idStr)) { 2065 CmsUUID id = new CmsUUID(idStr); 2066 result.add(new CmsFolderSizeEntry(id, path, size, type)); 2067 } 2068 } 2069 return Collections.unmodifiableList(result); 2070 } catch (SQLException e) { 2071 throw new CmsDbSqlException( 2072 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 2073 e); 2074 } 2075 } 2076 2077 /** 2078 * @see org.opencms.db.I_CmsVfsDriver#readHistoryContent(org.opencms.db.CmsDbContext, org.opencms.util.CmsUUID, int) 2079 */ 2080 public byte[] readHistoryContent(CmsDbContext dbc, CmsUUID resourceId, int publishTag) 2081 throws CmsDataAccessException { 2082 2083 Connection conn = null; 2084 PreparedStatement stmt = null; 2085 ResultSet res = null; 2086 byte[] content = null; 2087 2088 try { 2089 conn = m_sqlManager.getConnection(dbc); 2090 stmt = m_sqlManager.getPreparedStatement(conn, "C_HISTORY_READ_CONTENT"); 2091 stmt.setString(1, resourceId.toString()); 2092 stmt.setInt(2, publishTag); 2093 stmt.setInt(3, publishTag); 2094 res = stmt.executeQuery(); 2095 2096 if (res.next()) { 2097 content = m_sqlManager.getBytes(res, m_sqlManager.readQuery("C_RESOURCES_FILE_CONTENT")); 2098 while (res.next()) { 2099 // do nothing only move through all rows because of mssql odbc driver 2100 } 2101 } 2102 } catch (SQLException e) { 2103 throw new CmsDbSqlException( 2104 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 2105 e); 2106 } finally { 2107 m_sqlManager.closeAll(dbc, conn, stmt, res); 2108 } 2109 return content; 2110 } 2111 2112 /** 2113 * @see org.opencms.db.I_CmsVfsDriver#readParentFolder(org.opencms.db.CmsDbContext, CmsUUID, org.opencms.util.CmsUUID) 2114 */ 2115 public CmsFolder readParentFolder(CmsDbContext dbc, CmsUUID projectId, CmsUUID structureId) 2116 throws CmsDataAccessException { 2117 2118 CmsFolder parent = null; 2119 ResultSet res = null; 2120 PreparedStatement stmt = null; 2121 Connection conn = null; 2122 try { 2123 conn = m_sqlManager.getConnection(dbc); 2124 stmt = m_sqlManager.getPreparedStatement(conn, projectId, "C_RESOURCES_READ_PARENT_BY_ID"); 2125 stmt.setString(1, structureId.toString()); 2126 res = stmt.executeQuery(); 2127 2128 if (res.next()) { 2129 parent = new CmsFolder(createResource(res, projectId)); 2130 while (res.next()) { 2131 // do nothing only move through all rows because of mssql odbc driver 2132 } 2133 } 2134 } catch (SQLException e) { 2135 throw new CmsDbSqlException( 2136 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 2137 e); 2138 } finally { 2139 m_sqlManager.closeAll(dbc, conn, stmt, res); 2140 } 2141 return parent; 2142 } 2143 2144 /** 2145 * @see org.opencms.db.I_CmsVfsDriver#readPropertyDefinition(org.opencms.db.CmsDbContext, java.lang.String, CmsUUID) 2146 */ 2147 public CmsPropertyDefinition readPropertyDefinition(CmsDbContext dbc, String name, CmsUUID projectId) 2148 throws CmsDataAccessException { 2149 2150 CmsPropertyDefinition propDef = null; 2151 ResultSet res = null; 2152 PreparedStatement stmt = null; 2153 Connection conn = null; 2154 2155 try { 2156 conn = m_sqlManager.getConnection(dbc); 2157 stmt = m_sqlManager.getPreparedStatement(conn, projectId, "C_PROPERTYDEF_READ"); 2158 stmt.setString(1, name); 2159 res = stmt.executeQuery(); 2160 2161 // if result set exists - return it 2162 if (res.next()) { 2163 propDef = new CmsPropertyDefinition( 2164 new CmsUUID(res.getString(m_sqlManager.readQuery("C_PROPERTYDEF_ID"))), 2165 res.getString(m_sqlManager.readQuery("C_PROPERTYDEF_NAME")), 2166 CmsPropertyDefinition.CmsPropertyType.valueOf( 2167 res.getInt(m_sqlManager.readQuery("C_PROPERTYDEF_TYPE")))); 2168 while (res.next()) { 2169 // do nothing only move through all rows because of mssql odbc driver 2170 } 2171 } else { 2172 throw new CmsDbEntryNotFoundException( 2173 Messages.get().container(Messages.ERR_NO_PROPERTYDEF_WITH_NAME_1, name)); 2174 } 2175 } catch (SQLException e) { 2176 throw new CmsDbSqlException( 2177 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 2178 e); 2179 } finally { 2180 m_sqlManager.closeAll(dbc, conn, stmt, res); 2181 } 2182 2183 return propDef; 2184 } 2185 2186 /** 2187 * @see org.opencms.db.I_CmsVfsDriver#readPropertyDefinitions(org.opencms.db.CmsDbContext, CmsUUID) 2188 */ 2189 public List<CmsPropertyDefinition> readPropertyDefinitions(CmsDbContext dbc, CmsUUID projectId) 2190 throws CmsDataAccessException { 2191 2192 ArrayList<CmsPropertyDefinition> propertyDefinitions = new ArrayList<CmsPropertyDefinition>(); 2193 ResultSet res = null; 2194 PreparedStatement stmt = null; 2195 Connection conn = null; 2196 2197 try { 2198 conn = m_sqlManager.getConnection(dbc); 2199 stmt = m_sqlManager.getPreparedStatement(conn, projectId, "C_PROPERTYDEF_READALL"); 2200 2201 res = stmt.executeQuery(); 2202 while (res.next()) { 2203 propertyDefinitions.add( 2204 new CmsPropertyDefinition( 2205 new CmsUUID(res.getString(m_sqlManager.readQuery("C_PROPERTYDEF_ID"))), 2206 res.getString(m_sqlManager.readQuery("C_PROPERTYDEF_NAME")), 2207 CmsPropertyDefinition.CmsPropertyType.valueOf( 2208 res.getInt(m_sqlManager.readQuery("C_PROPERTYDEF_TYPE"))))); 2209 } 2210 } catch (SQLException e) { 2211 throw new CmsDbSqlException( 2212 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 2213 e); 2214 } finally { 2215 m_sqlManager.closeAll(dbc, conn, stmt, res); 2216 } 2217 return propertyDefinitions; 2218 } 2219 2220 /** 2221 * @see org.opencms.db.I_CmsVfsDriver#readPropertyObject(org.opencms.db.CmsDbContext, java.lang.String, org.opencms.file.CmsProject, org.opencms.file.CmsResource) 2222 */ 2223 public CmsProperty readPropertyObject(CmsDbContext dbc, String key, CmsProject project, CmsResource resource) 2224 throws CmsDataAccessException { 2225 2226 CmsUUID projectId = ((dbc.getProjectId() == null) || dbc.getProjectId().isNullUUID()) 2227 ? project.getUuid() 2228 : dbc.getProjectId(); 2229 2230 ResultSet res = null; 2231 PreparedStatement stmt = null; 2232 Connection conn = null; 2233 String propertyValue = null; 2234 int mappingType = -1; 2235 CmsProperty property = null; 2236 int resultSize = 0; 2237 2238 try { 2239 conn = m_sqlManager.getConnection(dbc); 2240 stmt = m_sqlManager.getPreparedStatement(conn, projectId, "C_PROPERTIES_READ"); 2241 2242 stmt.setString(1, key); 2243 stmt.setString(2, resource.getStructureId().toString()); 2244 stmt.setString(3, resource.getResourceId().toString()); 2245 res = stmt.executeQuery(); 2246 2247 while (res.next()) { 2248 if (resultSize >= 2) { 2249 throw new CmsDbConsistencyException( 2250 Messages.get().container( 2251 Messages.ERR_TOO_MANY_PROPERTIES_3, 2252 key, 2253 resource.getRootPath(), 2254 Integer.valueOf(resultSize))); 2255 } 2256 2257 if (property == null) { 2258 property = new CmsProperty(); 2259 property.setName(key); 2260 } 2261 2262 propertyValue = res.getString(1); 2263 mappingType = res.getInt(2); 2264 2265 if (mappingType == CmsProperty.STRUCTURE_RECORD_MAPPING) { 2266 property.setStructureValue(propertyValue); 2267 } else if (mappingType == CmsProperty.RESOURCE_RECORD_MAPPING) { 2268 property.setResourceValue(propertyValue); 2269 } else { 2270 throw new CmsDbConsistencyException( 2271 Messages.get().container( 2272 Messages.ERR_UNKNOWN_PROPERTY_VALUE_MAPPING_3, 2273 resource.getRootPath(), 2274 Integer.valueOf(mappingType), 2275 key)); 2276 } 2277 2278 resultSize++; 2279 } 2280 } catch (SQLException e) { 2281 throw new CmsDbSqlException( 2282 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 2283 e); 2284 } finally { 2285 m_sqlManager.closeAll(dbc, conn, stmt, res); 2286 } 2287 2288 return (property != null) ? property : CmsProperty.getNullProperty(); 2289 } 2290 2291 /** 2292 * @see org.opencms.db.I_CmsVfsDriver#readPropertyObjects(org.opencms.db.CmsDbContext, org.opencms.file.CmsProject, org.opencms.file.CmsResource) 2293 */ 2294 public List<CmsProperty> readPropertyObjects(CmsDbContext dbc, CmsProject project, CmsResource resource) 2295 throws CmsDataAccessException { 2296 2297 CmsUUID projectId = ((dbc.getProjectId() == null) || dbc.getProjectId().isNullUUID()) 2298 ? project.getUuid() 2299 : dbc.getProjectId(); 2300 2301 ResultSet res = null; 2302 PreparedStatement stmt = null; 2303 Connection conn = null; 2304 int mappingType = -1; 2305 Map<String, CmsProperty> propertyMap = new HashMap<String, CmsProperty>(); 2306 2307 String propertyKey; 2308 String propertyValue; 2309 CmsProperty property; 2310 2311 try { 2312 conn = m_sqlManager.getConnection(dbc); 2313 stmt = m_sqlManager.getPreparedStatement(conn, projectId, "C_PROPERTIES_READALL"); 2314 stmt.setString(1, resource.getStructureId().toString()); 2315 stmt.setString(2, resource.getResourceId().toString()); 2316 res = stmt.executeQuery(); 2317 2318 while (res.next()) { 2319 propertyKey = null; 2320 propertyValue = null; 2321 mappingType = -1; 2322 2323 propertyKey = res.getString(1); 2324 propertyValue = res.getString(2); 2325 mappingType = res.getInt(3); 2326 2327 property = propertyMap.get(propertyKey); 2328 if (property == null) { 2329 // there doesn't exist a property object for this key yet 2330 property = new CmsProperty(); 2331 property.setName(propertyKey); 2332 propertyMap.put(propertyKey, property); 2333 } 2334 2335 if (mappingType == CmsProperty.STRUCTURE_RECORD_MAPPING) { 2336 // this property value is mapped to a structure record 2337 property.setStructureValue(propertyValue); 2338 } else if (mappingType == CmsProperty.RESOURCE_RECORD_MAPPING) { 2339 // this property value is mapped to a resource record 2340 property.setResourceValue(propertyValue); 2341 } else { 2342 throw new CmsDbConsistencyException( 2343 Messages.get().container( 2344 Messages.ERR_UNKNOWN_PROPERTY_VALUE_MAPPING_3, 2345 resource.getRootPath(), 2346 Integer.valueOf(mappingType), 2347 propertyKey)); 2348 } 2349 property.setOrigin(resource.getRootPath()); 2350 } 2351 } catch (SQLException e) { 2352 throw new CmsDbSqlException( 2353 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 2354 e); 2355 } finally { 2356 m_sqlManager.closeAll(dbc, conn, stmt, res); 2357 } 2358 2359 return new ArrayList<CmsProperty>(propertyMap.values()); 2360 } 2361 2362 /** 2363 * @see org.opencms.db.I_CmsVfsDriver#readRelations(org.opencms.db.CmsDbContext, CmsUUID, CmsResource, org.opencms.relations.CmsRelationFilter) 2364 */ 2365 public List<CmsRelation> readRelations( 2366 CmsDbContext dbc, 2367 CmsUUID projectId, 2368 CmsResource resource, 2369 CmsRelationFilter filter) 2370 throws CmsDataAccessException { 2371 2372 Set<CmsRelation> relations = new HashSet<CmsRelation>(); 2373 2374 Connection conn = null; 2375 PreparedStatement stmt = null; 2376 ResultSet res = null; 2377 2378 try { 2379 conn = m_sqlManager.getConnection(dbc); 2380 if (filter.isSource()) { 2381 List<Object> params = new ArrayList<Object>(7); 2382 2383 StringBuffer queryBuf = new StringBuffer(256); 2384 queryBuf.append(m_sqlManager.readQuery(projectId, "C_READ_RELATIONS")); 2385 queryBuf.append( 2386 prepareRelationConditions(RelationConditionMode.read, projectId, filter, resource, params, true)); 2387 if (LOG.isDebugEnabled()) { 2388 LOG.debug(queryBuf.toString()); 2389 } 2390 2391 stmt = m_sqlManager.getPreparedStatementForSql(conn, queryBuf.toString()); 2392 for (int i = 0; i < params.size(); i++) { 2393 if (params.get(i) instanceof Integer) { 2394 stmt.setInt(i + 1, ((Integer)params.get(i)).intValue()); 2395 } else { 2396 stmt.setString(i + 1, (String)params.get(i)); 2397 } 2398 } 2399 res = stmt.executeQuery(); 2400 while (res.next()) { 2401 relations.add(internalReadRelation(res)); 2402 } 2403 m_sqlManager.closeAll(dbc, null, stmt, res); 2404 } 2405 2406 if (filter.isTarget()) { 2407 List<Object> params = new ArrayList<Object>(7); 2408 2409 StringBuffer queryBuf = new StringBuffer(256); 2410 queryBuf.append(m_sqlManager.readQuery(projectId, "C_READ_RELATIONS")); 2411 queryBuf.append( 2412 prepareRelationConditions(RelationConditionMode.read, projectId, filter, resource, params, false)); 2413 if (LOG.isDebugEnabled()) { 2414 LOG.debug(queryBuf.toString()); 2415 } 2416 2417 stmt = m_sqlManager.getPreparedStatementForSql(conn, queryBuf.toString()); 2418 for (int i = 0; i < params.size(); i++) { 2419 if (params.get(i) instanceof Integer) { 2420 stmt.setInt(i + 1, ((Integer)params.get(i)).intValue()); 2421 } else { 2422 stmt.setString(i + 1, (String)params.get(i)); 2423 } 2424 } 2425 res = stmt.executeQuery(); 2426 while (res.next()) { 2427 relations.add(internalReadRelation(res)); 2428 } 2429 m_sqlManager.closeAll(dbc, null, stmt, res); 2430 } 2431 } catch (SQLException e) { 2432 throw new CmsDbSqlException( 2433 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 2434 e); 2435 } finally { 2436 m_sqlManager.closeAll(dbc, conn, stmt, res); 2437 } 2438 2439 List<CmsRelation> result = new ArrayList<CmsRelation>(relations); 2440 Collections.sort(result, CmsRelation.COMPARATOR); 2441 return result; 2442 } 2443 2444 /** 2445 * @see org.opencms.db.I_CmsVfsDriver#readResource(org.opencms.db.CmsDbContext, CmsUUID, org.opencms.util.CmsUUID, boolean) 2446 */ 2447 public CmsResource readResource(CmsDbContext dbc, CmsUUID projectId, CmsUUID structureId, boolean includeDeleted) 2448 throws CmsDataAccessException { 2449 2450 CmsResource resource = null; 2451 ResultSet res = null; 2452 PreparedStatement stmt = null; 2453 Connection conn = null; 2454 2455 try { 2456 conn = m_sqlManager.getConnection(dbc); 2457 stmt = m_sqlManager.getPreparedStatement(conn, projectId, "C_RESOURCES_READBYID"); 2458 2459 stmt.setString(1, structureId.toString()); 2460 res = stmt.executeQuery(); 2461 2462 if (res.next()) { 2463 resource = createResource(res, projectId); 2464 while (res.next()) { 2465 // do nothing only move through all rows because of mssql odbc driver 2466 } 2467 } else { 2468 throw new CmsVfsResourceNotFoundException( 2469 Messages.get().container(Messages.ERR_READ_RESOURCE_WITH_ID_1, structureId)); 2470 } 2471 } catch (SQLException e) { 2472 throw new CmsDbSqlException( 2473 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 2474 e); 2475 } finally { 2476 m_sqlManager.closeAll(dbc, conn, stmt, res); 2477 } 2478 2479 // check if this resource is marked as deleted and if we are allowed to return a deleted resource 2480 if ((resource != null) && resource.getState().isDeleted() && !includeDeleted) { 2481 throw new CmsVfsResourceNotFoundException( 2482 Messages.get().container( 2483 Messages.ERR_READ_DELETED_RESOURCE_1, 2484 dbc.removeSiteRoot(resource.getRootPath()))); 2485 } 2486 2487 return resource; 2488 } 2489 2490 /** 2491 * @see org.opencms.db.I_CmsVfsDriver#readResource(org.opencms.db.CmsDbContext, CmsUUID, java.lang.String, boolean) 2492 */ 2493 public CmsResource readResource(CmsDbContext dbc, CmsUUID projectId, String path, boolean includeDeleted) 2494 throws CmsDataAccessException { 2495 2496 CmsResource resource = null; 2497 ResultSet res = null; 2498 PreparedStatement stmt = null; 2499 Connection conn = null; 2500 2501 // must remove trailing slash 2502 int len = path.length(); 2503 path = CmsFileUtil.removeTrailingSeparator(path); 2504 boolean endsWithSlash = (len != path.length()); 2505 2506 try { 2507 conn = m_sqlManager.getConnection(dbc); 2508 stmt = m_sqlManager.getPreparedStatement(conn, projectId, "C_RESOURCES_READ"); 2509 2510 stmt.setString(1, path); 2511 res = stmt.executeQuery(); 2512 2513 if (res.next()) { 2514 resource = createResource(res, projectId); 2515 2516 // check if the resource is a file, it is not allowed to end with a "/" then 2517 if (endsWithSlash && resource.isFile()) { 2518 throw new CmsVfsResourceNotFoundException( 2519 Messages.get().container(Messages.ERR_READ_RESOURCE_1, dbc.removeSiteRoot(path + "/"))); 2520 } 2521 2522 while (res.next()) { 2523 // do nothing only move through all rows because of mssql odbc driver 2524 } 2525 } else { 2526 throw new CmsVfsResourceNotFoundException( 2527 Messages.get().container(Messages.ERR_READ_RESOURCE_1, dbc.removeSiteRoot(path))); 2528 } 2529 } catch (SQLException e) { 2530 throw new CmsDbSqlException( 2531 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 2532 e); 2533 } finally { 2534 m_sqlManager.closeAll(dbc, conn, stmt, res); 2535 } 2536 2537 // check if this resource is marked as deleted and if we are allowed to return a deleted resource 2538 if ((resource != null) && resource.getState().isDeleted() && !includeDeleted) { 2539 throw new CmsVfsResourceNotFoundException( 2540 Messages.get().container( 2541 Messages.ERR_READ_DELETED_RESOURCE_1, 2542 dbc.removeSiteRoot(resource.getRootPath()))); 2543 } 2544 2545 return resource; 2546 } 2547 2548 /** 2549 * @see org.opencms.db.I_CmsVfsDriver#readResources(org.opencms.db.CmsDbContext, CmsUUID, CmsResourceState, int) 2550 */ 2551 public List<CmsResource> readResources(CmsDbContext dbc, CmsUUID projectId, CmsResourceState state, int mode) 2552 throws CmsDataAccessException { 2553 2554 List<CmsResource> result = new ArrayList<CmsResource>(); 2555 2556 ResultSet res = null; 2557 PreparedStatement stmt = null; 2558 Connection conn = null; 2559 2560 try { 2561 conn = m_sqlManager.getConnection(dbc); 2562 if (mode == CmsDriverManager.READMODE_MATCHSTATE) { 2563 stmt = m_sqlManager.getPreparedStatement( 2564 conn, 2565 projectId, 2566 "C_RESOURCES_GET_RESOURCE_IN_PROJECT_WITH_STATE"); 2567 stmt.setString(1, projectId.toString()); 2568 stmt.setInt(2, state.getState()); 2569 stmt.setInt(3, state.getState()); 2570 stmt.setInt(4, state.getState()); 2571 stmt.setInt(5, state.getState()); 2572 } else if (mode == CmsDriverManager.READMODE_UNMATCHSTATE) { 2573 stmt = m_sqlManager.getPreparedStatement( 2574 conn, 2575 projectId, 2576 "C_RESOURCES_GET_RESOURCE_IN_PROJECT_WITHOUT_STATE"); 2577 stmt.setString(1, projectId.toString()); 2578 stmt.setInt(2, state.getState()); 2579 stmt.setInt(3, state.getState()); 2580 } else { 2581 stmt = m_sqlManager.getPreparedStatement( 2582 conn, 2583 projectId, 2584 "C_RESOURCES_GET_RESOURCE_IN_PROJECT_IGNORE_STATE"); 2585 stmt.setString(1, projectId.toString()); 2586 } 2587 2588 res = stmt.executeQuery(); 2589 while (res.next()) { 2590 CmsResource resource = createResource(res, projectId); 2591 result.add(resource); 2592 } 2593 } catch (SQLException e) { 2594 throw new CmsDbSqlException( 2595 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 2596 e); 2597 } finally { 2598 m_sqlManager.closeAll(dbc, conn, stmt, res); 2599 } 2600 2601 return result; 2602 } 2603 2604 /** 2605 * @see org.opencms.db.I_CmsVfsDriver#readResourcesForPrincipalACE(org.opencms.db.CmsDbContext, org.opencms.file.CmsProject, org.opencms.util.CmsUUID) 2606 */ 2607 public List<CmsResource> readResourcesForPrincipalACE(CmsDbContext dbc, CmsProject project, CmsUUID principalId) 2608 throws CmsDataAccessException { 2609 2610 PreparedStatement stmt = null; 2611 Connection conn = null; 2612 ResultSet res = null; 2613 CmsResource currentResource = null; 2614 List<CmsResource> resources = new ArrayList<CmsResource>(); 2615 2616 try { 2617 conn = m_sqlManager.getConnection(dbc); 2618 stmt = m_sqlManager.getPreparedStatement(conn, project, "C_SELECT_RESOURCES_FOR_PRINCIPAL_ACE"); 2619 2620 stmt.setString(1, principalId.toString()); 2621 res = stmt.executeQuery(); 2622 2623 while (res.next()) { 2624 currentResource = createFile(dbc, res, project.getUuid(), false); 2625 resources.add(currentResource); 2626 } 2627 } catch (SQLException e) { 2628 throw new CmsDbSqlException( 2629 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 2630 e); 2631 } finally { 2632 m_sqlManager.closeAll(dbc, conn, stmt, res); 2633 } 2634 return resources; 2635 } 2636 2637 /** 2638 * @see org.opencms.db.I_CmsVfsDriver#readResourcesForPrincipalAttr(org.opencms.db.CmsDbContext, org.opencms.file.CmsProject, org.opencms.util.CmsUUID) 2639 */ 2640 public List<CmsResource> readResourcesForPrincipalAttr(CmsDbContext dbc, CmsProject project, CmsUUID principalId) 2641 throws CmsDataAccessException { 2642 2643 PreparedStatement stmt = null; 2644 Connection conn = null; 2645 ResultSet res = null; 2646 CmsResource currentResource = null; 2647 List<CmsResource> resources = new ArrayList<CmsResource>(); 2648 2649 try { 2650 conn = m_sqlManager.getConnection(dbc); 2651 stmt = m_sqlManager.getPreparedStatement(conn, project, "C_SELECT_RESOURCES_FOR_PRINCIPAL_ATTR"); 2652 2653 stmt.setString(1, principalId.toString()); 2654 stmt.setString(2, principalId.toString()); 2655 res = stmt.executeQuery(); 2656 2657 while (res.next()) { 2658 currentResource = createFile(dbc, res, project.getUuid(), false); 2659 resources.add(currentResource); 2660 } 2661 } catch (SQLException e) { 2662 throw new CmsDbSqlException( 2663 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 2664 e); 2665 } finally { 2666 m_sqlManager.closeAll(dbc, conn, stmt, res); 2667 } 2668 return resources; 2669 } 2670 2671 /** 2672 * @see org.opencms.db.I_CmsVfsDriver#readResourcesWithProperty(org.opencms.db.CmsDbContext, CmsUUID, org.opencms.util.CmsUUID, String, String) 2673 */ 2674 public List<CmsResource> readResourcesWithProperty( 2675 CmsDbContext dbc, 2676 CmsUUID projectId, 2677 CmsUUID propertyDef, 2678 String path, 2679 String value) 2680 throws CmsDataAccessException { 2681 2682 List<CmsResource> resources = new ArrayList<CmsResource>(); 2683 ResultSet res = null; 2684 PreparedStatement stmt = null; 2685 Connection conn = null; 2686 2687 try { 2688 conn = m_sqlManager.getConnection(dbc); 2689 if (value == null) { 2690 stmt = m_sqlManager.getPreparedStatement(conn, projectId, "C_RESOURCES_GET_RESOURCE_WITH_PROPERTYDEF"); 2691 stmt.setString(1, propertyDef.toString()); 2692 stmt.setString(2, path + "%"); 2693 stmt.setString(3, propertyDef.toString()); 2694 stmt.setString(4, path + "%"); 2695 } else { 2696 stmt = m_sqlManager.getPreparedStatement( 2697 conn, 2698 projectId, 2699 "C_RESOURCES_GET_RESOURCE_WITH_PROPERTYDEF_VALUE"); 2700 stmt.setString(1, propertyDef.toString()); 2701 stmt.setString(2, path + "%"); 2702 stmt.setString(3, "%" + value + "%"); 2703 stmt.setString(4, propertyDef.toString()); 2704 stmt.setString(5, path + "%"); 2705 stmt.setString(6, "%" + value + "%"); 2706 } 2707 res = stmt.executeQuery(); 2708 2709 while (res.next()) { 2710 CmsResource resource = createResource(res, projectId); 2711 resources.add(resource); 2712 } 2713 } catch (SQLException e) { 2714 throw new CmsDbSqlException( 2715 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 2716 e); 2717 } finally { 2718 m_sqlManager.closeAll(dbc, conn, stmt, res); 2719 } 2720 2721 return resources; 2722 } 2723 2724 /** 2725 * @see org.opencms.db.I_CmsVfsDriver#readResourceTree(org.opencms.db.CmsDbContext, CmsUUID, java.lang.String, int, CmsResourceState, long, long, long, long, long, long, int) 2726 */ 2727 public List<CmsResource> readResourceTree( 2728 CmsDbContext dbc, 2729 CmsUUID projectId, 2730 String parentPath, 2731 int type, 2732 CmsResourceState state, 2733 long lastModifiedAfter, 2734 long lastModifiedBefore, 2735 long releasedAfter, 2736 long releasedBefore, 2737 long expiredAfter, 2738 long expiredBefore, 2739 int mode) 2740 throws CmsDataAccessException { 2741 2742 List<CmsResource> result = new ArrayList<CmsResource>(); 2743 2744 StringBuffer conditions = new StringBuffer(); 2745 List<Object> params = new ArrayList<Object>(5); 2746 2747 // prepare the selection criteria 2748 prepareProjectCondition(projectId, mode, conditions, params); 2749 prepareResourceCondition(projectId, mode, conditions); 2750 prepareTypeCondition(projectId, type, mode, conditions, params); 2751 prepareTimeRangeCondition(projectId, lastModifiedAfter, lastModifiedBefore, conditions, params); 2752 prepareReleasedTimeRangeCondition(projectId, releasedAfter, releasedBefore, conditions, params); 2753 prepareExpiredTimeRangeCondition(projectId, expiredAfter, expiredBefore, conditions, params); 2754 preparePathCondition(projectId, parentPath, mode, conditions, params); 2755 prepareStateCondition(projectId, state, mode, conditions, params); 2756 2757 // now read matching resources within the subtree 2758 ResultSet res = null; 2759 PreparedStatement stmt = null; 2760 Connection conn = null; 2761 2762 try { 2763 conn = m_sqlManager.getConnection(dbc); 2764 StringBuffer queryBuf = new StringBuffer(256); 2765 queryBuf.append(m_sqlManager.readQuery(projectId, "C_RESOURCES_READ_TREE")); 2766 queryBuf.append(conditions); 2767 queryBuf.append(" "); 2768 queryBuf.append(m_sqlManager.readQuery(projectId, "C_RESOURCES_ORDER_BY_PATH")); 2769 stmt = m_sqlManager.getPreparedStatementForSql(conn, queryBuf.toString()); 2770 2771 for (int i = 0; i < params.size(); i++) { 2772 if (params.get(i) instanceof Integer) { 2773 stmt.setInt(i + 1, ((Integer)params.get(i)).intValue()); 2774 } else if (params.get(i) instanceof Long) { 2775 stmt.setLong(i + 1, ((Long)params.get(i)).longValue()); 2776 } else { 2777 stmt.setString(i + 1, (String)params.get(i)); 2778 } 2779 } 2780 2781 res = stmt.executeQuery(); 2782 while (res.next()) { 2783 CmsResource resource = createResource(res, projectId); 2784 result.add(resource); 2785 } 2786 2787 } catch (SQLException e) { 2788 throw new CmsDbSqlException( 2789 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 2790 e); 2791 } finally { 2792 m_sqlManager.closeAll(dbc, conn, stmt, res); 2793 } 2794 2795 return result; 2796 } 2797 2798 /** 2799 * @see org.opencms.db.I_CmsVfsDriver#readRewriteAliases(org.opencms.db.CmsDbContext, org.opencms.db.CmsRewriteAliasFilter) 2800 */ 2801 public List<CmsRewriteAlias> readRewriteAliases(CmsDbContext dbc, CmsRewriteAliasFilter filter) 2802 throws CmsDataAccessException { 2803 2804 Connection conn = null; 2805 PreparedStatement stmt = null; 2806 ResultSet res = null; 2807 List<CmsRewriteAlias> result = new ArrayList<CmsRewriteAlias>(); 2808 try { 2809 conn = m_sqlManager.getConnection(dbc); 2810 CmsPair<String, List<Object>> conditionAndParams = prepareRewriteAliasConditions(filter); 2811 String condition = conditionAndParams.getFirst(); 2812 List<Object> params = conditionAndParams.getSecond(); 2813 String query = m_sqlManager.readQuery("C_REWRITE_ALIAS_READ") + condition; 2814 stmt = m_sqlManager.getPreparedStatementForSql(conn, query); 2815 CmsDbUtil.fillParameters(stmt, params); 2816 res = stmt.executeQuery(); 2817 while (res.next()) { 2818 int col = 1; 2819 String id = res.getString(col++); 2820 String siteRoot = res.getString(col++); 2821 String patternString = res.getString(col++); 2822 String replacementString = res.getString(col++); 2823 int mode = res.getInt(col++); 2824 CmsRewriteAlias alias = new CmsRewriteAlias( 2825 new CmsUUID(id), 2826 siteRoot, 2827 patternString, 2828 replacementString, 2829 CmsAliasMode.fromInt(mode)); 2830 result.add(alias); 2831 } 2832 return result; 2833 } catch (SQLException e) { 2834 throw wrapException(stmt, e); 2835 } finally { 2836 m_sqlManager.closeAll(dbc, conn, stmt, res); 2837 } 2838 2839 } 2840 2841 /** 2842 * @see org.opencms.db.I_CmsVfsDriver#readSiblings(org.opencms.db.CmsDbContext, CmsUUID, org.opencms.file.CmsResource, boolean) 2843 */ 2844 public List<CmsResource> readSiblings( 2845 CmsDbContext dbc, 2846 CmsUUID projectId, 2847 CmsResource resource, 2848 boolean includeDeleted) 2849 throws CmsDataAccessException { 2850 2851 PreparedStatement stmt = null; 2852 Connection conn = null; 2853 ResultSet res = null; 2854 CmsResource currentResource = null; 2855 List<CmsResource> vfsLinks = new ArrayList<CmsResource>(); 2856 2857 try { 2858 conn = m_sqlManager.getConnection(dbc); 2859 2860 if (includeDeleted) { 2861 stmt = m_sqlManager.getPreparedStatement(conn, projectId, "C_SELECT_VFS_SIBLINGS"); 2862 } else { 2863 stmt = m_sqlManager.getPreparedStatement(conn, projectId, "C_SELECT_NONDELETED_VFS_SIBLINGS"); 2864 } 2865 2866 stmt.setString(1, resource.getResourceId().toString()); 2867 res = stmt.executeQuery(); 2868 2869 while (res.next()) { 2870 currentResource = createFile(dbc, res, projectId, false); 2871 vfsLinks.add(currentResource); 2872 } 2873 } catch (SQLException e) { 2874 throw new CmsDbSqlException( 2875 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 2876 e); 2877 } finally { 2878 m_sqlManager.closeAll(dbc, conn, stmt, res); 2879 } 2880 2881 return vfsLinks; 2882 } 2883 2884 /** 2885 * Reads the URL name mapping entries which match a given filter.<p> 2886 * 2887 * @param dbc the database context 2888 * @param online if true, reads from the online mapping, else from the offline mapping 2889 * @param filter the filter which the entries to be read should match 2890 * 2891 * @return the mapping entries which match the given filter 2892 * 2893 * @throws CmsDataAccessException if something goes wrong 2894 */ 2895 public List<CmsUrlNameMappingEntry> readUrlNameMappingEntries( 2896 CmsDbContext dbc, 2897 boolean online, 2898 CmsUrlNameMappingFilter filter) 2899 throws CmsDataAccessException { 2900 2901 Connection conn = null; 2902 ResultSet resultSet = null; 2903 PreparedStatement stmt = null; 2904 List<CmsUrlNameMappingEntry> result = new ArrayList<CmsUrlNameMappingEntry>(); 2905 try { 2906 conn = m_sqlManager.getConnection(dbc); 2907 String query = m_sqlManager.readQuery("C_READ_URLNAME_MAPPINGS"); 2908 query = replaceProject(query, online); 2909 stmt = getPreparedStatementForFilter(conn, query, filter); 2910 resultSet = stmt.executeQuery(); 2911 while (resultSet.next()) { 2912 CmsUrlNameMappingEntry entry = internalCreateUrlNameMappingEntry(resultSet); 2913 result.add(entry); 2914 } 2915 return result; 2916 } catch (SQLException e) { 2917 throw wrapException(stmt, e); 2918 } finally { 2919 m_sqlManager.closeAll(dbc, conn, stmt, resultSet); 2920 } 2921 } 2922 2923 /** 2924 * @see org.opencms.db.I_CmsVfsDriver#readVersions(org.opencms.db.CmsDbContext, org.opencms.util.CmsUUID, org.opencms.util.CmsUUID, org.opencms.util.CmsUUID) 2925 */ 2926 public Map<String, Integer> readVersions( 2927 CmsDbContext dbc, 2928 CmsUUID projectId, 2929 CmsUUID resourceId, 2930 CmsUUID structureId) 2931 throws CmsDataAccessException { 2932 2933 int structureVersion = -1; 2934 int resourceVersion = -1; 2935 2936 Connection conn = null; 2937 PreparedStatement stmt = null; 2938 ResultSet res = null; 2939 2940 try { 2941 conn = m_sqlManager.getConnection(dbc); 2942 2943 // read the offline version numbers, first for the resource entry 2944 stmt = m_sqlManager.getPreparedStatement(conn, projectId, "C_RESOURCES_READ_VERSION_RES"); 2945 stmt.setString(1, resourceId.toString()); 2946 res = stmt.executeQuery(); 2947 if (res.next()) { 2948 resourceVersion = res.getInt(m_sqlManager.readQuery("C_RESOURCES_VERSION")); 2949 while (res.next()) { 2950 // do nothing only move through all rows because of mssql odbc driver 2951 } 2952 } 2953 m_sqlManager.closeAll(dbc, null, stmt, res); 2954 // then for the structure entry 2955 stmt = m_sqlManager.getPreparedStatement(conn, projectId, "C_RESOURCES_READ_VERSION_STR"); 2956 stmt.setString(1, structureId.toString()); 2957 res = stmt.executeQuery(); 2958 if (res.next()) { 2959 structureVersion = res.getInt(m_sqlManager.readQuery("C_RESOURCES_STRUCTURE_VERSION")); 2960 while (res.next()) { 2961 // do nothing only move through all rows because of mssql odbc driver 2962 } 2963 } 2964 } catch (SQLException e) { 2965 throw new CmsDbSqlException( 2966 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 2967 e); 2968 } finally { 2969 m_sqlManager.closeAll(dbc, conn, stmt, res); 2970 } 2971 Map<String, Integer> result = new HashMap<String, Integer>(); 2972 result.put("structure", Integer.valueOf(structureVersion)); 2973 result.put(I_CmsEventListener.KEY_RESOURCE, Integer.valueOf(resourceVersion)); 2974 return result; 2975 } 2976 2977 /** 2978 * @see org.opencms.db.I_CmsVfsDriver#removeFile(org.opencms.db.CmsDbContext, CmsUUID, org.opencms.file.CmsResource) 2979 */ 2980 public void removeFile(CmsDbContext dbc, CmsUUID projectId, CmsResource resource) throws CmsDataAccessException { 2981 2982 PreparedStatement stmt = null; 2983 Connection conn = null; 2984 int siblingCount = 0; 2985 2986 try { 2987 conn = m_sqlManager.getConnection(dbc); 2988 2989 // delete the structure record 2990 stmt = m_sqlManager.getPreparedStatement(conn, projectId, "C_STRUCTURE_DELETE_BY_STRUCTUREID"); 2991 stmt.setString(1, resource.getStructureId().toString()); 2992 stmt.executeUpdate(); 2993 2994 m_sqlManager.closeAll(dbc, conn, stmt, null); 2995 2996 // count the references to the resource 2997 siblingCount = countSiblings(dbc, projectId, resource.getResourceId()); 2998 2999 conn = m_sqlManager.getConnection(dbc); 3000 if (siblingCount > 0) { 3001 // update the link Count 3002 stmt = m_sqlManager.getPreparedStatement(conn, projectId, "C_RESOURCES_UPDATE_SIBLING_COUNT"); 3003 stmt.setInt(1, siblingCount); 3004 stmt.setString(2, resource.getResourceId().toString()); 3005 stmt.executeUpdate(); 3006 3007 m_sqlManager.closeAll(dbc, null, stmt, null); 3008 3009 // update the resource flags 3010 stmt = m_sqlManager.getPreparedStatement(conn, projectId, "C_RESOURCES_UPDATE_FLAGS"); 3011 stmt.setInt(1, resource.getFlags()); 3012 stmt.setString(2, resource.getResourceId().toString()); 3013 stmt.executeUpdate(); 3014 3015 } else { 3016 // if not referenced any longer, also delete the resource and the content record 3017 stmt = m_sqlManager.getPreparedStatement(conn, projectId, "C_RESOURCES_DELETE_BY_RESOURCEID"); 3018 stmt.setString(1, resource.getResourceId().toString()); 3019 stmt.executeUpdate(); 3020 3021 m_sqlManager.closeAll(dbc, null, stmt, null); 3022 3023 boolean dbcHasProjectId = (dbc.getProjectId() != null) && !dbc.getProjectId().isNullUUID(); 3024 3025 // if online we have to keep historical content 3026 if (projectId.equals(CmsProject.ONLINE_PROJECT_ID)) { 3027 // put the online content in the history 3028 stmt = m_sqlManager.getPreparedStatement(conn, "C_ONLINE_CONTENTS_HISTORY"); 3029 stmt.setString(1, resource.getResourceId().toString()); 3030 stmt.executeUpdate(); 3031 } else if (dbcHasProjectId) { 3032 // remove current online version 3033 stmt = m_sqlManager.getPreparedStatement(conn, "C_ONLINE_CONTENTS_DELETE"); 3034 stmt.setString(1, resource.getResourceId().toString()); 3035 stmt.executeUpdate(); 3036 } else { 3037 // delete content records with this resource id 3038 stmt = m_sqlManager.getPreparedStatement(conn, projectId, "C_OFFLINE_FILE_CONTENT_DELETE"); 3039 stmt.setString(1, resource.getResourceId().toString()); 3040 stmt.executeUpdate(); 3041 } 3042 } 3043 } catch (SQLException e) { 3044 throw new CmsDbSqlException( 3045 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 3046 e); 3047 } finally { 3048 m_sqlManager.closeAll(dbc, conn, stmt, null); 3049 } 3050 } 3051 3052 /** 3053 * @see org.opencms.db.I_CmsVfsDriver#removeFolder(org.opencms.db.CmsDbContext, org.opencms.file.CmsProject, org.opencms.file.CmsResource) 3054 */ 3055 public void removeFolder(CmsDbContext dbc, CmsProject currentProject, CmsResource resource) 3056 throws CmsDataAccessException { 3057 3058 if ((dbc.getRequestContext() != null) 3059 && (dbc.getRequestContext().getAttribute(REQ_ATTR_CHECK_PERMISSIONS) != null)) { 3060 // only check write permissions 3061 checkWritePermissionsInFolder(dbc, resource); 3062 return; 3063 } 3064 3065 // check if the folder has any resources in it 3066 Iterator<CmsResource> childResources = readChildResources(dbc, currentProject, resource, true, true).iterator(); 3067 3068 CmsUUID projectId = CmsProject.ONLINE_PROJECT_ID; 3069 if (currentProject.isOnlineProject()) { 3070 projectId = CmsUUID.getOpenCmsUUID(); // HACK: to get an offline project id 3071 } 3072 3073 // collect the names of the resources inside the folder, excluding the moved resources 3074 I_CmsVfsDriver vfsDriver = m_driverManager.getVfsDriver(dbc); 3075 StringBuffer errorResNames = new StringBuffer(128); 3076 while (childResources.hasNext()) { 3077 CmsResource errorRes = childResources.next(); 3078 // if deleting offline, or not moved, or just renamed inside the deleted folder 3079 // so, it may remain some orphan online entries for moved resources 3080 // which will be fixed during the publishing of the moved resources 3081 boolean error = !currentProject.isOnlineProject(); 3082 if (!error) { 3083 try { 3084 String originalPath = vfsDriver.readResource( 3085 dbc, 3086 projectId, 3087 errorRes.getRootPath(), 3088 true).getRootPath(); 3089 error = originalPath.equals(errorRes.getRootPath()) 3090 || originalPath.startsWith(resource.getRootPath()); 3091 } catch (CmsVfsResourceNotFoundException e) { 3092 // ignore 3093 } 3094 } 3095 if (error) { 3096 if (errorResNames.length() != 0) { 3097 errorResNames.append(", "); 3098 } 3099 errorResNames.append("[" + dbc.removeSiteRoot(errorRes.getRootPath()) + "]"); 3100 } 3101 } 3102 3103 // the current implementation only deletes empty folders 3104 if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(errorResNames.toString())) { 3105 3106 throw new CmsVfsException( 3107 Messages.get().container( 3108 Messages.ERR_DELETE_NONEMTY_FOLDER_2, 3109 dbc.removeSiteRoot(resource.getRootPath()), 3110 errorResNames.toString())); 3111 } 3112 internalRemoveFolder(dbc, currentProject, resource); 3113 3114 // remove project resources 3115 String deletedResourceRootPath = resource.getRootPath(); 3116 if (dbc.getRequestContext() != null) { 3117 dbc.getRequestContext().setAttribute(CmsProjectDriver.DBC_ATTR_READ_PROJECT_FOR_RESOURCE, Boolean.TRUE); 3118 I_CmsProjectDriver projectDriver = m_driverManager.getProjectDriver(dbc); 3119 Iterator<CmsProject> itProjects = projectDriver.readProjects(dbc, deletedResourceRootPath).iterator(); 3120 while (itProjects.hasNext()) { 3121 CmsProject project = itProjects.next(); 3122 projectDriver.deleteProjectResource(dbc, project.getUuid(), deletedResourceRootPath); 3123 } 3124 } 3125 } 3126 3127 /** 3128 * @see org.opencms.db.I_CmsVfsDriver#replaceResource(org.opencms.db.CmsDbContext, org.opencms.file.CmsResource, byte[], int) 3129 */ 3130 public void replaceResource(CmsDbContext dbc, CmsResource newResource, byte[] resContent, int newResourceType) 3131 throws CmsDataAccessException { 3132 3133 if (resContent == null) { 3134 // nothing to do 3135 return; 3136 } 3137 Connection conn = null; 3138 PreparedStatement stmt = null; 3139 try { 3140 // write the file content 3141 writeContent(dbc, newResource, resContent); 3142 3143 // update the resource record 3144 conn = m_sqlManager.getConnection(dbc); 3145 stmt = m_sqlManager.getPreparedStatement(conn, dbc.currentProject(), "C_RESOURCE_REPLACE"); 3146 stmt.setInt(1, newResourceType); 3147 stmt.setInt(2, resContent.length); 3148 stmt.setLong(3, System.currentTimeMillis()); 3149 stmt.setString(4, newResource.getResourceId().toString()); 3150 stmt.executeUpdate(); 3151 3152 } catch (SQLException e) { 3153 throw new CmsDbSqlException( 3154 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 3155 e); 3156 } finally { 3157 m_sqlManager.closeAll(dbc, conn, stmt, null); 3158 } 3159 } 3160 3161 /** 3162 * @see org.opencms.db.I_CmsVfsDriver#setDriverManager(org.opencms.db.CmsDriverManager) 3163 */ 3164 public void setDriverManager(CmsDriverManager driverManager) { 3165 3166 m_driverManager = driverManager; 3167 } 3168 3169 /** 3170 * @see org.opencms.db.I_CmsVfsDriver#setSqlManager(org.opencms.db.CmsSqlManager) 3171 */ 3172 public void setSqlManager(org.opencms.db.CmsSqlManager sqlManager) { 3173 3174 m_sqlManager = (CmsSqlManager)sqlManager; 3175 } 3176 3177 /** 3178 * @see org.opencms.db.I_CmsVfsDriver#transferResource(org.opencms.db.CmsDbContext, org.opencms.file.CmsProject, org.opencms.file.CmsResource, org.opencms.util.CmsUUID, org.opencms.util.CmsUUID) 3179 */ 3180 public void transferResource( 3181 CmsDbContext dbc, 3182 CmsProject project, 3183 CmsResource resource, 3184 CmsUUID createdUser, 3185 CmsUUID lastModifiedUser) 3186 throws CmsDataAccessException { 3187 3188 if (createdUser == null) { 3189 createdUser = resource.getUserCreated(); 3190 } 3191 if (lastModifiedUser == null) { 3192 lastModifiedUser = resource.getUserLastModified(); 3193 } 3194 3195 PreparedStatement stmt = null; 3196 Connection conn = null; 3197 try { 3198 conn = m_sqlManager.getConnection(dbc); 3199 stmt = m_sqlManager.getPreparedStatement(conn, project, "C_RESOURCES_TRANSFER_RESOURCE"); 3200 stmt.setString(1, createdUser.toString()); 3201 stmt.setString(2, lastModifiedUser.toString()); 3202 stmt.setString(3, resource.getResourceId().toString()); 3203 stmt.executeUpdate(); 3204 } catch (SQLException e) { 3205 throw new CmsDbSqlException( 3206 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 3207 e); 3208 } finally { 3209 m_sqlManager.closeAll(dbc, conn, stmt, null); 3210 } 3211 } 3212 3213 /** 3214 * @see org.opencms.db.I_CmsVfsDriver#updateRelations(CmsDbContext, CmsProject, CmsResource) 3215 */ 3216 public void updateRelations(CmsDbContext dbc, CmsProject onlineProject, CmsResource offlineResource) 3217 throws CmsDataAccessException { 3218 3219 // delete online relations 3220 I_CmsVfsDriver vfsDriver = m_driverManager.getVfsDriver(dbc); 3221 vfsDriver.deleteRelations(dbc, onlineProject.getUuid(), offlineResource, CmsRelationFilter.TARGETS); 3222 3223 CmsUUID projectId; 3224 if (!dbc.getProjectId().isNullUUID()) { 3225 projectId = CmsProject.ONLINE_PROJECT_ID; 3226 } else { 3227 projectId = dbc.currentProject().getUuid(); 3228 } 3229 3230 // copy offline to online relations 3231 CmsUUID dbcProjectId = dbc.getProjectId(); 3232 dbc.setProjectId(CmsUUID.getNullUUID()); 3233 Iterator<CmsRelation> itRelations = m_driverManager.getVfsDriver( 3234 dbc).readRelations(dbc, projectId, offlineResource, CmsRelationFilter.TARGETS).iterator(); 3235 dbc.setProjectId(dbcProjectId); 3236 while (itRelations.hasNext()) { 3237 vfsDriver.createRelation(dbc, onlineProject.getUuid(), itRelations.next()); 3238 } 3239 } 3240 3241 /** 3242 * @see org.opencms.db.I_CmsVfsDriver#validateResourceIdExists(org.opencms.db.CmsDbContext, CmsUUID, org.opencms.util.CmsUUID) 3243 */ 3244 public boolean validateResourceIdExists(CmsDbContext dbc, CmsUUID projectId, CmsUUID resourceId) 3245 throws CmsDataAccessException { 3246 3247 Connection conn = null; 3248 PreparedStatement stmt = null; 3249 ResultSet res = null; 3250 boolean exists = false; 3251 3252 try { 3253 conn = m_sqlManager.getConnection(dbc); 3254 stmt = m_sqlManager.getPreparedStatement(conn, projectId, "C_RESOURCES_READ_RESOURCE_STATE"); 3255 stmt.setString(1, resourceId.toString()); 3256 3257 res = stmt.executeQuery(); 3258 exists = res.next(); 3259 } catch (SQLException e) { 3260 throw new CmsDbSqlException( 3261 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 3262 e); 3263 } finally { 3264 m_sqlManager.closeAll(dbc, conn, stmt, res); 3265 } 3266 3267 return exists; 3268 } 3269 3270 /** 3271 * @see org.opencms.db.I_CmsVfsDriver#validateStructureIdExists(org.opencms.db.CmsDbContext, CmsUUID, org.opencms.util.CmsUUID) 3272 */ 3273 public boolean validateStructureIdExists(CmsDbContext dbc, CmsUUID projectId, CmsUUID structureId) 3274 throws CmsDataAccessException { 3275 3276 Connection conn = null; 3277 PreparedStatement stmt = null; 3278 ResultSet res = null; 3279 boolean found = false; 3280 int count = 0; 3281 3282 try { 3283 conn = m_sqlManager.getConnection(dbc); 3284 stmt = m_sqlManager.getPreparedStatement(conn, projectId, "C_RESOURCES_SELECT_STRUCTURE_ID"); 3285 stmt.setString(1, structureId.toString()); 3286 3287 res = stmt.executeQuery(); 3288 if (res.next()) { 3289 count = res.getInt(1); 3290 found = (count == 1); 3291 while (res.next()) { 3292 // do nothing only move through all rows because of mssql odbc driver 3293 } 3294 } else { 3295 found = false; 3296 } 3297 } catch (SQLException e) { 3298 throw new CmsDbSqlException( 3299 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 3300 e); 3301 } finally { 3302 m_sqlManager.closeAll(dbc, conn, stmt, res); 3303 } 3304 3305 return found; 3306 } 3307 3308 /** 3309 * @see org.opencms.db.I_CmsVfsDriver#writeContent(org.opencms.db.CmsDbContext, org.opencms.file.CmsResource, byte[]) 3310 */ 3311 public void writeContent(CmsDbContext dbc, CmsResource resource, byte[] content) throws CmsDataAccessException { 3312 3313 Connection conn = null; 3314 PreparedStatement stmt = null; 3315 3316 try { 3317 conn = m_sqlManager.getConnection(dbc); 3318 stmt = m_sqlManager.getPreparedStatement(conn, dbc.currentProject(), "C_OFFLINE_CONTENTS_UPDATE"); 3319 // update the file content in the database. 3320 if (content.length < 2000) { 3321 stmt.setBytes(1, content); 3322 } else { 3323 stmt.setBinaryStream(1, new ByteArrayInputStream(content), content.length); 3324 } 3325 stmt.setString(2, resource.getResourceId().toString()); 3326 stmt.executeUpdate(); 3327 } catch (SQLException e) { 3328 throw new CmsDbSqlException( 3329 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 3330 e); 3331 } finally { 3332 m_sqlManager.closeAll(dbc, conn, stmt, null); 3333 } 3334 } 3335 3336 /** 3337 * @see org.opencms.db.I_CmsVfsDriver#writeLastModifiedProjectId(org.opencms.db.CmsDbContext, org.opencms.file.CmsProject, CmsUUID, org.opencms.file.CmsResource) 3338 */ 3339 public void writeLastModifiedProjectId( 3340 CmsDbContext dbc, 3341 CmsProject project, 3342 CmsUUID projectId, 3343 CmsResource resource) 3344 throws CmsDataAccessException { 3345 3346 Connection conn = null; 3347 PreparedStatement stmt = null; 3348 3349 try { 3350 conn = m_sqlManager.getConnection(dbc); 3351 stmt = m_sqlManager.getPreparedStatement(conn, project, "C_RESOURCES_UPDATE_PROJECT_LASTMODIFIED"); 3352 stmt.setString(1, projectId.toString()); 3353 stmt.setString(2, resource.getResourceId().toString()); 3354 stmt.executeUpdate(); 3355 } catch (SQLException e) { 3356 throw new CmsDbSqlException( 3357 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 3358 e); 3359 } finally { 3360 m_sqlManager.closeAll(dbc, conn, stmt, null); 3361 } 3362 } 3363 3364 /** 3365 * @see org.opencms.db.I_CmsVfsDriver#writePropertyObject(org.opencms.db.CmsDbContext, org.opencms.file.CmsProject, org.opencms.file.CmsResource, org.opencms.file.CmsProperty) 3366 */ 3367 public void writePropertyObject(CmsDbContext dbc, CmsProject project, CmsResource resource, CmsProperty property) 3368 throws CmsDataAccessException { 3369 3370 CmsUUID projectId = ((dbc.getProjectId() == null) || dbc.getProjectId().isNullUUID()) 3371 ? project.getUuid() 3372 : dbc.getProjectId(); 3373 3374 // TODO: check if we need autocreation for link property definition types too 3375 CmsPropertyDefinition propertyDefinition = null; 3376 try { 3377 // read the property definition 3378 propertyDefinition = readPropertyDefinition(dbc, property.getName(), projectId); 3379 } catch (CmsDbEntryNotFoundException e) { 3380 if (property.autoCreatePropertyDefinition()) { 3381 propertyDefinition = createPropertyDefinition( 3382 dbc, 3383 projectId, 3384 property.getName(), 3385 CmsPropertyDefinition.TYPE_NORMAL); 3386 try { 3387 readPropertyDefinition(dbc, property.getName(), CmsProject.ONLINE_PROJECT_ID); 3388 } catch (CmsDataAccessException e1) { 3389 createPropertyDefinition( 3390 dbc, 3391 CmsProject.ONLINE_PROJECT_ID, 3392 property.getName(), 3393 CmsPropertyDefinition.TYPE_NORMAL); 3394 } 3395 try { 3396 m_driverManager.getHistoryDriver(dbc).readPropertyDefinition(dbc, property.getName()); 3397 } catch (CmsDataAccessException e1) { 3398 m_driverManager.getHistoryDriver(dbc).createPropertyDefinition( 3399 dbc, 3400 property.getName(), 3401 CmsPropertyDefinition.TYPE_NORMAL); 3402 } 3403 OpenCms.fireCmsEvent( 3404 new CmsEvent( 3405 I_CmsEventListener.EVENT_PROPERTY_DEFINITION_CREATED, 3406 Collections.<String, Object> singletonMap("propertyDefinition", propertyDefinition))); 3407 3408 } else { 3409 throw new CmsDbEntryNotFoundException( 3410 Messages.get().container(Messages.ERR_NO_PROPERTYDEF_WITH_NAME_1, property.getName())); 3411 } 3412 } 3413 3414 PreparedStatement stmt = null; 3415 Connection conn = null; 3416 3417 try { 3418 // read the existing property to test if we need the 3419 // insert or update query to write a property value 3420 CmsProperty existingProperty = readPropertyObject(dbc, propertyDefinition.getName(), project, resource); 3421 3422 if (existingProperty.isIdentical(property)) { 3423 // property already has the identical values set, no write required 3424 return; 3425 } 3426 3427 conn = m_sqlManager.getConnection(dbc); 3428 3429 for (int i = 0; i < 2; i++) { 3430 int mappingType = -1; 3431 String value = null; 3432 CmsUUID id = null; 3433 boolean existsPropertyValue = false; 3434 boolean deletePropertyValue = false; 3435 3436 // 1) take any required decisions to choose and fill the correct SQL query 3437 3438 if (i == 0) { 3439 // write/delete the *structure value* on the first cycle 3440 if ((existingProperty.getStructureValue() != null) && property.isDeleteStructureValue()) { 3441 // this property value is marked to be deleted 3442 deletePropertyValue = true; 3443 } else { 3444 value = property.getStructureValue(); 3445 if (CmsStringUtil.isEmptyOrWhitespaceOnly(value)) { 3446 // no structure value set or the structure value is an empty string, 3447 // continue with the resource value 3448 continue; 3449 } 3450 } 3451 3452 // set the vars to be written to the database 3453 mappingType = CmsProperty.STRUCTURE_RECORD_MAPPING; 3454 id = resource.getStructureId(); 3455 existsPropertyValue = existingProperty.getStructureValue() != null; 3456 } else { 3457 // write/delete the *resource value* on the second cycle 3458 if ((existingProperty.getResourceValue() != null) && property.isDeleteResourceValue()) { 3459 // this property value is marked to be deleted 3460 deletePropertyValue = true; 3461 } else { 3462 value = property.getResourceValue(); 3463 if (CmsStringUtil.isEmptyOrWhitespaceOnly(value)) { 3464 // no resource value set or the resource value is an empty string, 3465 // break out of the loop 3466 break; 3467 } 3468 } 3469 3470 // set the vars to be written to the database 3471 mappingType = CmsProperty.RESOURCE_RECORD_MAPPING; 3472 id = resource.getResourceId(); 3473 existsPropertyValue = existingProperty.getResourceValue() != null; 3474 } 3475 3476 // 2) execute the SQL query 3477 try { 3478 if (!deletePropertyValue) { 3479 // insert/update the property value 3480 if (existsPropertyValue) { 3481 // {structure|resource} property value already exists- use update statement 3482 stmt = m_sqlManager.getPreparedStatement(conn, projectId, "C_PROPERTIES_UPDATE"); 3483 stmt.setString(1, m_sqlManager.validateEmpty(value)); 3484 stmt.setString(2, id.toString()); 3485 stmt.setInt(3, mappingType); 3486 stmt.setString(4, propertyDefinition.getId().toString()); 3487 } else { 3488 // {structure|resource} property value doesn't exist- use create statement 3489 stmt = m_sqlManager.getPreparedStatement(conn, projectId, "C_PROPERTIES_CREATE"); 3490 stmt.setString(1, new CmsUUID().toString()); 3491 stmt.setString(2, propertyDefinition.getId().toString()); 3492 stmt.setString(3, id.toString()); 3493 stmt.setInt(4, mappingType); 3494 stmt.setString(5, m_sqlManager.validateEmpty(value)); 3495 } 3496 } else { 3497 // {structure|resource} property value marked as deleted- use delete statement 3498 stmt = m_sqlManager.getPreparedStatement(conn, projectId, "C_PROPERTIES_DELETE"); 3499 stmt.setString(1, propertyDefinition.getId().toString()); 3500 stmt.setString(2, id.toString()); 3501 stmt.setInt(3, mappingType); 3502 } 3503 stmt.executeUpdate(); 3504 } finally { 3505 m_sqlManager.closeAll(dbc, null, stmt, null); 3506 } 3507 } 3508 } catch (SQLException e) { 3509 throw new CmsDbSqlException( 3510 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 3511 e); 3512 } finally { 3513 m_sqlManager.closeAll(dbc, conn, stmt, null); 3514 } 3515 } 3516 3517 /** 3518 * @see org.opencms.db.I_CmsVfsDriver#writePropertyObjects(org.opencms.db.CmsDbContext, org.opencms.file.CmsProject, org.opencms.file.CmsResource, java.util.List) 3519 */ 3520 public void writePropertyObjects( 3521 CmsDbContext dbc, 3522 CmsProject project, 3523 CmsResource resource, 3524 List<CmsProperty> properties) 3525 throws CmsDataAccessException { 3526 3527 CmsProperty property = null; 3528 3529 for (int i = 0; i < properties.size(); i++) { 3530 property = properties.get(i); 3531 writePropertyObject(dbc, project, resource, property); 3532 } 3533 } 3534 3535 /** 3536 * @see org.opencms.db.I_CmsVfsDriver#writeResource(org.opencms.db.CmsDbContext, CmsUUID, org.opencms.file.CmsResource, int) 3537 */ 3538 public void writeResource(CmsDbContext dbc, CmsUUID projectId, CmsResource resource, int changed) 3539 throws CmsDataAccessException { 3540 3541 // validate the resource length 3542 internalValidateResourceLength(resource); 3543 3544 String resourcePath = CmsFileUtil.removeTrailingSeparator(resource.getRootPath()); 3545 3546 // this task is split into two statements because some DBs (e.g. Oracle) doesn't support multi-table updates 3547 PreparedStatement stmt = null; 3548 Connection conn = null; 3549 long resourceDateModified; 3550 3551 if (resource.isTouched()) { 3552 resourceDateModified = resource.getDateLastModified(); 3553 } else { 3554 resourceDateModified = System.currentTimeMillis(); 3555 } 3556 3557 CmsResourceState structureState = resource.getState(); 3558 CmsResourceState resourceState = resource.getState(); 3559 CmsResourceState structureStateOld = internalReadStructureState(dbc, projectId, resource); 3560 CmsResourceState resourceStateOld = internalReadResourceState(dbc, projectId, resource); 3561 CmsUUID projectLastModified = projectId; 3562 3563 if (changed == CmsDriverManager.UPDATE_RESOURCE_STATE) { 3564 resourceState = resourceStateOld; 3565 resourceState = (resourceState.isNew() ? CmsResource.STATE_NEW : CmsResource.STATE_CHANGED); 3566 structureState = structureStateOld; 3567 } else if (changed == CmsDriverManager.UPDATE_STRUCTURE_STATE) { 3568 structureState = structureStateOld; 3569 structureState = (structureState.isNew() ? CmsResource.STATE_NEW : CmsResource.STATE_CHANGED); 3570 } else if (changed == CmsDriverManager.NOTHING_CHANGED) { 3571 projectLastModified = resource.getProjectLastModified(); 3572 } else { 3573 resourceState = resourceStateOld; 3574 resourceState = (resourceState.isNew() ? CmsResource.STATE_NEW : CmsResource.STATE_CHANGED); 3575 structureState = structureStateOld; 3576 structureState = (structureState.isNew() ? CmsResource.STATE_NEW : CmsResource.STATE_CHANGED); 3577 } 3578 3579 try { 3580 3581 // read the parent id 3582 String parentId = internalReadParentId(dbc, projectId, resourcePath); 3583 int sibCount = countSiblings(dbc, projectId, resource.getResourceId()); 3584 3585 conn = m_sqlManager.getConnection(dbc); 3586 3587 if (changed != CmsDriverManager.UPDATE_STRUCTURE_STATE) { 3588 // if the resource was unchanged 3589 stmt = m_sqlManager.getPreparedStatement(conn, projectId, "C_RESOURCES_UPDATE_RESOURCES"); 3590 stmt.setInt(1, resource.getTypeId()); 3591 stmt.setInt(2, resource.getFlags()); 3592 stmt.setLong(3, resourceDateModified); 3593 stmt.setString(4, resource.getUserLastModified().toString()); 3594 stmt.setInt(5, resourceState.getState()); 3595 stmt.setInt(6, resource.getLength()); 3596 stmt.setLong(7, resource.getDateContent()); 3597 stmt.setString(8, projectLastModified.toString()); 3598 stmt.setInt(9, sibCount); 3599 stmt.setString(10, resource.getResourceId().toString()); 3600 stmt.executeUpdate(); 3601 m_sqlManager.closeAll(dbc, null, stmt, null); 3602 } else { 3603 stmt = m_sqlManager.getPreparedStatement(conn, projectId, "C_RESOURCES_UPDATE_RESOURCES_WITHOUT_STATE"); 3604 stmt.setInt(1, resource.getTypeId()); 3605 stmt.setInt(2, resource.getFlags()); 3606 stmt.setLong(3, resourceDateModified); 3607 stmt.setString(4, resource.getUserLastModified().toString()); 3608 stmt.setInt(5, resource.getLength()); 3609 stmt.setLong(6, resource.getDateContent()); 3610 stmt.setString(7, projectLastModified.toString()); 3611 stmt.setInt(8, sibCount); 3612 stmt.setString(9, resource.getResourceId().toString()); 3613 stmt.executeUpdate(); 3614 m_sqlManager.closeAll(dbc, null, stmt, null); 3615 } 3616 3617 // update the structure 3618 stmt = m_sqlManager.getPreparedStatement(conn, projectId, "C_RESOURCES_UPDATE_STRUCTURE"); 3619 stmt.setString(1, resource.getResourceId().toString()); 3620 stmt.setString(2, resourcePath); 3621 stmt.setInt(3, structureState.getState()); 3622 stmt.setLong(4, resource.getDateReleased()); 3623 stmt.setLong(5, resource.getDateExpired()); 3624 stmt.setString(6, parentId); 3625 stmt.setString(7, resource.getStructureId().toString()); 3626 stmt.executeUpdate(); 3627 } catch (SQLException e) { 3628 throw new CmsDbSqlException( 3629 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 3630 e); 3631 } finally { 3632 m_sqlManager.closeAll(dbc, conn, stmt, null); 3633 } 3634 } 3635 3636 /** 3637 * @see org.opencms.db.I_CmsVfsDriver#writeResourceState(org.opencms.db.CmsDbContext, org.opencms.file.CmsProject, org.opencms.file.CmsResource, int, boolean) 3638 */ 3639 public void writeResourceState( 3640 CmsDbContext dbc, 3641 CmsProject project, 3642 CmsResource resource, 3643 int changed, 3644 boolean isPublishing) 3645 throws CmsDataAccessException { 3646 3647 PreparedStatement stmt = null; 3648 Connection conn = null; 3649 3650 if (project.getUuid().equals(CmsProject.ONLINE_PROJECT_ID)) { 3651 return; 3652 } 3653 3654 try { 3655 conn = m_sqlManager.getConnection(dbc); 3656 3657 if (changed == CmsDriverManager.UPDATE_RESOURCE_PROJECT) { 3658 stmt = m_sqlManager.getPreparedStatement(conn, project, "C_RESOURCES_UPDATE_RESOURCE_PROJECT"); 3659 stmt.setInt(1, resource.getFlags()); 3660 stmt.setString(2, project.getUuid().toString()); 3661 stmt.setString(3, resource.getResourceId().toString()); 3662 stmt.executeUpdate(); 3663 m_sqlManager.closeAll(dbc, null, stmt, null); 3664 } 3665 3666 if (changed == CmsDriverManager.UPDATE_RESOURCE) { 3667 stmt = m_sqlManager.getPreparedStatement( 3668 conn, 3669 project, 3670 "C_RESOURCES_UPDATE_RESOURCE_STATELASTMODIFIED"); 3671 stmt.setInt(1, resource.getState().getState()); 3672 stmt.setLong(2, resource.getDateLastModified()); 3673 stmt.setString(3, resource.getUserLastModified().toString()); 3674 stmt.setString(4, project.getUuid().toString()); 3675 stmt.setString(5, resource.getResourceId().toString()); 3676 stmt.executeUpdate(); 3677 m_sqlManager.closeAll(dbc, null, stmt, null); 3678 } 3679 3680 if ((changed == CmsDriverManager.UPDATE_RESOURCE_STATE) || (changed == CmsDriverManager.UPDATE_ALL)) { 3681 stmt = m_sqlManager.getPreparedStatement(conn, project, "C_RESOURCES_UPDATE_RESOURCE_STATE"); 3682 stmt.setInt(1, resource.getState().getState()); 3683 stmt.setString(2, project.getUuid().toString()); 3684 stmt.setString(3, resource.getResourceId().toString()); 3685 stmt.executeUpdate(); 3686 m_sqlManager.closeAll(dbc, null, stmt, null); 3687 } 3688 3689 if ((changed == CmsDriverManager.UPDATE_STRUCTURE) 3690 || (changed == CmsDriverManager.UPDATE_ALL) 3691 || (changed == CmsDriverManager.UPDATE_STRUCTURE_STATE)) { 3692 stmt = m_sqlManager.getPreparedStatement(conn, project, "C_RESOURCES_UPDATE_STRUCTURE_STATE"); 3693 stmt.setInt(1, resource.getState().getState()); 3694 stmt.setString(2, resource.getStructureId().toString()); 3695 stmt.executeUpdate(); 3696 m_sqlManager.closeAll(dbc, null, stmt, null); 3697 } 3698 3699 if ((changed == CmsDriverManager.UPDATE_STRUCTURE) || (changed == CmsDriverManager.UPDATE_ALL)) { 3700 stmt = m_sqlManager.getPreparedStatement(conn, project, "C_RESOURCES_UPDATE_RELEASE_EXPIRED"); 3701 stmt.setLong(1, resource.getDateReleased()); 3702 stmt.setLong(2, resource.getDateExpired()); 3703 stmt.setString(3, resource.getStructureId().toString()); 3704 stmt.executeUpdate(); 3705 m_sqlManager.closeAll(dbc, null, stmt, null); 3706 } 3707 } catch (SQLException e) { 3708 throw new CmsDbSqlException( 3709 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 3710 e); 3711 } finally { 3712 m_sqlManager.closeAll(dbc, conn, stmt, null); 3713 } 3714 3715 if (isPublishing) { 3716 internalUpdateVersions(dbc, resource); 3717 } 3718 } 3719 3720 /** 3721 * Checks that the current user has write permissions for all subresources of the given folder.<p> 3722 * 3723 * @param dbc the current database context 3724 * @param folder the folder to check 3725 * 3726 * @throws CmsDataAccessException if something goes wrong 3727 */ 3728 protected void checkWritePermissionsInFolder(CmsDbContext dbc, CmsResource folder) throws CmsDataAccessException { 3729 3730 ResultSet res = null; 3731 PreparedStatement stmt = null; 3732 Connection conn = null; 3733 3734 CmsUUID projectId = dbc.getRequestContext().getCurrentProject().getUuid(); 3735 3736 // first read all subresources with ACEs 3737 List<CmsResource> resources = new ArrayList<CmsResource>(); 3738 try { 3739 conn = m_sqlManager.getConnection(dbc); 3740 stmt = m_sqlManager.getPreparedStatement(conn, projectId, "C_RESOURCES_READ_WITH_ACE_1"); 3741 stmt.setString(1, folder.getRootPath() + "%"); 3742 res = stmt.executeQuery(); 3743 3744 while (res.next()) { 3745 resources.add(createResource(res, projectId)); 3746 } 3747 } catch (SQLException e) { 3748 throw new CmsDbSqlException( 3749 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 3750 e); 3751 } finally { 3752 m_sqlManager.closeAll(dbc, conn, stmt, res); 3753 } 3754 3755 // check current user write permission for each of these resources 3756 Iterator<CmsResource> itResources = resources.iterator(); 3757 while (itResources.hasNext()) { 3758 CmsResource resource = itResources.next(); 3759 try { 3760 m_driverManager.getSecurityManager().checkPermissions( 3761 dbc.getRequestContext(), 3762 resource, 3763 CmsPermissionSet.ACCESS_WRITE, 3764 false, 3765 CmsResourceFilter.ALL); 3766 } catch (CmsException e) { 3767 throw new CmsDataAccessException(e.getMessageContainer(), e); 3768 } 3769 } 3770 3771 // then check for possible jsp pages without permissions 3772 CmsResourceFilter filter = CmsResourceFilter.ALL; 3773 itResources = readTypesInResourceTree( 3774 dbc, 3775 projectId, 3776 folder.getRootPath(), 3777 CmsResourceTypeJsp.getJspResourceTypeIds(), 3778 filter.getState(), 3779 filter.getModifiedAfter(), 3780 filter.getModifiedBefore(), 3781 filter.getReleaseAfter(), 3782 filter.getReleaseBefore(), 3783 filter.getExpireAfter(), 3784 filter.getExpireBefore(), 3785 CmsDriverManager.READMODE_INCLUDE_TREE).iterator(); 3786 while (itResources.hasNext()) { 3787 CmsResource resource = itResources.next(); 3788 try { 3789 m_driverManager.getSecurityManager().checkPermissions( 3790 dbc.getRequestContext(), 3791 resource, 3792 CmsPermissionSet.ACCESS_WRITE, 3793 false, 3794 CmsResourceFilter.ALL); 3795 } catch (CmsException e) { 3796 throw new CmsDataAccessException(e.getMessageContainer(), e); 3797 } 3798 } 3799 } 3800 3801 /** 3802 * Returns additional SQL query property files to load between the generic and database-specific queries.<p> 3803 * 3804 * @param configuration the OpenCms parameter configuration 3805 * 3806 * @return the additional SQL query property files 3807 */ 3808 protected List<String> getAdditionalSqlQueryProperties(CmsParameterConfiguration configuration) { 3809 3810 return Collections.emptyList(); 3811 } 3812 3813 /** 3814 * Returns the count of properties for a property definition.<p> 3815 * 3816 * @param dbc the current database context 3817 * @param propertyDefinition the property definition to test 3818 * @param projectId the ID of the current project 3819 * 3820 * @return the amount of properties for a property definition 3821 * @throws CmsDataAccessException if something goes wrong 3822 */ 3823 protected int internalCountProperties(CmsDbContext dbc, CmsPropertyDefinition propertyDefinition, CmsUUID projectId) 3824 throws CmsDataAccessException { 3825 3826 ResultSet res = null; 3827 PreparedStatement stmt = null; 3828 Connection conn = null; 3829 int count = 0; 3830 3831 try { 3832 // create statement 3833 conn = m_sqlManager.getConnection(dbc); 3834 stmt = m_sqlManager.getPreparedStatement(conn, projectId, "C_PROPERTIES_READALL_COUNT"); 3835 stmt.setString(1, propertyDefinition.getId().toString()); 3836 res = stmt.executeQuery(); 3837 3838 if (res.next()) { 3839 count = res.getInt(1); 3840 while (res.next()) { 3841 // do nothing only move through all rows because of mssql odbc driver 3842 } 3843 } else { 3844 throw new CmsDbConsistencyException( 3845 Messages.get().container(Messages.ERR_COUNTING_PROPERTIES_1, propertyDefinition.getName())); 3846 } 3847 } catch (SQLException e) { 3848 throw new CmsDbSqlException( 3849 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 3850 e); 3851 } finally { 3852 m_sqlManager.closeAll(dbc, conn, stmt, res); 3853 } 3854 3855 return count; 3856 } 3857 3858 /** 3859 * Creates a new counter.<p> 3860 * 3861 * @param dbc the database context 3862 * @param name the name of the counter to create 3863 * @param value the inital value of the counter 3864 * 3865 * @throws CmsDbSqlException if something goes wrong 3866 */ 3867 protected void internalCreateCounter(CmsDbContext dbc, String name, int value) throws CmsDbSqlException { 3868 3869 PreparedStatement stmt = null; 3870 Connection conn = null; 3871 try { 3872 conn = m_sqlManager.getConnection(dbc); 3873 stmt = m_sqlManager.getPreparedStatement(conn, CmsProject.ONLINE_PROJECT_ID, "C_CREATE_COUNTER"); 3874 stmt.setString(1, name); 3875 stmt.setInt(2, value); 3876 stmt.executeUpdate(); 3877 } catch (SQLException e) { 3878 throw wrapException(stmt, e); 3879 } finally { 3880 m_sqlManager.closeAll(dbc, conn, stmt, null); 3881 } 3882 } 3883 3884 /** 3885 * Creates an URL name mapping entry from a result set.<p> 3886 * 3887 * @param resultSet a result set 3888 * @return the URL name mapping entry created from the result set 3889 * 3890 * @throws SQLException if something goes wrong 3891 */ 3892 protected CmsUrlNameMappingEntry internalCreateUrlNameMappingEntry(ResultSet resultSet) throws SQLException { 3893 3894 String name = resultSet.getString(1); 3895 CmsUUID structureId = new CmsUUID(resultSet.getString(2)); 3896 int state = resultSet.getInt(3); 3897 long dateChanged = resultSet.getLong(4); 3898 String locale = resultSet.getString(5); 3899 return new CmsUrlNameMappingEntry(name, structureId, state, dateChanged, locale); 3900 } 3901 3902 /** 3903 * Increments a counter.<p> 3904 * 3905 * @param dbc the current db context 3906 * @param name the name of the counter which should be incremented 3907 * 3908 * @throws CmsDbSqlException if something goes wrong 3909 */ 3910 protected void internalIncrementCounter(CmsDbContext dbc, String name) throws CmsDbSqlException { 3911 3912 PreparedStatement stmt = null; 3913 Connection conn = null; 3914 ResultSet resultSet = null; 3915 try { 3916 conn = m_sqlManager.getConnection(dbc); 3917 stmt = m_sqlManager.getPreparedStatement(conn, CmsProject.ONLINE_PROJECT_ID, "C_INCREMENT_COUNTER"); 3918 stmt.setString(1, name); 3919 stmt.executeUpdate(); 3920 3921 } catch (SQLException e) { 3922 throw wrapException(stmt, e); 3923 } finally { 3924 m_sqlManager.closeAll(dbc, conn, stmt, resultSet); 3925 } 3926 } 3927 3928 /** 3929 * Helper method to create an alias object from a result set.<p> 3930 * 3931 * @param resultset the result set 3932 * @return the alias object created from the result set 3933 * 3934 * @throws SQLException if something goes wrong 3935 */ 3936 protected CmsAlias internalReadAlias(ResultSet resultset) throws SQLException { 3937 3938 String siteRoot = resultset.getString(1); 3939 String path = resultset.getString(2); 3940 int mode = resultset.getInt(3); 3941 String structId = resultset.getString(4); 3942 return new CmsAlias(new CmsUUID(structId), siteRoot, path, CmsAliasMode.fromInt(mode)); 3943 } 3944 3945 /** 3946 * Reads the current value of a counter.<p> 3947 * 3948 * @param dbc the database context 3949 * @param name the name of the counter 3950 * @return the current value of the counter, or null if the counter was not found 3951 * 3952 * @throws CmsDbSqlException if something goes wrong 3953 */ 3954 protected Integer internalReadCounter(CmsDbContext dbc, String name) throws CmsDbSqlException { 3955 3956 PreparedStatement stmt = null; 3957 Connection conn = null; 3958 ResultSet resultSet = null; 3959 try { 3960 conn = m_sqlManager.getConnection(dbc); 3961 stmt = m_sqlManager.getPreparedStatement(conn, CmsProject.ONLINE_PROJECT_ID, "C_READ_COUNTER"); 3962 stmt.setString(1, name); 3963 resultSet = stmt.executeQuery(); 3964 Integer result = null; 3965 if (resultSet.next()) { 3966 int counter = resultSet.getInt(1); 3967 result = Integer.valueOf(counter); 3968 while (resultSet.next()) { 3969 // for MSSQL 3970 } 3971 } 3972 return result; 3973 } catch (SQLException e) { 3974 throw wrapException(stmt, e); 3975 } finally { 3976 m_sqlManager.closeAll(dbc, conn, stmt, resultSet); 3977 } 3978 } 3979 3980 /** 3981 * Returns the parent id of the given resource.<p> 3982 * 3983 * @param dbc the current database context 3984 * @param projectId the current project id 3985 * @param resourcename the resource name to read the parent id for 3986 * 3987 * @return the parent id of the given resource 3988 * 3989 * @throws CmsDataAccessException if something goes wrong 3990 */ 3991 protected String internalReadParentId(CmsDbContext dbc, CmsUUID projectId, String resourcename) 3992 throws CmsDataAccessException { 3993 3994 if ("/".equalsIgnoreCase(resourcename)) { 3995 return CmsUUID.getNullUUID().toString(); 3996 } 3997 3998 String parent = CmsResource.getParentFolder(resourcename); 3999 parent = CmsFileUtil.removeTrailingSeparator(parent); 4000 4001 ResultSet res = null; 4002 PreparedStatement stmt = null; 4003 Connection conn = null; 4004 String parentId = null; 4005 4006 try { 4007 conn = m_sqlManager.getConnection(dbc); 4008 stmt = m_sqlManager.getPreparedStatement(conn, projectId, "C_RESOURCES_READ_PARENT_STRUCTURE_ID"); 4009 stmt.setString(1, parent); 4010 res = stmt.executeQuery(); 4011 4012 if (res.next()) { 4013 parentId = res.getString(1); 4014 while (res.next()) { 4015 // do nothing only move through all rows because of mssql odbc driver 4016 } 4017 } else { 4018 throw new CmsVfsResourceNotFoundException( 4019 Messages.get().container(Messages.ERR_READ_PARENT_ID_1, dbc.removeSiteRoot(resourcename))); 4020 } 4021 } catch (SQLException e) { 4022 throw new CmsDbSqlException( 4023 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 4024 e); 4025 } finally { 4026 m_sqlManager.closeAll(dbc, conn, stmt, res); 4027 } 4028 4029 return parentId; 4030 } 4031 4032 /** 4033 * Creates a new {@link CmsRelation} object from the given result set entry.<p> 4034 * 4035 * @param res the result set 4036 * 4037 * @return the new {@link CmsRelation} object 4038 * 4039 * @throws SQLException if something goes wrong 4040 */ 4041 protected CmsRelation internalReadRelation(ResultSet res) throws SQLException { 4042 4043 CmsUUID sourceId = new CmsUUID(res.getString(m_sqlManager.readQuery("C_RELATION_SOURCE_ID"))); 4044 String sourcePath = res.getString(m_sqlManager.readQuery("C_RELATION_SOURCE_PATH")); 4045 CmsUUID targetId = new CmsUUID(res.getString(m_sqlManager.readQuery("C_RELATION_TARGET_ID"))); 4046 String targetPath = res.getString(m_sqlManager.readQuery("C_RELATION_TARGET_PATH")); 4047 int type = res.getInt(m_sqlManager.readQuery("C_RELATION_TYPE")); 4048 return new CmsRelation(sourceId, sourcePath, targetId, targetPath, CmsRelationType.valueOf(type)); 4049 } 4050 4051 /** 4052 * Returns the resource state of the given resource.<p> 4053 * 4054 * @param dbc the database context 4055 * @param projectId the id of the project 4056 * @param resource the resource to read the resource state for 4057 * 4058 * @return the resource state of the given resource 4059 * 4060 * @throws CmsDbSqlException if something goes wrong 4061 */ 4062 protected CmsResourceState internalReadResourceState(CmsDbContext dbc, CmsUUID projectId, CmsResource resource) 4063 throws CmsDbSqlException { 4064 4065 CmsResourceState state = CmsResource.STATE_KEEP; 4066 4067 Connection conn = null; 4068 PreparedStatement stmt = null; 4069 ResultSet res = null; 4070 try { 4071 conn = m_sqlManager.getConnection(dbc); 4072 stmt = m_sqlManager.getPreparedStatement(conn, projectId, "C_READ_RESOURCE_STATE"); 4073 stmt.setString(1, resource.getResourceId().toString()); 4074 res = stmt.executeQuery(); 4075 if (res.next()) { 4076 state = CmsResourceState.valueOf(res.getInt(m_sqlManager.readQuery("C_RESOURCES_STATE"))); 4077 while (res.next()) { 4078 // do nothing only move through all rows because of mssql odbc driver 4079 } 4080 } 4081 } catch (SQLException e) { 4082 throw new CmsDbSqlException( 4083 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 4084 e); 4085 } finally { 4086 m_sqlManager.closeAll(dbc, conn, stmt, res); 4087 } 4088 return state; 4089 } 4090 4091 /** 4092 * Returns the structure state of the given resource.<p> 4093 * 4094 * @param dbc the database context 4095 * @param projectId the id of the project 4096 * @param resource the resource to read the structure state for 4097 * 4098 * @return the structure state of the given resource 4099 * 4100 * @throws CmsDbSqlException if something goes wrong 4101 */ 4102 protected CmsResourceState internalReadStructureState(CmsDbContext dbc, CmsUUID projectId, CmsResource resource) 4103 throws CmsDbSqlException { 4104 4105 CmsResourceState state = CmsResource.STATE_KEEP; 4106 4107 Connection conn = null; 4108 PreparedStatement stmt = null; 4109 ResultSet res = null; 4110 try { 4111 conn = m_sqlManager.getConnection(dbc); 4112 stmt = m_sqlManager.getPreparedStatement(conn, projectId, "C_READ_STRUCTURE_STATE"); 4113 stmt.setString(1, resource.getStructureId().toString()); 4114 res = stmt.executeQuery(); 4115 if (res.next()) { 4116 state = CmsResourceState.valueOf(res.getInt(m_sqlManager.readQuery("C_RESOURCES_STRUCTURE_STATE"))); 4117 while (res.next()) { 4118 // do nothing only move through all rows because of mssql odbc driver 4119 } 4120 } 4121 } catch (SQLException e) { 4122 throw new CmsDbSqlException( 4123 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 4124 e); 4125 } finally { 4126 m_sqlManager.closeAll(dbc, conn, stmt, res); 4127 } 4128 return state; 4129 } 4130 4131 /** 4132 * Removes a resource physically in the database.<p> 4133 * 4134 * @param dbc the current database context 4135 * @param currentProject the current project 4136 * @param resource the folder to remove 4137 * 4138 * @throws CmsDataAccessException if something goes wrong 4139 */ 4140 protected void internalRemoveFolder(CmsDbContext dbc, CmsProject currentProject, CmsResource resource) 4141 throws CmsDataAccessException { 4142 4143 PreparedStatement stmt = null; 4144 Connection conn = null; 4145 4146 try { 4147 conn = m_sqlManager.getConnection(dbc); 4148 4149 // delete the structure record 4150 stmt = m_sqlManager.getPreparedStatement(conn, currentProject, "C_STRUCTURE_DELETE_BY_STRUCTUREID"); 4151 stmt.setString(1, resource.getStructureId().toString()); 4152 stmt.executeUpdate(); 4153 4154 m_sqlManager.closeAll(dbc, null, stmt, null); 4155 4156 // delete the resource record 4157 stmt = m_sqlManager.getPreparedStatement(conn, currentProject, "C_RESOURCES_DELETE_BY_RESOURCEID"); 4158 stmt.setString(1, resource.getResourceId().toString()); 4159 stmt.executeUpdate(); 4160 } catch (SQLException e) { 4161 throw new CmsDbSqlException( 4162 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 4163 e); 4164 } finally { 4165 m_sqlManager.closeAll(dbc, conn, stmt, null); 4166 } 4167 } 4168 4169 /** 4170 * Updates the offline version numbers.<p> 4171 * 4172 * @param dbc the current database context 4173 * @param resource the resource to update the version number for 4174 * 4175 * @throws CmsDataAccessException if something goes wrong 4176 */ 4177 protected void internalUpdateVersions(CmsDbContext dbc, CmsResource resource) throws CmsDataAccessException { 4178 4179 if (dbc.getRequestContext() == null) { 4180 // no needed during initialization 4181 return; 4182 } 4183 if (dbc.currentProject().isOnlineProject()) { 4184 // this method is supposed to be used only in the offline project 4185 return; 4186 } 4187 4188 // read the online version numbers 4189 Map<String, Integer> onlineVersions = readVersions( 4190 dbc, 4191 CmsProject.ONLINE_PROJECT_ID, 4192 resource.getResourceId(), 4193 resource.getStructureId()); 4194 int onlineStructureVersion = onlineVersions.get("structure").intValue(); 4195 int onlineResourceVersion = onlineVersions.get("resource").intValue(); 4196 4197 Connection conn = null; 4198 PreparedStatement stmt = null; 4199 ResultSet res = null; 4200 4201 try { 4202 conn = m_sqlManager.getConnection(dbc); 4203 4204 // update the resource version 4205 stmt = m_sqlManager.getPreparedStatement(conn, dbc.currentProject(), "C_RESOURCES_UPDATE_RESOURCE_VERSION"); 4206 stmt.setInt(1, onlineResourceVersion); 4207 stmt.setString(2, resource.getResourceId().toString()); 4208 stmt.executeUpdate(); 4209 m_sqlManager.closeAll(dbc, null, stmt, null); 4210 4211 // update the structure version 4212 stmt = m_sqlManager.getPreparedStatement( 4213 conn, 4214 dbc.currentProject(), 4215 "C_RESOURCES_UPDATE_STRUCTURE_VERSION"); 4216 stmt.setInt(1, onlineStructureVersion); 4217 stmt.setString(2, resource.getStructureId().toString()); 4218 stmt.executeUpdate(); 4219 m_sqlManager.closeAll(dbc, null, stmt, null); 4220 4221 } catch (SQLException e) { 4222 throw new CmsDbSqlException( 4223 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 4224 e); 4225 } finally { 4226 m_sqlManager.closeAll(dbc, conn, stmt, res); 4227 } 4228 } 4229 4230 /** 4231 * Validates that the length setting of a resource is always correct.<p> 4232 * 4233 * Files need to have a resource length of >= 0, while folders require 4234 * a resource length of -1.<p> 4235 * 4236 * @param resource the resource to check the length for 4237 * @throws CmsDataAccessException if the resource length is not correct 4238 */ 4239 protected void internalValidateResourceLength(CmsResource resource) throws CmsDataAccessException { 4240 4241 if (resource.isFolder() && (resource.getLength() == -1)) { 4242 return; 4243 } 4244 4245 if (resource.isFile() && (resource.getLength() >= 0)) { 4246 return; 4247 } 4248 4249 throw new CmsDataAccessException( 4250 Messages.get().container( 4251 Messages.ERR_INVALID_RESOURCE_LENGTH_2, 4252 Integer.valueOf(resource.getLength()), 4253 resource.getRootPath())); 4254 } 4255 4256 /** 4257 * Moves all relations of a resource to the new path.<p> 4258 * 4259 * @param dbc the current database context 4260 * @param projectId the id of the project to apply the changes 4261 * @param structureId the structure id of the resource to apply the changes to 4262 * @param rootPath the new root path 4263 * 4264 * @throws CmsDataAccessException if something goes wrong 4265 */ 4266 protected void moveRelations(CmsDbContext dbc, CmsUUID projectId, CmsUUID structureId, String rootPath) 4267 throws CmsDataAccessException { 4268 4269 Connection conn = null; 4270 PreparedStatement stmt = null; 4271 4272 try { 4273 conn = m_sqlManager.getConnection(dbc); 4274 stmt = m_sqlManager.getPreparedStatement(conn, projectId, "C_MOVE_RELATIONS_SOURCE"); 4275 stmt.setString(1, rootPath); 4276 stmt.setString(2, structureId.toString()); 4277 4278 stmt.executeUpdate(); 4279 m_sqlManager.closeAll(dbc, null, stmt, null); 4280 4281 stmt = m_sqlManager.getPreparedStatement(conn, projectId, "C_MOVE_RELATIONS_TARGET"); 4282 stmt.setString(1, rootPath); 4283 stmt.setString(2, structureId.toString()); 4284 4285 stmt.executeUpdate(); 4286 } catch (SQLException e) { 4287 throw new CmsDbSqlException( 4288 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 4289 e); 4290 } finally { 4291 m_sqlManager.closeAll(dbc, conn, stmt, null); 4292 } 4293 } 4294 4295 /** 4296 * Appends the appropriate selection criteria related with the expiration date.<p> 4297 * 4298 * @param projectId the id of the project of the resources 4299 * @param startTime the start time 4300 * @param endTime the end time 4301 * @param conditions buffer to append the selection criteria 4302 * @param params list to append the selection parameters 4303 */ 4304 protected void prepareExpiredTimeRangeCondition( 4305 CmsUUID projectId, 4306 long startTime, 4307 long endTime, 4308 StringBuffer conditions, 4309 List<Object> params) { 4310 4311 if (startTime > 0L) { 4312 // READ_IGNORE_TIME: if NOT set, add condition to match expired date against startTime 4313 conditions.append(BEGIN_INCLUDE_CONDITION); 4314 conditions.append(m_sqlManager.readQuery(projectId, "C_STRUCTURE_SELECT_BY_DATE_EXPIRED_AFTER")); 4315 conditions.append(END_CONDITION); 4316 params.add(Long.valueOf(startTime)); 4317 } 4318 4319 if (endTime > 0L) { 4320 // READ_IGNORE_TIME: if NOT set, add condition to match expired date against endTime 4321 conditions.append(BEGIN_INCLUDE_CONDITION); 4322 conditions.append(m_sqlManager.readQuery(projectId, "C_STRUCTURE_SELECT_BY_DATE_EXPIRED_BEFORE")); 4323 conditions.append(END_CONDITION); 4324 params.add(Long.valueOf(endTime)); 4325 } 4326 } 4327 4328 /** 4329 * Appends the appropriate selection criteria related with the parentPath.<p> 4330 * 4331 * @param projectId the id of the project of the resources 4332 * @param parent the parent path or UUID (if mode is C_READMODE_EXCLUDE_TREE) 4333 * @param mode the selection mode 4334 * @param conditions buffer to append the selection criteria 4335 * @param params list to append the selection parameters 4336 */ 4337 protected void preparePathCondition( 4338 CmsUUID projectId, 4339 String parent, 4340 int mode, 4341 StringBuffer conditions, 4342 List<Object> params) { 4343 4344 if (parent == CmsDriverManager.READ_IGNORE_PARENT) { 4345 // parent can be ignored 4346 return; 4347 } 4348 4349 if ((mode & CmsDriverManager.READMODE_EXCLUDE_TREE) > 0) { 4350 // only return immediate children - use UUID optimization 4351 conditions.append(BEGIN_INCLUDE_CONDITION); 4352 conditions.append(m_sqlManager.readQuery(projectId, "C_RESOURCES_SELECT_BY_PARENT_UUID")); 4353 conditions.append(END_CONDITION); 4354 params.add(parent); 4355 return; 4356 } 4357 4358 if ("/".equalsIgnoreCase(parent)) { 4359 // if root folder is parent, no additional condition is needed since all resources match anyway 4360 return; 4361 } 4362 4363 // add condition to read path subtree 4364 conditions.append(BEGIN_INCLUDE_CONDITION); 4365 conditions.append(m_sqlManager.readQuery(projectId, "C_RESOURCES_SELECT_BY_PATH_PREFIX")); 4366 conditions.append(END_CONDITION); 4367 params.add(CmsFileUtil.addTrailingSeparator(escapeDbWildcard(parent)) + "%"); 4368 } 4369 4370 /** 4371 * Appends the appropriate selection criteria related with the projectId.<p> 4372 * 4373 * @param projectId the id of the project of the resources 4374 * @param mode the selection mode 4375 * @param conditions buffer to append the selection criteria 4376 * @param params list to append the selection parameters 4377 */ 4378 protected void prepareProjectCondition(CmsUUID projectId, int mode, StringBuffer conditions, List<Object> params) { 4379 4380 if ((mode & CmsDriverManager.READMODE_INCLUDE_PROJECT) > 0) { 4381 // C_READMODE_INCLUDE_PROJECT: add condition to match the PROJECT_ID 4382 conditions.append(BEGIN_INCLUDE_CONDITION); 4383 conditions.append(m_sqlManager.readQuery(projectId, "C_RESOURCES_SELECT_BY_PROJECT_LASTMODIFIED")); 4384 conditions.append(END_CONDITION); 4385 params.add(projectId.toString()); 4386 } 4387 } 4388 4389 /** 4390 * Build the whole WHERE sql statement part for the given relation filter.<p> 4391 * 4392 * @param mode the relation condition mode - indicates what the conditions will be used for 4393 * @param projectId the current project id 4394 * @param filter the filter 4395 * @param resource the resource (may be null, if you want to delete all relations for the resource in the filter) 4396 * @param params the parameter values (return parameter) 4397 * @param checkSource if the query is for the source relations 4398 * 4399 * @return the WHERE sql statement part string 4400 */ 4401 protected String prepareRelationConditions( 4402 RelationConditionMode mode, 4403 CmsUUID projectId, 4404 CmsRelationFilter filter, 4405 CmsResource resource, 4406 List<Object> params, 4407 boolean checkSource) { 4408 4409 StringBuffer conditions = new StringBuffer(128); 4410 params.clear(); // be sure the parameters list is clear 4411 4412 // source or target filter 4413 if (filter.isSource() || filter.isTarget()) { 4414 // source or target id filter from resource 4415 if (resource != null) { 4416 conditions.append(BEGIN_CONDITION); 4417 if (filter.isSource() && checkSource) { 4418 if (!filter.isIncludeSubresources()) { 4419 conditions.append(m_sqlManager.readQuery(projectId, "C_RELATION_FILTER_TARGET_ID")); 4420 params.add(resource.getStructureId().toString()); 4421 } else { 4422 conditions.append(m_sqlManager.readQuery(projectId, "C_RELATION_FILTER_TARGET_PATH")); 4423 params.add(escapeDbWildcard(resource.getRootPath()) + '%'); 4424 } 4425 } else if (filter.isTarget() && !checkSource) { 4426 if (!filter.isIncludeSubresources() || (mode == RelationConditionMode.delete)) { 4427 // the mode check above is there to *not* silently remove categories for everything below the passed in resource! 4428 conditions.append(m_sqlManager.readQuery(projectId, "C_RELATION_FILTER_SOURCE_ID")); 4429 params.add(resource.getStructureId().toString()); 4430 } else { 4431 conditions.append(m_sqlManager.readQuery(projectId, "C_RELATION_FILTER_SOURCE_PATH")); 4432 params.add(escapeDbWildcard(resource.getRootPath()) + '%'); 4433 } 4434 } 4435 conditions.append(END_CONDITION); 4436 } 4437 4438 // target or source id filter from filter parameter 4439 if (filter.getStructureId() != null) { 4440 if (conditions.length() == 0) { 4441 conditions.append(BEGIN_CONDITION); 4442 } else { 4443 conditions.append(BEGIN_INCLUDE_CONDITION); 4444 } 4445 4446 if (filter.isSource() && checkSource) { 4447 conditions.append(m_sqlManager.readQuery(projectId, "C_RELATION_FILTER_SOURCE_ID")); 4448 params.add(filter.getStructureId().toString()); 4449 } else if (filter.isTarget() && !checkSource) { 4450 conditions.append(m_sqlManager.readQuery(projectId, "C_RELATION_FILTER_TARGET_ID")); 4451 params.add(filter.getStructureId().toString()); 4452 } 4453 conditions.append(END_CONDITION); 4454 } 4455 4456 // target or source path filter from filter parameter 4457 if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(filter.getPath())) { 4458 if (conditions.length() == 0) { 4459 conditions.append(BEGIN_CONDITION); 4460 } else { 4461 conditions.append(BEGIN_INCLUDE_CONDITION); 4462 } 4463 4464 String queryPath = filter.getPath(); 4465 queryPath = escapeDbWildcard(queryPath); 4466 if (filter.isIncludeSubresources()) { 4467 queryPath += '%'; 4468 } 4469 if (filter.isSource() && checkSource) { 4470 conditions.append(m_sqlManager.readQuery(projectId, "C_RELATION_FILTER_SOURCE_PATH")); 4471 params.add(queryPath); 4472 } else if (filter.isTarget() && !checkSource) { 4473 conditions.append(m_sqlManager.readQuery(projectId, "C_RELATION_FILTER_TARGET_PATH")); 4474 params.add(queryPath); 4475 } 4476 conditions.append(END_CONDITION); 4477 } 4478 } 4479 4480 // relation type filter 4481 Set<CmsRelationType> types = filter.getTypes(); 4482 if (!types.isEmpty()) { 4483 if (conditions.length() == 0) { 4484 conditions.append(BEGIN_CONDITION); 4485 } else { 4486 conditions.append(BEGIN_INCLUDE_CONDITION); 4487 } 4488 conditions.append(m_sqlManager.readQuery(projectId, "C_RELATION_FILTER_TYPE")); 4489 conditions.append(BEGIN_CONDITION); 4490 Iterator<CmsRelationType> it = types.iterator(); 4491 while (it.hasNext()) { 4492 CmsRelationType type = it.next(); 4493 conditions.append("?"); 4494 params.add(Integer.valueOf(type.getId())); 4495 if (it.hasNext()) { 4496 conditions.append(", "); 4497 } 4498 } 4499 conditions.append(END_CONDITION); 4500 conditions.append(END_CONDITION); 4501 } 4502 return conditions.toString(); 4503 } 4504 4505 /** 4506 * Appends the appropriate selection criteria related with the released date.<p> 4507 * 4508 * @param projectId the id of the project 4509 * @param startTime the start time 4510 * @param endTime the stop time 4511 * @param conditions buffer to append the selection criteria 4512 * @param params list to append the selection parameters 4513 */ 4514 protected void prepareReleasedTimeRangeCondition( 4515 CmsUUID projectId, 4516 long startTime, 4517 long endTime, 4518 StringBuffer conditions, 4519 List<Object> params) { 4520 4521 if (startTime > 0L) { 4522 // READ_IGNORE_TIME: if NOT set, add condition to match released date against startTime 4523 conditions.append(BEGIN_INCLUDE_CONDITION); 4524 conditions.append(m_sqlManager.readQuery(projectId, "C_STRUCTURE_SELECT_BY_DATE_RELEASED_AFTER")); 4525 conditions.append(END_CONDITION); 4526 params.add(Long.valueOf(startTime)); 4527 } 4528 4529 if (endTime > 0L) { 4530 // READ_IGNORE_TIME: if NOT set, add condition to match released date against endTime 4531 conditions.append(BEGIN_INCLUDE_CONDITION); 4532 conditions.append(m_sqlManager.readQuery(projectId, "C_STRUCTURE_SELECT_BY_DATE_RELEASED_BEFORE")); 4533 conditions.append(END_CONDITION); 4534 params.add(Long.valueOf(endTime)); 4535 } 4536 } 4537 4538 /** 4539 * Appends the appropriate selection criteria related with the read mode.<p> 4540 * 4541 * @param projectId the id of the project of the resources 4542 * @param mode the selection mode 4543 * @param conditions buffer to append the selection criteria 4544 */ 4545 protected void prepareResourceCondition(CmsUUID projectId, int mode, StringBuffer conditions) { 4546 4547 if ((mode & CmsDriverManager.READMODE_ONLY_FOLDERS) > 0) { 4548 // C_READMODE_ONLY_FOLDERS: add condition to match only folders 4549 conditions.append(BEGIN_INCLUDE_CONDITION); 4550 conditions.append(m_sqlManager.readQuery(projectId, "C_RESOURCES_SELECT_ONLY_FOLDERS")); 4551 conditions.append(END_CONDITION); 4552 } else if ((mode & CmsDriverManager.READMODE_ONLY_FILES) > 0) { 4553 // C_READMODE_ONLY_FILES: add condition to match only files 4554 conditions.append(BEGIN_INCLUDE_CONDITION); 4555 conditions.append(m_sqlManager.readQuery(projectId, "C_RESOURCES_SELECT_ONLY_FILES")); 4556 conditions.append(END_CONDITION); 4557 } 4558 } 4559 4560 /** 4561 * Appends the appropriate selection criteria related with the resource state.<p> 4562 * 4563 * @param projectId the id of the project of the resources 4564 * @param state the resource state 4565 * @param mode the selection mode 4566 * @param conditions buffer to append the selection criteria 4567 * @param params list to append the selection parameters 4568 */ 4569 protected void prepareStateCondition( 4570 CmsUUID projectId, 4571 CmsResourceState state, 4572 int mode, 4573 StringBuffer conditions, 4574 List<Object> params) { 4575 4576 if (state != null) { 4577 if ((mode & CmsDriverManager.READMODE_EXCLUDE_STATE) > 0) { 4578 // C_READ_MODIFIED_STATES: add condition to match against any state but not given state 4579 conditions.append(BEGIN_EXCLUDE_CONDITION); 4580 } else { 4581 // otherwise add condition to match against given state if necessary 4582 conditions.append(BEGIN_INCLUDE_CONDITION); 4583 } 4584 conditions.append(m_sqlManager.readQuery(projectId, "C_RESOURCES_SELECT_BY_RESOURCE_STATE")); 4585 conditions.append(END_CONDITION); 4586 params.add(Integer.valueOf(state.getState())); 4587 params.add(Integer.valueOf(state.getState())); 4588 } 4589 } 4590 4591 /** 4592 * Appends the appropriate selection criteria related with the date of the last modification.<p> 4593 * 4594 * @param projectId the id of the project of the resources 4595 * @param startTime start of the time range 4596 * @param endTime end of the time range 4597 * @param conditions buffer to append the selection criteria 4598 * @param params list to append the selection parameters 4599 */ 4600 protected void prepareTimeRangeCondition( 4601 CmsUUID projectId, 4602 long startTime, 4603 long endTime, 4604 StringBuffer conditions, 4605 List<Object> params) { 4606 4607 if (startTime > 0L) { 4608 // READ_IGNORE_TIME: if NOT set, add condition to match last modified date against startTime 4609 conditions.append(BEGIN_INCLUDE_CONDITION); 4610 conditions.append(m_sqlManager.readQuery(projectId, "C_RESOURCES_SELECT_BY_DATE_LASTMODIFIED_AFTER")); 4611 conditions.append(END_CONDITION); 4612 params.add(Long.valueOf(startTime)); 4613 } 4614 4615 if (endTime > 0L) { 4616 // READ_IGNORE_TIME: if NOT set, add condition to match last modified date against endTime 4617 conditions.append(BEGIN_INCLUDE_CONDITION); 4618 conditions.append(m_sqlManager.readQuery(projectId, "C_RESOURCES_SELECT_BY_DATE_LASTMODIFIED_BEFORE")); 4619 conditions.append(END_CONDITION); 4620 params.add(Long.valueOf(endTime)); 4621 } 4622 } 4623 4624 /** 4625 * Appends the appropriate selection criteria related with the resource type.<p> 4626 * 4627 * @param projectId the id of the project of the resources 4628 * @param type the resource type 4629 * @param mode the selection mode 4630 * @param conditions buffer to append the selection criteria 4631 * @param params list to append the selection parameters 4632 */ 4633 protected void prepareTypeCondition( 4634 CmsUUID projectId, 4635 int type, 4636 int mode, 4637 StringBuffer conditions, 4638 List<Object> params) { 4639 4640 if (type != CmsDriverManager.READ_IGNORE_TYPE) { 4641 if ((mode & CmsDriverManager.READMODE_EXCLUDE_TYPE) > 0) { 4642 // C_READ_FILE_TYPES: add condition to match against any type, but not given type 4643 conditions.append(BEGIN_EXCLUDE_CONDITION); 4644 conditions.append(m_sqlManager.readQuery(projectId, "C_RESOURCES_SELECT_BY_RESOURCE_TYPE")); 4645 conditions.append(END_CONDITION); 4646 params.add(Integer.valueOf(type)); 4647 } else { 4648 //otherwise add condition to match against given type if necessary 4649 conditions.append(BEGIN_INCLUDE_CONDITION); 4650 conditions.append(m_sqlManager.readQuery(projectId, "C_RESOURCES_SELECT_BY_RESOURCE_TYPE")); 4651 conditions.append(END_CONDITION); 4652 params.add(Integer.valueOf(type)); 4653 } 4654 } 4655 } 4656 4657 /** 4658 * Appends the appropriate selection criteria related with the resource type.<p> 4659 * 4660 * @param projectId the id of the project of the resources 4661 * @param types the resource type id's 4662 * @param mode the selection mode 4663 * @param conditions buffer to append the selection criteria 4664 * @param params list to append the selection parameters 4665 */ 4666 protected void prepareTypesCondition( 4667 CmsUUID projectId, 4668 List<Integer> types, 4669 int mode, 4670 StringBuffer conditions, 4671 List<Object> params) { 4672 4673 if ((mode & CmsDriverManager.READMODE_EXCLUDE_TYPE) > 0) { 4674 // C_READ_FILE_TYPES: add condition to match against any type, but not given type 4675 conditions.append(BEGIN_EXCLUDE_CONDITION); 4676 conditions.append(m_sqlManager.readQuery(projectId, "C_RESOURCES_SELECT_BY_RESOURCE_TYPE")); 4677 conditions.append(END_CONDITION); 4678 params.add(Integer.valueOf(CmsDriverManager.READ_IGNORE_TYPE)); 4679 } else if (!((types == null) || types.isEmpty())) { 4680 //otherwise add condition to match against given type if necessary 4681 conditions.append(BEGIN_INCLUDE_CONDITION); 4682 Iterator<Integer> typeIt = types.iterator(); 4683 while (typeIt.hasNext()) { 4684 conditions.append(m_sqlManager.readQuery(projectId, "C_RESOURCES_SELECT_BY_RESOURCE_TYPE")); 4685 params.add(typeIt.next()); 4686 if (typeIt.hasNext()) { 4687 conditions.append(OR_CONDITION); 4688 } 4689 } 4690 conditions.append(END_CONDITION); 4691 } 4692 } 4693 4694 /** 4695 * Reads all resources inside a given project matching the criteria specified by parameter values.<p> 4696 * 4697 * Important: If {@link CmsDriverManager#READMODE_EXCLUDE_TREE} is true (or {@link CmsDriverManager#READMODE_INCLUDE_TREE} is false), 4698 * the provided parent String must be the UUID of the parent folder, NOT the parent folder path.<p> 4699 * 4700 * @param dbc the current database context 4701 * @param projectId the project id for matching resources 4702 * @param parentPath the path to the resource used as root of the searched subtree or {@link CmsDriverManager#READ_IGNORE_PARENT}, 4703 * {@link CmsDriverManager#READMODE_EXCLUDE_TREE} means to read immediate children only 4704 * @param types the resource types of matching resources or <code>null</code> (meaning inverted by {@link CmsDriverManager#READMODE_EXCLUDE_TYPE} 4705 * @param state the state of matching resources (meaning inverted by {@link CmsDriverManager#READMODE_EXCLUDE_STATE} or <code>null</code> to ignore 4706 * @param lastModifiedAfter the start of the time range for the last modification date of matching resources or READ_IGNORE_TIME 4707 * @param lastModifiedBefore the end of the time range for the last modification date of matching resources or READ_IGNORE_TIME 4708 * @param releasedAfter the start of the time range for the release date of matching resources 4709 * @param releasedBefore the end of the time range for the release date of matching resources 4710 * @param expiredAfter the start of the time range for the expire date of matching resources 4711 * @param expiredBefore the end of the time range for the expire date of matching resources 4712 * @param mode additional mode flags: 4713 * <ul> 4714 * <li>{@link CmsDriverManager#READMODE_INCLUDE_TREE} 4715 * <li>{@link CmsDriverManager#READMODE_EXCLUDE_TREE} 4716 * <li>{@link CmsDriverManager#READMODE_INCLUDE_PROJECT} 4717 * <li>{@link CmsDriverManager#READMODE_EXCLUDE_TYPE} 4718 * <li>{@link CmsDriverManager#READMODE_EXCLUDE_STATE} 4719 * </ul> 4720 * 4721 * @return a list of CmsResource objects matching the given criteria 4722 * 4723 * @throws CmsDataAccessException if something goes wrong 4724 */ 4725 protected List<CmsResource> readTypesInResourceTree( 4726 CmsDbContext dbc, 4727 CmsUUID projectId, 4728 String parentPath, 4729 List<Integer> types, 4730 CmsResourceState state, 4731 long lastModifiedAfter, 4732 long lastModifiedBefore, 4733 long releasedAfter, 4734 long releasedBefore, 4735 long expiredAfter, 4736 long expiredBefore, 4737 int mode) 4738 throws CmsDataAccessException { 4739 4740 List<CmsResource> result = new ArrayList<CmsResource>(); 4741 4742 StringBuffer conditions = new StringBuffer(); 4743 List<Object> params = new ArrayList<Object>(5); 4744 4745 // prepare the selection criteria 4746 prepareProjectCondition(projectId, mode, conditions, params); 4747 prepareResourceCondition(projectId, mode, conditions); 4748 prepareTypesCondition(projectId, types, mode, conditions, params); 4749 prepareTimeRangeCondition(projectId, lastModifiedAfter, lastModifiedBefore, conditions, params); 4750 prepareReleasedTimeRangeCondition(projectId, releasedAfter, releasedBefore, conditions, params); 4751 prepareExpiredTimeRangeCondition(projectId, expiredAfter, expiredBefore, conditions, params); 4752 preparePathCondition(projectId, parentPath, mode, conditions, params); 4753 prepareStateCondition(projectId, state, mode, conditions, params); 4754 4755 // now read matching resources within the subtree 4756 ResultSet res = null; 4757 PreparedStatement stmt = null; 4758 Connection conn = null; 4759 4760 try { 4761 conn = m_sqlManager.getConnection(dbc); 4762 StringBuffer queryBuf = new StringBuffer(256); 4763 queryBuf.append(m_sqlManager.readQuery(projectId, "C_RESOURCES_READ_TREE")); 4764 queryBuf.append(conditions); 4765 queryBuf.append(" "); 4766 queryBuf.append(m_sqlManager.readQuery(projectId, "C_RESOURCES_ORDER_BY_PATH")); 4767 stmt = m_sqlManager.getPreparedStatementForSql(conn, queryBuf.toString()); 4768 4769 for (int i = 0; i < params.size(); i++) { 4770 if (params.get(i) instanceof Integer) { 4771 stmt.setInt(i + 1, ((Integer)params.get(i)).intValue()); 4772 } else if (params.get(i) instanceof Long) { 4773 stmt.setLong(i + 1, ((Long)params.get(i)).longValue()); 4774 } else { 4775 stmt.setString(i + 1, (String)params.get(i)); 4776 } 4777 } 4778 4779 res = stmt.executeQuery(); 4780 while (res.next()) { 4781 CmsResource resource = createResource(res, projectId); 4782 result.add(resource); 4783 } 4784 4785 } catch (SQLException e) { 4786 throw new CmsDbSqlException( 4787 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 4788 e); 4789 } finally { 4790 m_sqlManager.closeAll(dbc, conn, stmt, res); 4791 } 4792 4793 return result; 4794 } 4795 4796 /** 4797 * Repairs broken links.<p> 4798 * 4799 * When a resource is created any relation pointing to it is updated to use the right id.<p> 4800 * 4801 * @param dbc the current database context 4802 * @param projectId the project id 4803 * @param structureId the structure id of the resource that may help to repair broken links 4804 * @param rootPath the path of the resource that may help to repair broken links 4805 * 4806 * @throws CmsDataAccessException if something goes wrong 4807 */ 4808 protected void repairBrokenRelations(CmsDbContext dbc, CmsUUID projectId, CmsUUID structureId, String rootPath) 4809 throws CmsDataAccessException { 4810 4811 PreparedStatement stmt = null; 4812 Connection conn = null; 4813 4814 try { 4815 conn = m_sqlManager.getConnection(dbc); 4816 stmt = m_sqlManager.getPreparedStatement(conn, projectId, "C_RELATIONS_REPAIR_BROKEN"); 4817 stmt.setString(1, structureId.toString()); 4818 stmt.setString(2, rootPath); 4819 stmt.executeUpdate(); 4820 } catch (SQLException e) { 4821 throw new CmsDbSqlException( 4822 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 4823 e); 4824 } finally { 4825 m_sqlManager.closeAll(dbc, conn, stmt, null); 4826 } 4827 } 4828 4829 /** 4830 * Updates broken links.<p> 4831 * 4832 * When a resource is deleted, then the relations pointing to 4833 * the deleted resource are set to the null uuid.<p> 4834 * 4835 * @param dbc the current database context 4836 * @param projectId the project id 4837 * @param rootPath the root path of the resource that has been deleted 4838 * 4839 * @throws CmsDataAccessException if something goes wrong 4840 */ 4841 protected void updateBrokenRelations(CmsDbContext dbc, CmsUUID projectId, String rootPath) 4842 throws CmsDataAccessException { 4843 4844 PreparedStatement stmt = null; 4845 Connection conn = null; 4846 try { 4847 try { 4848 conn = m_sqlManager.getConnection(dbc); 4849 stmt = m_sqlManager.getPreparedStatement(conn, projectId, "C_RELATIONS_UPDATE_BROKEN"); 4850 stmt.setString(1, rootPath); 4851 stmt.executeUpdate(); 4852 } finally { 4853 m_sqlManager.closeAll(dbc, conn, stmt, null); 4854 } 4855 4856 try { 4857 conn = m_sqlManager.getConnection(dbc); 4858 stmt = m_sqlManager.getPreparedStatement(conn, projectId, "C_RELATIONS_DELETE_BROKEN_LOCALE_RELATIONS"); 4859 stmt.setString(1, rootPath); 4860 stmt.executeUpdate(); 4861 } finally { 4862 m_sqlManager.closeAll(dbc, conn, stmt, null); 4863 } 4864 } catch (SQLException e) { 4865 throw new CmsDbSqlException( 4866 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 4867 e); 4868 } 4869 4870 } 4871 4872 /** 4873 * Wrap a SQL exception into a CmsDbSqlException.<p> 4874 * 4875 * @param stmt the used statement 4876 * @param e the exception 4877 * 4878 * @return the CmsDbSqlException 4879 */ 4880 protected CmsDbSqlException wrapException(PreparedStatement stmt, SQLException e) { 4881 4882 return new CmsDbSqlException( 4883 Messages.get().container(Messages.ERR_GENERIC_SQL_1, CmsDbSqlException.getErrorQuery(stmt)), 4884 e); 4885 } 4886 4887 /** 4888 * Creates a prepared statement by combining a base query with the generated SQL conditions for a given 4889 * URL name mapping filter.<p> 4890 * 4891 * @param conn the connection to use for creating the prepared statement 4892 * @param baseQuery the base query to which the conditions should be appended 4893 * @param filter the filter from which to generate the conditions 4894 * 4895 * @return the created prepared statement 4896 * 4897 * @throws SQLException if something goes wrong 4898 */ 4899 PreparedStatement getPreparedStatementForFilter(Connection conn, String baseQuery, CmsUrlNameMappingFilter filter) 4900 throws SQLException { 4901 4902 CmsPair<String, List<I_CmsPreparedStatementParameter>> conditionData = prepareUrlNameMappingConditions(filter); 4903 String whereClause = ""; 4904 if (!conditionData.getFirst().equals("")) { 4905 whereClause = " WHERE " + conditionData.getFirst(); 4906 } 4907 String query = baseQuery + whereClause; 4908 PreparedStatement stmt = m_sqlManager.getPreparedStatementForSql(conn, query); 4909 int counter = 1; 4910 for (I_CmsPreparedStatementParameter param : conditionData.getSecond()) { 4911 param.insertIntoStatement(stmt, counter); 4912 counter += 1; 4913 } 4914 return stmt; 4915 } 4916 4917 /** 4918 * Helper method to convert an alias filter to SQL conditions.<p> 4919 * 4920 * @param filter the alias filter 4921 * @return a pair containing a condition string and the parameters which are necessary for the conditions 4922 */ 4923 private CmsPair<String, List<String>> buildAliasConditions(CmsAliasFilter filter) { 4924 4925 List<String> conditions = new ArrayList<String>(); 4926 conditions.add("1 = 1"); 4927 List<String> conditionParams = new ArrayList<String>(); 4928 if (filter.getSiteRoot() != null) { 4929 conditions.add("site_root = ?"); 4930 conditionParams.add(filter.getSiteRoot()); 4931 } 4932 if (filter.getStructureId() != null) { 4933 conditions.add("structure_id = ?"); 4934 conditionParams.add(filter.getStructureId().toString()); 4935 } 4936 if (filter.getPath() != null) { 4937 conditions.add("path = ?"); 4938 conditionParams.add(filter.getPath()); 4939 } 4940 String conditionString = CmsStringUtil.listAsString(conditions, " AND "); 4941 return CmsPair.create(conditionString, conditionParams); 4942 } 4943 4944 /** 4945 * Helper method to prepare the SQL conditions for accessing rewrite aliases using a given filter.<p> 4946 * 4947 * @param filter the filter to use for rewrite aliases 4948 * 4949 * @return a pair consisting of an SQL condition string and a list of query parameters 4950 */ 4951 private CmsPair<String, List<Object>> prepareRewriteAliasConditions(CmsRewriteAliasFilter filter) { 4952 4953 List<String> conditions = new ArrayList<String>(); 4954 conditions.add("1 = 1"); 4955 List<Object> parameters = new ArrayList<Object>(); 4956 if (filter.getSiteRoot() != null) { 4957 parameters.add(filter.getSiteRoot()); 4958 conditions.add("SITE_ROOT = ?"); 4959 } 4960 if (filter.getId() != null) { 4961 parameters.add(filter.getId().toString()); 4962 conditions.add("ID = ?"); 4963 } 4964 return CmsPair.create(CmsStringUtil.listAsString(conditions, " AND "), parameters); 4965 } 4966 4967 /** 4968 * Replaces the %(PROJECT) macro inside a query with either ONLINE or OFFLINE, depending on the value 4969 * of a flag.<p> 4970 * 4971 * We use this instead of the ${PROJECT} replacement mechanism when we need explicit control over the 4972 * project, and don't want to implicitly use the project of the DB context.<p> 4973 * 4974 * @param query the query in which the macro should be replaced 4975 * @param online if true, the macro will be replaced with "ONLINE", else "OFFLINE" 4976 * 4977 * @return the query with the replaced macro 4978 */ 4979 private String replaceProject(String query, boolean online) { 4980 4981 return query.replace("%(PROJECT)", online ? ONLINE : OFFLINE); 4982 } 4983 4984}