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