]> source.dussan.org Git - sonarqube.git/blob
b9c691df4221d5fa568d8828bdead130b435766e
[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 import static org.sonar.server.edition.EditionManagementState.PendingStatus.UNINSTALL_IN_PROGRESS;
40
41 public class StandaloneEditionManagementStateImpl implements MutableEditionManagementState, Startable {
42   private static final String CURRENT_EDITION_KEY = "currentEditionKey";
43   private static final String PENDING_INSTALLATION_STATUS = "pendingInstallStatus";
44   private static final String PENDING_EDITION_KEY = "pendingEditionKey";
45   private static final String PENDING_LICENSE = "pendingLicense";
46
47   private final DbClient dbClient;
48   private String currentEditionKey;
49   private PendingStatus pendingInstallationStatus;
50   private String pendingEditionKey;
51   private String pendingLicense;
52
53   public StandaloneEditionManagementStateImpl(DbClient dbClient) {
54     this.dbClient = dbClient;
55   }
56
57   @Override
58   public void start() {
59     try (DbSession dbSession = dbClient.openSession(false)) {
60       // load current state value
61       Map<String, Optional<String>> internalPropertyValues = dbClient.internalPropertiesDao().selectByKeys(dbSession,
62         ImmutableSet.of(CURRENT_EDITION_KEY, PENDING_INSTALLATION_STATUS, PENDING_EDITION_KEY, PENDING_LICENSE));
63       this.currentEditionKey = internalPropertyValues.getOrDefault(CURRENT_EDITION_KEY, empty())
64         .map(StandaloneEditionManagementStateImpl::emptyToNull)
65         .orElse(null);
66       this.pendingInstallationStatus = internalPropertyValues.getOrDefault(PENDING_INSTALLATION_STATUS, empty())
67         .map(StandaloneEditionManagementStateImpl::emptyToNull)
68         .map(PendingStatus::valueOf)
69         .orElse(NONE);
70       this.pendingEditionKey = internalPropertyValues.getOrDefault(PENDING_EDITION_KEY, empty())
71         .map(StandaloneEditionManagementStateImpl::emptyToNull)
72         .orElse(null);
73       this.pendingLicense = internalPropertyValues.getOrDefault(PENDING_LICENSE, empty())
74         .map(StandaloneEditionManagementStateImpl::emptyToNull)
75         .orElse(null);
76     }
77   }
78
79   @Override
80   public void stop() {
81     // nothing to do
82   }
83
84   @Override
85   public Optional<String> getCurrentEditionKey() {
86     ensureStarted();
87     return Optional.ofNullable(currentEditionKey);
88   }
89
90   @Override
91   public PendingStatus getPendingInstallationStatus() {
92     ensureStarted();
93     return pendingInstallationStatus;
94   }
95
96   @Override
97   public Optional<String> getPendingEditionKey() {
98     ensureStarted();
99     return Optional.ofNullable(pendingEditionKey);
100   }
101
102   @Override
103   public Optional<String> getPendingLicense() {
104     ensureStarted();
105     return Optional.ofNullable(pendingLicense);
106   }
107
108   @Override
109   public synchronized PendingStatus startAutomaticInstall(License license) {
110     ensureStarted();
111     checkLicense(license);
112     changeStatusToFrom(AUTOMATIC_IN_PROGRESS, NONE);
113     this.pendingLicense = license.getContent();
114     this.pendingEditionKey = license.getEditionKey();
115     persistProperties();
116     return this.pendingInstallationStatus;
117   }
118
119   @Override
120   public synchronized PendingStatus startManualInstall(License license) {
121     ensureStarted();
122     checkLicense(license);
123     changeStatusToFrom(MANUAL_IN_PROGRESS, NONE);
124     this.pendingLicense = license.getContent();
125     this.pendingEditionKey = license.getEditionKey();
126     this.pendingInstallationStatus = MANUAL_IN_PROGRESS;
127     persistProperties();
128     return this.pendingInstallationStatus;
129   }
130
131   @Override
132   public synchronized PendingStatus newEditionWithoutInstall(String newEditionKey) {
133     ensureStarted();
134     requireNonNull(newEditionKey, "newEditionKey can't be null");
135     checkArgument(!newEditionKey.isEmpty(), "newEditionKey can't be empty");
136     changeStatusToFrom(NONE, NONE);
137     this.currentEditionKey = newEditionKey;
138     persistProperties();
139     return this.pendingInstallationStatus;
140   }
141
142   @Override
143   public synchronized PendingStatus automaticInstallReady() {
144     ensureStarted();
145     changeStatusToFrom(AUTOMATIC_READY, AUTOMATIC_IN_PROGRESS);
146     persistProperties();
147     return this.pendingInstallationStatus;
148   }
149
150   @Override
151   public synchronized PendingStatus finalizeInstallation() {
152     ensureStarted();
153     changeStatusToFrom(NONE, AUTOMATIC_READY, MANUAL_IN_PROGRESS, UNINSTALL_IN_PROGRESS);
154
155     this.pendingInstallationStatus = NONE;
156     this.currentEditionKey = this.pendingEditionKey;
157     this.pendingEditionKey = null;
158     this.pendingLicense = null;
159     persistProperties();
160     return this.pendingInstallationStatus;
161   }
162
163   @Override
164   public synchronized PendingStatus uninstall() {
165     ensureStarted();
166     changeStatusToFrom(UNINSTALL_IN_PROGRESS, NONE);
167     checkState(currentEditionKey != null, "There is no edition currently installed");
168
169     this.pendingInstallationStatus = UNINSTALL_IN_PROGRESS;
170     this.pendingEditionKey = null;
171     this.pendingLicense = null;
172     this.currentEditionKey = null;
173     persistProperties();
174     return this.pendingInstallationStatus;
175   }
176
177   private void ensureStarted() {
178     checkState(pendingInstallationStatus != null, "%s is not started", getClass().getSimpleName());
179   }
180
181   private void changeStatusToFrom(PendingStatus newStatus, PendingStatus... validPendingStatuses) {
182     checkState(Arrays.stream(validPendingStatuses).anyMatch(s -> s == pendingInstallationStatus),
183       "Can't move to %s when status is %s (should be any of %s)",
184       newStatus, pendingInstallationStatus, Arrays.toString(validPendingStatuses));
185     this.pendingInstallationStatus = newStatus;
186   }
187
188   private void persistProperties() {
189     try (DbSession dbSession = dbClient.openSession(false)) {
190       InternalPropertiesDao internalPropertiesDao = dbClient.internalPropertiesDao();
191       if (pendingInstallationStatus == NONE || pendingInstallationStatus == UNINSTALL_IN_PROGRESS) {
192         internalPropertiesDao.saveAsEmpty(dbSession, PENDING_EDITION_KEY);
193         internalPropertiesDao.saveAsEmpty(dbSession, PENDING_LICENSE);
194       } else {
195         internalPropertiesDao.save(dbSession, PENDING_EDITION_KEY, pendingEditionKey);
196         internalPropertiesDao.save(dbSession, PENDING_LICENSE, pendingLicense);
197       }
198       if (currentEditionKey == null) {
199         internalPropertiesDao.saveAsEmpty(dbSession, CURRENT_EDITION_KEY);
200       } else {
201         internalPropertiesDao.save(dbSession, CURRENT_EDITION_KEY, currentEditionKey);
202       }
203       internalPropertiesDao.save(dbSession, PENDING_INSTALLATION_STATUS, pendingInstallationStatus.name());
204       dbSession.commit();
205     }
206   }
207
208   private static void checkLicense(License license) {
209     requireNonNull(license, "license can't be null");
210   }
211
212   private static String emptyToNull(String s) {
213     return s.isEmpty() ? null : s;
214   }
215 }