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 }