]> source.dussan.org Git - sonarqube.git/blob
1ca7eb3e62f38561af33ce58cf8d6d840daed825
[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.Map;
24 import java.util.Optional;
25 import org.picocontainer.Startable;
26 import org.sonar.db.DbClient;
27 import org.sonar.db.DbSession;
28 import org.sonar.db.property.InternalPropertiesDao;
29
30 import static com.google.common.base.Preconditions.checkArgument;
31 import static com.google.common.base.Preconditions.checkState;
32 import static java.util.Objects.requireNonNull;
33 import static java.util.Optional.empty;
34 import static org.sonar.server.edition.EditionManagementState.PendingStatus.AUTOMATIC_IN_PROGRESS;
35 import static org.sonar.server.edition.EditionManagementState.PendingStatus.AUTOMATIC_READY;
36 import static org.sonar.server.edition.EditionManagementState.PendingStatus.MANUAL_IN_PROGRESS;
37 import static org.sonar.server.edition.EditionManagementState.PendingStatus.NONE;
38
39 public class StandaloneEditionManagementStateImpl implements MutableEditionManagementState, Startable {
40   private static final String CURRENT_EDITION_KEY = "sonar.editionManagement.currentEditionKey";
41   private static final String PENDING_INSTALLATION_STATUS = "sonar.editionManagement.pendingInstallationStatus";
42   private static final String PENDING_EDITION_KEY = "sonar.editionManagement.pendingEditionKey";
43   private static final String PENDING_LICENSE = "sonar.editionManagement.pendingLicense";
44
45   private final DbClient dbClient;
46   private String currentEditionKey;
47   private PendingStatus pendingInstallationStatus = NONE;
48   private String pendingEditionKey;
49   private String pendingLicense;
50
51   public StandaloneEditionManagementStateImpl(DbClient dbClient) {
52     this.dbClient = dbClient;
53   }
54
55   @Override
56   public void start() {
57     try (DbSession dbSession = dbClient.openSession(false)) {
58       // load current state value
59       Map<String, Optional<String>> internalPropertyValues = dbClient.internalPropertiesDao().selectByKeys(dbSession,
60         ImmutableSet.of(CURRENT_EDITION_KEY, PENDING_INSTALLATION_STATUS, PENDING_EDITION_KEY, PENDING_LICENSE));
61       this.currentEditionKey = internalPropertyValues.getOrDefault(CURRENT_EDITION_KEY, empty())
62         .map(StandaloneEditionManagementStateImpl::emptyToNull)
63         .orElse(null);
64       this.pendingInstallationStatus = internalPropertyValues.getOrDefault(PENDING_INSTALLATION_STATUS, empty())
65         .map(PendingStatus::valueOf)
66         .orElse(NONE);
67       this.pendingEditionKey = internalPropertyValues.getOrDefault(PENDING_EDITION_KEY, empty())
68         .map(StandaloneEditionManagementStateImpl::emptyToNull)
69         .orElse(null);
70       this.pendingLicense = internalPropertyValues.getOrDefault(PENDING_LICENSE, empty()).orElse(null);
71     }
72   }
73
74   @Override
75   public void stop() {
76     // nothing to do
77   }
78
79   @Override
80   public Optional<String> getCurrentEditionKey() {
81     return Optional.ofNullable(currentEditionKey);
82   }
83
84   @Override
85   public PendingStatus getPendingInstallationStatus() {
86     return pendingInstallationStatus;
87   }
88
89   @Override
90   public Optional<String> getPendingEditionKey() {
91     return Optional.ofNullable(pendingEditionKey);
92   }
93
94   @Override
95   public Optional<String> getPendingLicense() {
96     return Optional.ofNullable(pendingLicense);
97   }
98
99   @Override
100   public synchronized PendingStatus startAutomaticInstall(License license) {
101     checkLicense(license);
102     changeStatusFromTo(NONE, AUTOMATIC_IN_PROGRESS);
103     this.pendingLicense = license.getContent();
104     this.pendingEditionKey = license.getEditionKey();
105     persistProperties();
106     return this.pendingInstallationStatus;
107   }
108
109   @Override
110   public synchronized PendingStatus startManualInstall(License license) {
111     checkLicense(license);
112     changeStatusFromTo(NONE, MANUAL_IN_PROGRESS);
113     this.pendingLicense = license.getContent();
114     this.pendingEditionKey = license.getEditionKey();
115     this.pendingInstallationStatus = MANUAL_IN_PROGRESS;
116     persistProperties();
117     return this.pendingInstallationStatus;
118   }
119
120   @Override
121   public synchronized PendingStatus newEditionWithoutInstall(String newEditionKey) {
122     requireNonNull(newEditionKey, "newEditionKey can't be null");
123     checkArgument(!newEditionKey.isEmpty(), "newEditionKey can't be empty");
124     changeStatusFromTo(NONE, NONE);
125     this.currentEditionKey = newEditionKey;
126     persistProperties();
127     return this.pendingInstallationStatus;
128   }
129
130   @Override
131   public synchronized PendingStatus automaticInstallReady() {
132     changeStatusFromTo(AUTOMATIC_IN_PROGRESS, AUTOMATIC_READY);
133     persistProperties();
134     return this.pendingInstallationStatus;
135   }
136
137   @Override
138   public synchronized PendingStatus finalizeInstallation() {
139     checkState(this.pendingInstallationStatus == AUTOMATIC_READY || this.pendingInstallationStatus == MANUAL_IN_PROGRESS,
140       "Can't finalize installation when state is %s", this.pendingInstallationStatus);
141
142     this.pendingInstallationStatus = NONE;
143     this.currentEditionKey = this.pendingEditionKey;
144     this.pendingEditionKey = null;
145     this.pendingLicense = null;
146     persistProperties();
147     return this.pendingInstallationStatus;
148   }
149
150   private void changeStatusFromTo(PendingStatus expectedStatus, PendingStatus newStatus) {
151     checkState(pendingInstallationStatus == expectedStatus,
152       "Can't move to {} when status is {} (should be {})",
153       newStatus, pendingInstallationStatus, expectedStatus);
154     this.pendingInstallationStatus = newStatus;
155   }
156
157   private void persistProperties() {
158     try (DbSession dbSession = dbClient.openSession(false)) {
159       InternalPropertiesDao internalPropertiesDao = dbClient.internalPropertiesDao();
160       if (pendingInstallationStatus == NONE) {
161         internalPropertiesDao.saveAsEmpty(dbSession, PENDING_EDITION_KEY);
162         internalPropertiesDao.saveAsEmpty(dbSession, PENDING_LICENSE);
163       } else {
164         internalPropertiesDao.save(dbSession, PENDING_EDITION_KEY, pendingEditionKey);
165         internalPropertiesDao.save(dbSession, PENDING_LICENSE, pendingLicense);
166       }
167       if (currentEditionKey == null) {
168         internalPropertiesDao.saveAsEmpty(dbSession, CURRENT_EDITION_KEY);
169       } else {
170         internalPropertiesDao.save(dbSession, CURRENT_EDITION_KEY, currentEditionKey);
171       }
172       internalPropertiesDao.save(dbSession, PENDING_INSTALLATION_STATUS, pendingInstallationStatus.name());
173       dbSession.commit();
174     }
175   }
176
177   private static void checkLicense(License license) {
178     requireNonNull(license, "license can't be null");
179   }
180
181   private static String emptyToNull(String s) {
182     return s.isEmpty() ? null : s;
183   }
184 }