001 /* 002 * Sonar, open source software quality management tool. 003 * Copyright (C) 2009 SonarSource SA 004 * mailto:contact AT sonarsource DOT com 005 * 006 * Sonar is free software; you can redistribute it and/or 007 * modify it under the terms of the GNU Lesser General Public 008 * License as published by the Free Software Foundation; either 009 * version 3 of the License, or (at your option) any later version. 010 * 011 * Sonar is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 014 * Lesser General Public License for more details. 015 * 016 * You should have received a copy of the GNU Lesser General Public 017 * License along with Sonar; if not, write to the Free Software 018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 019 */ 020 package org.sonar.batch; 021 022 import org.slf4j.Logger; 023 import org.slf4j.LoggerFactory; 024 import org.sonar.api.batch.Purge; 025 import org.sonar.api.batch.PurgeContext; 026 import org.sonar.api.batch.SensorContext; 027 import org.sonar.api.database.DatabaseSession; 028 import org.sonar.api.database.model.Snapshot; 029 import org.sonar.api.resources.Project; 030 import org.sonar.api.utils.ServerHttpClient; 031 import org.sonar.api.utils.TimeProfiler; 032 033 import javax.persistence.Query; 034 035 public class FinalizeSnapshotsJob implements CoreJob { 036 037 private DatabaseSession session; 038 private Purge[] purges; 039 private ServerHttpClient server; 040 private Snapshot snapshot; 041 042 public FinalizeSnapshotsJob(ServerHttpClient server, DatabaseSession session, Purge[] purges, Snapshot snapshot) { 043 this.session = session; 044 this.purges = purges; 045 this.server = server; 046 this.snapshot = snapshot; 047 } 048 049 public void execute(Project project, SensorContext context) { 050 if (shouldExecuteOn(project)) { 051 Snapshot previousLastSnapshot = getPreviousLastSnapshot(snapshot); 052 updateFlags(snapshot, previousLastSnapshot); 053 purge(snapshot, previousLastSnapshot); 054 } 055 } 056 057 private boolean shouldExecuteOn(Project project) { 058 return project.isRoot(); 059 } 060 061 private Snapshot getPreviousLastSnapshot(Snapshot snapshot) { 062 Query query = session.createQuery( 063 "SELECT s FROM " + Snapshot.class.getSimpleName() + " s " + 064 "WHERE s.last=true AND s.resourceId=:resourceId"); 065 query.setParameter("resourceId", snapshot.getResourceId()); 066 return session.getSingleResult(query, null); 067 } 068 069 070 private void updateFlags(Snapshot rootSnapshot, Snapshot previousLastSnapshot) { 071 if (previousLastSnapshot != null && previousLastSnapshot.getCreatedAt().before(rootSnapshot.getCreatedAt())) { 072 setFlags(previousLastSnapshot, false, null); 073 } 074 075 boolean isLast = (previousLastSnapshot == null || previousLastSnapshot.getCreatedAt().before(rootSnapshot.getCreatedAt())); 076 setFlags(rootSnapshot, isLast, Snapshot.STATUS_PROCESSED); 077 LoggerFactory.getLogger(getClass()).info("ANALYSIS SUCCESSFUL, you can browse {}", server.getUrl()); 078 } 079 080 private void setFlags(Snapshot snapshot, boolean last, String status) { 081 String hql = "UPDATE " + Snapshot.class.getSimpleName() + " SET last=:last"; 082 if (status != null) { 083 hql += ", status=:status "; 084 } 085 hql += " WHERE root_snapshot_id=:rootId OR id=:rootId OR (path LIKE :path AND root_snapshot_id=:pathRootId)"; 086 087 Query query = session.createQuery(hql); 088 if (status != null) { 089 query.setParameter("status", status); 090 snapshot.setStatus(status); 091 } 092 query.setParameter("last", last); 093 query.setParameter("rootId", snapshot.getId()); 094 query.setParameter("path", snapshot.getPath() + snapshot.getId() + ".%"); 095 query.setParameter("pathRootId", (snapshot.getRootId() == null ? snapshot.getId() : snapshot.getRootId())); 096 query.executeUpdate(); 097 session.commit(); 098 099 snapshot.setLast(last); 100 } 101 102 private void purge(Snapshot currentSnapshot, Snapshot previousLastSnapshot) { 103 final Logger logger = LoggerFactory.getLogger(FinalizeSnapshotsJob.class); 104 TimeProfiler profiler = new TimeProfiler(logger).start("Database optimization"); 105 PurgeContext context = createPurgeContext(currentSnapshot, previousLastSnapshot); 106 logger.debug("Snapshots to purge: " + context); 107 for (Purge purge : purges) { 108 logger.debug("Executing {}...", purge.getClass().getName()); 109 purge.purge(context); 110 } 111 profiler.stop(); 112 } 113 114 private PurgeContext createPurgeContext(Snapshot currentSnapshot, Snapshot previousLastSnapshot) { 115 PurgeContext context = new PurgeContext(currentSnapshot); 116 if (previousLastSnapshot != null && previousLastSnapshot.getCreatedAt().before(currentSnapshot.getCreatedAt())) { 117 context.setLastSnapshotId(previousLastSnapshot.getId()); 118 } 119 return context; 120 } 121 122 }