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