1 23 24 package org.apache.slide.store.impl.rdbms; 25 26 import java.sql.Connection ; 27 import java.sql.PreparedStatement ; 28 import java.sql.ResultSet ; 29 import java.sql.SQLException ; 30 31 import org.apache.slide.common.Service; 32 import org.apache.slide.common.ServiceAccessException; 33 import org.apache.slide.common.Uri; 34 import org.apache.slide.content.NodeRevisionDescriptor; 35 import org.apache.slide.content.NodeRevisionNumber; 36 import org.apache.slide.lock.LockTokenNotFoundException; 37 import org.apache.slide.lock.NodeLock; 38 import org.apache.slide.macro.ConflictException; 39 import org.apache.slide.security.NodePermission; 40 import org.apache.slide.structure.ObjectNode; 41 import org.apache.slide.structure.ObjectNotFoundException; 42 import org.apache.slide.util.logger.Logger; 43 44 56 57 public class PostgresRDBMSAdapter extends StandardRDBMSAdapter implements SequenceAdapter { 58 59 protected static String LOG_CHANNEL = 60 PostgresRDBMSAdapter.class.getName(); 61 62 protected static String normalizeSequenceName(String sequenceName) { 63 return sequenceName.replace('-', '_').toUpperCase() + "_SEQ"; 64 } 65 66 public PostgresRDBMSAdapter(Service service, Logger logger) { 67 super(service, logger); 68 } 69 70 public void removeObject(Connection connection, Uri uri, ObjectNode object) 71 throws ServiceAccessException, ObjectNotFoundException { 72 PreparedStatement statement = null; 73 try { 74 75 clearBinding(connection, uri); 76 77 try { 79 statement = 80 connection.prepareStatement( 81 "delete from LINKS where LINKS.URI_ID = URI.URI_ID and URI.URI_STRING = ?"); 82 statement.setString(1, uri.toString()); 83 statement.executeUpdate(); 84 } finally { 85 close(statement); 86 } 87 try { 90 statement = 91 connection.prepareStatement( 92 "delete from VERSION_HISTORY where VERSION_HISTORY.URI_ID = URI.URI_ID and URI.URI_STRING = ?"); 93 statement.setString(1, uri.toString()); 94 statement.executeUpdate(); 95 } finally { 96 close(statement); 97 } 98 try { 100 statement = 101 connection.prepareStatement( 102 "delete from VERSION where VERSION.URI_ID = URI.URI_ID and URI.URI_STRING = ?"); 103 statement.setString(1, uri.toString()); 104 statement.executeUpdate(); 105 } finally { 106 close(statement); 107 } 108 try { 110 statement = 111 connection.prepareStatement( 112 "delete from OBJECT where OBJECT.URI_ID = URI.URI_ID and URI.URI_STRING = ?"); 113 statement.setString(1, uri.toString()); 114 statement.executeUpdate(); 115 } finally { 116 close(statement); 117 } 118 try { 120 statement = 121 connection.prepareStatement( 122 "delete from URI where URI_STRING = ?"); 123 statement.setString(1, uri.toString()); 124 statement.executeUpdate(); 125 } finally { 126 close(statement); 127 } 128 } catch (SQLException e) { 129 getLogger().log(e, LOG_CHANNEL, Logger.ERROR); 130 throw new ServiceAccessException(service, e); 131 } 132 } 133 134 public void removeRevisionContent( 135 Connection connection, 136 Uri uri, 137 NodeRevisionDescriptor revisionDescriptor) 138 throws ServiceAccessException { 139 try { 140 PreparedStatement statement = null; 141 try { 142 statement = 143 connection.prepareStatement( 144 "delete from VERSION_CONTENT where VERSION_CONTENT.VERSION_ID = VERSION_HISTORY.VERSION_ID and VERSION_HISTORY.REVISION_NO = ? and VERSION_HISTORY.URI_ID=URI.URI_ID AND URI.URI_STRING=?"); 145 statement.setString( 146 1, 147 revisionDescriptor.getRevisionNumber().toString()); 148 statement.setString(2, uri.toString()); 149 statement.executeUpdate(); 150 } finally { 151 close(statement); 152 } 153 } catch (Exception e) { 154 getLogger().log(e, LOG_CHANNEL, Logger.ERROR); 155 throw new ServiceAccessException(service, e); 156 } 157 } 158 159 public void removeRevisionDescriptor( 160 Connection connection, 161 Uri uri, 162 NodeRevisionNumber revisionNumber) 163 throws ServiceAccessException { 164 PreparedStatement statement = null; 165 try { 166 try { 167 statement = 168 connection.prepareStatement( 169 "delete from VERSION_LABELS where VERSION_LABELS.VERSION_ID = VERSION_HISTORY.VERSION_ID and VERSION_HISTORY.REVISION_NO = ? and VERSION_HISTORY.URI_ID = URI.URI_ID AND URI.URI_STRING = ?"); 170 statement.setString(1, revisionNumber.toString()); 171 statement.setString(2, uri.toString()); 172 statement.executeUpdate(); 173 } finally { 174 close(statement); 175 } 176 try { 177 statement = 178 connection.prepareStatement( 179 "delete from PROPERTIES where PROPERTIES.VERSION_ID = VERSION_HISTORY.VERSION_ID and VERSION_HISTORY.REVISION_NO = ? and VERSION_HISTORY.URI_ID = URI.URI_ID AND URI.URI_STRING = ?"); 180 statement.setString(1, revisionNumber.toString()); 181 statement.setString(2, uri.toString()); 182 statement.executeUpdate(); 183 } finally { 184 close(statement); 185 } 186 } catch (SQLException e) { 187 getLogger().log(e, LOG_CHANNEL, Logger.ERROR); 188 throw new ServiceAccessException(service, e); 189 } 190 } 191 192 public void removeRevisionDescriptors(Connection connection, Uri uri) throws ServiceAccessException { 193 PreparedStatement statement = null; 194 try { 195 196 statement = 197 connection.prepareStatement( 198 "delete from VERSION_PREDS where VERSION_PREDS.VERSION_ID = VERSION_HISTORY.VERSION_ID and VERSION_HISTORY.URI_ID = URI.URI_ID and URI.URI_STRING = ?"); 199 statement.setString(1, uri.toString()); 200 statement.executeUpdate(); 201 } catch (SQLException e) { 202 throw createException(e, uri.toString()); 203 } finally { 204 close(statement); 205 } 206 } 207 208 public void removeLock(Connection connection, Uri uri, NodeLock lock) 209 throws ServiceAccessException, LockTokenNotFoundException { 210 PreparedStatement statement = null; 211 try { 212 try { 213 statement = 214 connection.prepareStatement( 215 "delete from LOCKS where LOCK_ID = URI.URI_ID and URI.URI_STRING=?"); 216 statement.setString(1, lock.getLockId()); 217 statement.executeUpdate(); 218 } finally { 219 close(statement); 220 } 221 try { 222 statement = 223 connection.prepareStatement( 224 "delete from URI where URI_STRING=?"); 225 statement.setString(1, lock.getLockId()); 226 statement.executeUpdate(); 227 } finally { 228 close(statement); 229 } 230 } catch (SQLException e) { 231 getLogger().log(e, LOG_CHANNEL, Logger.ERROR); 232 throw new ServiceAccessException(service, e); 233 } 234 } 235 236 public void revokePermission( 237 Connection connection, 238 Uri uri, 239 NodePermission permission) 240 throws ServiceAccessException { 241 if (permission == null) return; 242 PreparedStatement statement = null; 243 try { 244 NodeRevisionNumber revisionNumber = permission.getRevisionNumber(); 245 statement = 246 connection.prepareStatement( 247 "delete from PERMISSIONS, URI ou, URI su, URI au where OBJECT_ID = ou.URI_ID and ou.URI_STRING = ? and SUBJECT_ID = su.URI_ID and su.URI_STRING = ? and ACTION_ID = au.URI_ID and au.URI_STRING = ? and VERSION_NO = ?"); 248 statement.setString(1, permission.getObjectUri()); 249 statement.setString(2, permission.getSubjectUri()); 250 statement.setString(3, permission.getActionUri()); 251 statement.setString(3, revisionNumber.toString()); 252 statement.executeUpdate(); 253 } catch (SQLException e) { 254 getLogger().log(e, LOG_CHANNEL, Logger.ERROR); 255 throw new ServiceAccessException(service, e); 256 } finally { 257 close(statement); 258 } 259 } 260 261 public void revokePermissions(Connection connection, Uri uri) 262 throws ServiceAccessException { 263 PreparedStatement statement = null; 264 try { 265 statement = 266 connection.prepareStatement( 267 "delete from PERMISSIONS where PERMISSIONS.OBJECT_ID = URI.URI_ID and URI.URI_STRING = ?"); 268 statement.setString(1, uri.toString()); 269 statement.executeUpdate(); 270 } catch (SQLException e) { 271 getLogger().log(e, LOG_CHANNEL, Logger.ERROR); 272 throw new ServiceAccessException(service, e); 273 } finally { 274 close(statement); 275 } 276 } 277 278 protected void clearBinding(Connection connection, Uri uri) 279 throws ServiceAccessException, ObjectNotFoundException, SQLException { 280 PreparedStatement statement = null; 281 282 284 286 try { 287 statement = 288 connection.prepareStatement( 289 "delete from BINDING where (BINDING.URI_ID = URI.URI_ID and URI.URI_STRING = ?) "); 290 statement.setString(1, uri.toString()); 292 statement.executeUpdate(); 294 } finally { 295 close(statement); 296 } 297 298 try { 299 statement = 300 connection.prepareStatement( 301 "delete from PARENT_BINDING where PARENT_BINDING.URI_ID = URI.URI_ID and URI.URI_STRING = ?"); 302 statement.setString(1, uri.toString()); 304 statement.executeUpdate(); 306 } finally { 307 close(statement); 308 } 309 } 310 311 protected ServiceAccessException createException( 312 SQLException e, 313 String uri) { 314 316 317 String sqlstate = e.getSQLState(); 318 319 if (sqlstate != null) { 320 if (sqlstate.startsWith("23")) { 321 getLogger().log(e.getErrorCode() + ": Deadlock resolved on " + uri, 322 LOG_CHANNEL, Logger.WARNING); 323 return new ServiceAccessException(service, new ConflictException(uri)); 324 } else if (sqlstate.startsWith("40")) { 325 getLogger().log( 326 e.getErrorCode() + ": Deadlock resolved on " + uri, 327 LOG_CHANNEL, 328 Logger.WARNING); 329 return new ServiceAccessException(service, new ConflictException(uri)); 330 } else { 331 getLogger().log( 332 "SQL error " 333 + e.getErrorCode() 334 + " on " 335 + uri 336 + ": " 337 + e.getMessage(), 338 LOG_CHANNEL, 339 Logger.ERROR); 340 341 return new ServiceAccessException(service, e); 342 } 343 } 344 else { 345 return super.createException(e, uri); 346 } 347 } 348 349 public boolean isSequenceSupported(Connection conn) { 350 return true; 351 } 352 353 public boolean createSequence(Connection conn, String sequenceName) throws ServiceAccessException { 354 355 String query = "CREATE SEQUENCE " + normalizeSequenceName(sequenceName); 356 357 PreparedStatement statement = null; 358 359 try { 360 statement = conn.prepareStatement(query); 361 statement.executeUpdate(); 362 return true; 363 } catch (SQLException e) { 364 throw new ServiceAccessException(service, e); 365 } finally { 366 close(statement); 367 } 368 369 } 370 371 public long nextSequenceValue(Connection conn, String sequenceName) throws ServiceAccessException { 372 String selectQuery = "SELECT nextval('" + normalizeSequenceName(sequenceName)+"');"; 373 374 PreparedStatement selectStatement = null; 375 ResultSet res = null; 376 377 try { 378 selectStatement = conn.prepareStatement(selectQuery); 379 res = selectStatement.executeQuery(); 380 if (!res.next()) { 381 throw new ServiceAccessException(service, "Could not increment sequence " + sequenceName); 382 } 383 long value = res.getLong(1); 384 return value; 385 } catch (SQLException e) { 386 throw new ServiceAccessException(service, e); 387 } finally { 388 close(selectStatement, res); 389 } 390 } 391 392 public boolean sequenceExists(Connection conn, String sequenceName) throws ServiceAccessException { 393 394 PreparedStatement selectStatement = null; 395 ResultSet res = null; 396 397 try { 398 selectStatement = conn.prepareStatement("SELECT * FROM " + normalizeSequenceName(sequenceName)); 399 res = selectStatement.executeQuery(); 400 return true; 401 } catch (SQLException e) { 402 return false; 403 } finally { 404 close(selectStatement, res); 405 } 406 } 407 408 protected String convertRevisionNumberToComparable(String revisioNumber) { 409 return "cast(split_part(" 410 + revisioNumber 411 + ", '.', 1) as numeric), cast(split_part(" 412 + revisioNumber 413 + ", '.', 2) as numeric)"; 414 } 415 416 } 417 | Popular Tags |