]> source.dussan.org Git - sonarqube.git/blob
5a714a4c7da2f2e6994a4dc04030b4e6b0a86ef6
[sonarqube.git] /
1 /*
2  * SonarQube
3  * Copyright (C) 2009-2017 SonarSource SA
4  * mailto:info AT sonarsource DOT com
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 3 of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19  */
20 package org.sonar.server.edition;
21
22 import com.google.common.collect.ImmutableSet;
23 import java.util.Arrays;
24 import java.util.Map;
25 import java.util.Optional;
26 import org.picocontainer.Startable;
27 import org.sonar.db.DbClient;
28 import org.sonar.db.DbSession;
29 import org.sonar.db.property.InternalPropertiesDao;
30
31 import static com.google.common.base.Preconditions.checkArgument;
32 import static com.google.common.base.Preconditions.checkState;
33 import static java.util.Objects.requireNonNull;
34 import static java.util.Optional.empty;
35 import static org.sonar.server.edition.EditionManagementState.PendingStatus.AUTOMATIC_IN_PROGRESS;
36 import static org.sonar.server.edition.EditionManagementState.PendingStatus.AUTOMATIC_READY;
37 import static org.sonar.server.edition.EditionManagementState.PendingStatus.MANUAL_IN_PROGRESS;
38 import static org.sonar.server.edition.EditionManagementState.PendingStatus.NONE;
39
40 public class StandaloneEditionManagementStateImpl implements MutableEditionManagementState, Startable {
41   private static final String CURRENT_EDITION_KEY = "currentEditionKey";
42   private static final String PENDING_INSTALLATION_STATUS = "pendingInstallStatus";
43   private static final String PENDING_EDITION_KEY = "pendingEditionKey";
44   private static final String PENDING_LICENSE = "pendingLicense";
45
46   private final DbClient dbClient;
47   private String currentEditionKey;
48   private PendingStatus pendingInstallationStatus;
49   private String pendingEditionKey;
50   private String pendingLicense;
51
52   public StandaloneEditionManagementStateImpl(DbClient dbClient) {
53     this.dbClient = dbClient;
54   }
55
56   @Override
57   public void start() {
58     try (DbSession dbSession = dbClient.openSession(false)) {
59       // load current state value
60       Map<String, Optional<String>> internalPropertyValues = dbClient.internalPropertiesDao().selectByKeys(dbSession,
61         ImmutableSet.of(CURRENT_EDITION_KEY, PENDING_INSTALLATION_STATUS, PENDING_EDITION_KEY, PENDING_LICENSE));
62       this.currentEditionKey = internalPropertyValues.getOrDefault(CURRENT_EDITION_KEY, empty())
63         .map(StandaloneEditionManagementStateImpl::emptyToNull)
64         .orElse(null);
65       this.pendingInstallationStatus = internalPropertyValues.getOrDefault(PENDING_INSTALLATION_STATUS, empty())
66         .map(StandaloneEditionManagementStateImpl::emptyToNull)
67         .map(PendingStatus::valueOf)
68         .orElse(NONE);
69       this.pendingEditionKey = internalPropertyValues.getOrDefault(PENDING_EDITION_KEY, empty())
70         .map(StandaloneEditionManagementStateImpl::emptyToNull)
71         .orElse(null);
72       this.pendingLicense = internalPropertyValues.getOrDefault(PENDING_LICENSE, empty())
73         .map(StandaloneEditionManagementStateImpl::emptyToNull)
74         .orElse(null);
75     }
76   }
77
78   @Override
79   public void stop() {
80     // nothing to do
81   }
82
83   @Override
84   public Optional<String> getCurrentEditionKey() {
85     ensureStarted();
86     return Optional.ofNullable(currentEditionKey);
87   }
88
89   @Override
90   public PendingStatus getPendingInstallationStatus() {
91     ensureStarted();
92     return pendingInstallationStatus;
93   }
94
95   @Override
96   public Optional<String> getPendingEditionKey() {
97     ensureStarted();
98     return Optional.ofNullable(pendingEditionKey);
99   }
100
101   @Override
102   public Optional<String> getPendingLicense() {
103     ensureStarted();
104     return Optional.ofNullable(pendingLicense);
105   }
106
107   @Override
108   public synchronized PendingStatus startAutomaticInstall(License license) {
109     ensureStarted();
110     checkLicense(license);
111     changeStatusToFrom(AUTOMATIC_IN_PROGRESS, NONE);
112     this.pendingLicense = license.getContent();
113     this.pendingEditionKey = license.getEditionKey();
114     persistProperties();
115     return this.pendingInstallationStatus;
116   }
117
118   @Override
119   public synchronized PendingStatus startManualInstall(License license) {
120     ensureStarted();
121     checkLicense(license);
122     changeStatusToFrom(MANUAL_IN_PROGRESS, NONE);
123     this.pendingLicense = license.getContent();
124     this.pendingEditionKey = license.getEditionKey();
125     this.pendingInstallationStatus = MANUAL_IN_PROGRESS;
126     persistProperties();
127     return this.pendingInstallationStatus;
128   }
129
130   @Override
131   public synchronized PendingStatus newEditionWithoutInstall(String newEditionKey) {
132     ensureStarted();
133     requireNonNull(newEditionKey, "newEditionKey can't be null");
134     checkArgument(!newEditionKey.isEmpty(), "newEditionKey can't be empty");
135     changeStatusToFrom(NONE, NONE);
136     this.currentEditionKey = newEditionKey;
137     persistProperties();
138     return this.pendingInstallationStatus;
139   }
140
141   @Override
142   public synchronized PendingStatus automaticInstallReady() {
143     ensureStarted();
144     changeStatusToFrom(AUTOMATIC_READY, AUTOMATIC_IN_PROGRESS);
145     persistProperties();
146     return this.pendingInstallationStatus;
147   }
148
149   @Override
150   public synchronized PendingStatus finalizeInstallation() {
151     ensureStarted();
152     changeStatusToFrom(NONE, AUTOMATIC_READY, MANUAL_IN_PROGRESS);
153
154     this.pendingInstallationStatus = NONE;
155     this.currentEditionKey = this.pendingEditionKey;
156     this.pendingEditionKey = null;
157     this.pendingLicense = null;
158     persistProperties();
159     return this.pendingInstallationStatus;
160   }
161
162   private void ensureStarted() {
163     checkState(pendingInstallationStatus != null, "%s is not started", getClass().getSimpleName());
164   }
165
166   private void changeStatusToFrom(PendingStatus newStatus, PendingStatus... validPendingStatuses) {
167     checkState(Arrays.stream(validPendingStatuses).anyMatch(s -> s == pendingInstallationStatus),
168       "Can't move to %s when status is %s (should be any of %s)",
169       newStatus, pendingInstallationStatus, Arrays.toString(validPendingStatuses));
170     this.pendingInstallationStatus = newStatus;
171   }
172
173   private void persistProperties() {
174     try (DbSession dbSession = dbClient.openSession(false)) {
175       InternalPropertiesDao internalPropertiesDao = dbClient.internalPropertiesDao();
176       if (pendingInstallationStatus == NONE) {
177         internalPropertiesDao.saveAsEmpty(dbSession, PENDING_EDITION_KEY);
178         internalPropertiesDao.saveAsEmpty(dbSession, PENDING_LICENSE);
179       } else {
180         internalPropertiesDao.save(dbSession, PENDING_EDITION_KEY, pendingEditionKey);
181         internalPropertiesDao.save(dbSession, PENDING_LICENSE, pendingLicense);
182       }
183       if (currentEditionKey == null) {
184         internalPropertiesDao.saveAsEmpty(dbSession, CURRENT_EDITION_KEY);
185       } else {
186         internalPropertiesDao.save(dbSession, CURRENT_EDITION_KEY, currentEditionKey);
187       }
188       internalPropertiesDao.save(dbSession, PENDING_INSTALLATION_STATUS, pendingInstallationStatus.name());
189       dbSession.commit();
190     }
191   }
192
193   private static void checkLicense(License license) {
194     requireNonNull(license, "license can't be null");
195   }
196
197   private static String emptyToNull(String s) {
198     return s.isEmpty() ? null : s;
199   }
200 }