1 |
|
|
2 |
|
|
3 |
|
|
4 |
|
|
5 |
|
|
6 |
|
|
7 |
|
|
8 |
|
|
9 |
|
|
10 |
|
|
11 |
|
|
12 |
|
|
13 |
|
|
14 |
|
|
15 |
|
|
16 |
|
|
17 |
|
|
18 |
|
|
19 |
|
|
20 |
|
package com.xpn.xwiki.store.migration; |
21 |
|
|
22 |
|
import java.util.ArrayList; |
23 |
|
import java.util.Arrays; |
24 |
|
import java.util.Collection; |
25 |
|
import java.util.Collections; |
26 |
|
import java.util.HashMap; |
27 |
|
import java.util.HashSet; |
28 |
|
import java.util.List; |
29 |
|
import java.util.Map; |
30 |
|
import java.util.Set; |
31 |
|
import java.util.SortedMap; |
32 |
|
import java.util.TreeMap; |
33 |
|
|
34 |
|
import javax.inject.Inject; |
35 |
|
|
36 |
|
import org.slf4j.Logger; |
37 |
|
import org.xwiki.bridge.event.WikiDeletedEvent; |
38 |
|
import org.xwiki.component.manager.ComponentLookupException; |
39 |
|
import org.xwiki.component.manager.ComponentManager; |
40 |
|
import org.xwiki.component.phase.Initializable; |
41 |
|
import org.xwiki.component.phase.InitializationException; |
42 |
|
import org.xwiki.context.Execution; |
43 |
|
import org.xwiki.context.ExecutionContext; |
44 |
|
import org.xwiki.job.event.status.JobProgressManager; |
45 |
|
import org.xwiki.observation.EventListener; |
46 |
|
import org.xwiki.observation.ObservationManager; |
47 |
|
import org.xwiki.observation.event.Event; |
48 |
|
|
49 |
|
import com.xpn.xwiki.XWikiConfig; |
50 |
|
import com.xpn.xwiki.XWikiContext; |
51 |
|
import com.xpn.xwiki.XWikiException; |
52 |
|
|
53 |
|
|
54 |
|
@link |
55 |
|
|
56 |
|
@version |
57 |
|
@since |
58 |
|
|
|
|
| 72.9% |
Uncovered Elements: 81 (299) |
Complexity: 83 |
Complexity Density: 0.43 |
|
59 |
|
public abstract class AbstractDataMigrationManager implements DataMigrationManager, Initializable |
60 |
|
{ |
61 |
|
|
62 |
|
|
63 |
|
|
64 |
|
@Inject |
65 |
|
protected ComponentManager componentManager; |
66 |
|
|
67 |
|
|
68 |
|
|
69 |
|
|
70 |
|
@Inject |
71 |
|
protected ObservationManager observationManager; |
72 |
|
|
73 |
|
@Inject |
74 |
|
protected JobProgressManager progress; |
75 |
|
|
76 |
|
|
77 |
|
|
78 |
|
|
79 |
|
protected Collection<XWikiMigration> migrations; |
80 |
|
|
81 |
|
|
82 |
|
|
83 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (3) |
Complexity: 1 |
Complexity Density: 0.5 |
|
84 |
|
protected class XWikiMigration |
85 |
|
{ |
86 |
|
|
87 |
|
|
88 |
|
|
89 |
|
public boolean isForced; |
90 |
|
|
91 |
|
|
92 |
|
|
93 |
|
|
94 |
|
public DataMigration dataMigration; |
95 |
|
|
96 |
|
|
97 |
|
|
98 |
|
|
99 |
|
@param |
100 |
|
@param |
101 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (2) |
Complexity: 1 |
Complexity Density: 0.5 |
|
102 |
1552 |
public XWikiMigration(DataMigration dataMigration, boolean isForced)... |
103 |
|
{ |
104 |
1552 |
this.dataMigration = dataMigration; |
105 |
1552 |
this.isForced = isForced; |
106 |
|
} |
107 |
|
} |
108 |
|
|
109 |
|
|
110 |
|
|
111 |
|
|
112 |
|
@Inject |
113 |
|
protected Logger logger; |
114 |
|
|
115 |
|
|
116 |
|
|
117 |
|
|
118 |
|
@Inject |
119 |
|
private Execution execution; |
120 |
|
|
121 |
|
|
122 |
|
|
123 |
|
|
|
|
| 94.4% |
Uncovered Elements: 1 (18) |
Complexity: 6 |
Complexity Density: 0.6 |
|
124 |
|
private static class ThreadLock extends ThreadLocal<Integer> |
125 |
|
{ |
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
126 |
390 |
@Override... |
127 |
|
protected Integer initialValue() |
128 |
|
{ |
129 |
390 |
return 0; |
130 |
|
} |
131 |
|
|
132 |
|
|
133 |
|
|
134 |
|
|
|
|
| 80% |
Uncovered Elements: 1 (5) |
Complexity: 2 |
Complexity Density: 0.67 |
|
135 |
124526 |
public void unlock()... |
136 |
|
{ |
137 |
124521 |
int i = get(); |
138 |
124532 |
if (i > 0) { |
139 |
124538 |
set(--i); |
140 |
|
} |
141 |
|
} |
142 |
|
|
143 |
|
|
144 |
|
|
145 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
146 |
83039 |
public void lock()... |
147 |
|
{ |
148 |
83043 |
set(get() + 1); |
149 |
|
} |
150 |
|
|
151 |
|
|
152 |
|
|
153 |
|
|
154 |
|
@return |
155 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (7) |
Complexity: 2 |
Complexity Density: 0.4 |
|
156 |
41938 |
public boolean tryLock()... |
157 |
|
{ |
158 |
41936 |
int i = get(); |
159 |
41934 |
if (i > 0) { |
160 |
452 |
return false; |
161 |
|
} |
162 |
41480 |
set(++i); |
163 |
41476 |
return true; |
164 |
|
} |
165 |
|
} |
166 |
|
|
167 |
|
|
168 |
|
|
169 |
|
|
170 |
|
private final ThreadLock lock = new ThreadLock(); |
171 |
|
|
172 |
|
|
173 |
|
|
174 |
|
|
|
|
| 33.3% |
Uncovered Elements: 10 (15) |
Complexity: 6 |
Complexity Density: 0.67 |
|
175 |
|
private static class MigrationStatus implements DataMigrationStatus |
176 |
|
{ |
177 |
|
|
178 |
|
|
179 |
|
|
180 |
|
private XWikiDBVersion version; |
181 |
|
|
182 |
|
|
183 |
|
|
184 |
|
|
185 |
|
private Exception migrationException; |
186 |
|
|
187 |
|
|
188 |
|
|
189 |
|
|
190 |
|
private boolean migrationAttempted; |
191 |
|
|
192 |
|
|
193 |
|
|
194 |
|
|
195 |
|
@param |
196 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (2) |
Complexity: 1 |
Complexity Density: 0.5 |
|
197 |
67 |
public MigrationStatus(XWikiDBVersion version)... |
198 |
|
{ |
199 |
67 |
this.version = version; |
200 |
67 |
this.migrationAttempted = false; |
201 |
|
} |
202 |
|
|
203 |
|
|
204 |
|
|
205 |
|
|
206 |
|
|
207 |
|
@param |
208 |
|
@param |
209 |
|
|
|
|
| 0% |
Uncovered Elements: 3 (3) |
Complexity: 1 |
Complexity Density: 0.33 |
|
210 |
0 |
public MigrationStatus(XWikiDBVersion version, Exception migrationException)... |
211 |
|
{ |
212 |
0 |
this.version = version; |
213 |
0 |
this.migrationAttempted = true; |
214 |
0 |
this.migrationException = migrationException; |
215 |
|
} |
216 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
217 |
41519 |
@Override... |
218 |
|
public XWikiDBVersion getDBVersion() |
219 |
|
{ |
220 |
41528 |
return this.version; |
221 |
|
} |
222 |
|
|
|
|
| 0% |
Uncovered Elements: 1 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
223 |
0 |
@Override... |
224 |
|
public boolean hasDataMigrationBeenAttempted() |
225 |
|
{ |
226 |
0 |
return this.migrationAttempted; |
227 |
|
} |
228 |
|
|
|
|
| 0% |
Uncovered Elements: 1 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
229 |
0 |
@Override... |
230 |
|
public boolean hasBeenSuccessfullyMigrated() |
231 |
|
{ |
232 |
0 |
return this.migrationAttempted && this.migrationException == null; |
233 |
|
} |
234 |
|
|
|
|
| 0% |
Uncovered Elements: 1 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
235 |
0 |
@Override... |
236 |
|
public Exception getLastMigrationException() |
237 |
|
{ |
238 |
0 |
return this.migrationException; |
239 |
|
} |
240 |
|
} |
241 |
|
|
242 |
|
|
243 |
|
|
244 |
|
|
245 |
|
private final Map<String, MigrationStatus> statusCache = new HashMap<String, MigrationStatus>(); |
246 |
|
|
247 |
|
|
248 |
|
|
249 |
|
|
250 |
|
|
251 |
|
private XWikiDBVersion targetVersion; |
252 |
|
|
253 |
|
|
254 |
|
|
255 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (6) |
Complexity: 3 |
Complexity Density: 1 |
|
256 |
|
private class WikiDeletedEventListener implements EventListener |
257 |
|
{ |
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
258 |
360 |
@Override... |
259 |
|
public String getName() |
260 |
|
{ |
261 |
360 |
return "dbversioncache"; |
262 |
|
} |
263 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
264 |
90 |
@Override... |
265 |
|
public List<Event> getEvents() |
266 |
|
{ |
267 |
90 |
return Arrays.<Event>asList(new WikiDeletedEvent()); |
268 |
|
} |
269 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
270 |
3 |
@Override... |
271 |
|
public void onEvent(Event event, Object source, Object data) |
272 |
|
{ |
273 |
3 |
AbstractDataMigrationManager.this.statusCache.remove(((WikiDeletedEvent) event).getWikiId()); |
274 |
|
} |
275 |
|
} |
276 |
|
|
277 |
|
|
278 |
|
|
279 |
|
|
|
|
| - |
Uncovered Elements: 0 (0) |
Complexity: 1 |
Complexity Density: - |
|
280 |
90 |
public AbstractDataMigrationManager()... |
281 |
|
{ |
282 |
|
} |
283 |
|
|
284 |
|
|
285 |
|
@return |
286 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (2) |
Complexity: 1 |
Complexity Density: 0.5 |
|
287 |
100519 |
protected XWikiContext getXWikiContext()... |
288 |
|
{ |
289 |
100516 |
ExecutionContext context = this.execution.getContext(); |
290 |
100535 |
return (XWikiContext) context.getProperty("xwikicontext"); |
291 |
|
} |
292 |
|
|
293 |
|
|
294 |
|
@return |
295 |
|
@deprecated |
296 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
297 |
16876 |
@Deprecated... |
298 |
|
protected XWikiConfig getXWikiConfig() |
299 |
|
{ |
300 |
16875 |
return getXWikiContext().getWiki().getConfig(); |
301 |
|
} |
302 |
|
|
303 |
|
|
304 |
|
@deprecated |
305 |
|
@return |
306 |
|
|
|
|
| 0% |
Uncovered Elements: 1 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
307 |
0 |
@Deprecated... |
308 |
|
protected boolean isVirtualMode() |
309 |
|
{ |
310 |
0 |
return true; |
311 |
|
} |
312 |
|
|
313 |
|
|
314 |
|
@return |
315 |
|
@throws |
316 |
|
|
|
|
| 66.7% |
Uncovered Elements: 1 (3) |
Complexity: 2 |
Complexity Density: 0.67 |
|
317 |
33 |
@Deprecated... |
318 |
|
protected List<String> getVirtualWikisDatabaseNames() throws DataMigrationException |
319 |
|
{ |
320 |
33 |
try { |
321 |
33 |
return getXWikiContext().getWiki().getVirtualWikisDatabaseNames(getXWikiContext()); |
322 |
|
} catch (XWikiException e) { |
323 |
0 |
throw new DataMigrationException("Unable to retrieve the list of wiki names", e); |
324 |
|
} |
325 |
|
} |
326 |
|
|
327 |
|
|
328 |
|
@return |
329 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
330 |
66 |
protected String getMainXWiki()... |
331 |
|
{ |
332 |
66 |
return getXWikiContext().getMainXWiki(); |
333 |
|
} |
334 |
|
|
|
|
| 90.5% |
Uncovered Elements: 2 (21) |
Complexity: 6 |
Complexity Density: 0.4 |
|
335 |
90 |
@Override... |
336 |
|
public void initialize() throws InitializationException |
337 |
|
{ |
338 |
90 |
try { |
339 |
90 |
SortedMap<XWikiDBVersion, XWikiMigration> availableMigrations = new TreeMap<>(); |
340 |
|
|
341 |
90 |
Map<XWikiDBVersion, XWikiMigration> forcedMigrations = getForcedMigrations(); |
342 |
90 |
if (!forcedMigrations.isEmpty()) { |
343 |
1 |
availableMigrations.putAll(forcedMigrations); |
344 |
|
} else { |
345 |
89 |
Set<String> ignoredMigrations = new HashSet<String>(Arrays.asList(getXWikiConfig() |
346 |
|
.getPropertyAsList("xwiki.store.migration.ignored"))); |
347 |
89 |
for (DataMigration migrator : getAllMigrations()) { |
348 |
1552 |
if (ignoredMigrations.contains(migrator.getClass().getName()) |
349 |
|
|| ignoredMigrations.contains(migrator.getVersion().toString())) |
350 |
|
{ |
351 |
1 |
continue; |
352 |
|
} |
353 |
1551 |
XWikiMigration migration = new XWikiMigration(migrator, false); |
354 |
1551 |
availableMigrations.put(migrator.getVersion(), migration); |
355 |
|
} |
356 |
|
} |
357 |
|
|
358 |
90 |
this.targetVersion = (availableMigrations.size() > 0) ? availableMigrations.lastKey() |
359 |
|
: new XWikiDBVersion(0); |
360 |
90 |
this.migrations = availableMigrations.values(); |
361 |
|
} catch (Exception e) { |
362 |
0 |
throw new InitializationException("Migration Manager initialization failed", e); |
363 |
|
} |
364 |
|
|
365 |
90 |
this.observationManager.addListener(new WikiDeletedEventListener()); |
366 |
|
} |
367 |
|
|
368 |
|
|
369 |
|
|
370 |
|
|
371 |
|
@return |
372 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (4) |
Complexity: 2 |
Complexity Density: 1 |
|
373 |
69 |
protected XWikiDBVersion getDBVersionFromConfig()... |
374 |
|
{ |
375 |
69 |
String ver = getXWikiConfig().getProperty("xwiki.store.migration.version"); |
376 |
69 |
return ver == null ? null : new XWikiDBVersion(Integer.parseInt(ver)); |
377 |
|
} |
378 |
|
|
379 |
|
|
380 |
|
|
381 |
|
|
382 |
|
@return |
383 |
|
@throws |
384 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
385 |
5 |
protected XWikiDBVersion getDBVersionFromDatabase() throws DataMigrationException... |
386 |
|
{ |
387 |
5 |
return getDBVersionFromConfig(); |
388 |
|
} |
389 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (16) |
Complexity: 3 |
Complexity Density: 0.25 |
|
390 |
69 |
@Override... |
391 |
|
public final XWikiDBVersion getDBVersion() throws DataMigrationException |
392 |
|
{ |
393 |
69 |
this.lock.lock(); |
394 |
69 |
try { |
395 |
69 |
String wikiName = getXWikiContext().getWikiId(); |
396 |
69 |
MigrationStatus dbStatus = this.statusCache.get(wikiName); |
397 |
69 |
if (dbStatus == null) { |
398 |
5 |
synchronized (this.statusCache) { |
399 |
5 |
XWikiDBVersion version = getDBVersionFromDatabase(); |
400 |
5 |
if (version != null) { |
401 |
2 |
this.statusCache.put(wikiName, new MigrationStatus(version)); |
402 |
|
} |
403 |
5 |
return version; |
404 |
|
} |
405 |
|
} |
406 |
64 |
return dbStatus.getDBVersion(); |
407 |
|
} finally { |
408 |
69 |
this.lock.unlock(); |
409 |
|
} |
410 |
|
} |
411 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (16) |
Complexity: 3 |
Complexity Density: 0.25 |
|
412 |
82931 |
@Override... |
413 |
|
public DataMigrationStatus getDataMigrationStatus() throws DataMigrationException |
414 |
|
{ |
415 |
82933 |
this.lock.lock(); |
416 |
82958 |
try { |
417 |
82955 |
String wikiName = getXWikiContext().getWikiId(); |
418 |
82971 |
MigrationStatus dbStatus = this.statusCache.get(wikiName); |
419 |
82960 |
if (dbStatus == null) { |
420 |
64 |
synchronized (this.statusCache) { |
421 |
64 |
XWikiDBVersion version = getDBVersionFromDatabase(); |
422 |
64 |
if (version != null) { |
423 |
26 |
dbStatus = new MigrationStatus(version); |
424 |
26 |
this.statusCache.put(wikiName, dbStatus); |
425 |
|
} |
426 |
|
} |
427 |
|
} |
428 |
82957 |
return dbStatus; |
429 |
|
} finally { |
430 |
82952 |
this.lock.unlock(); |
431 |
|
} |
432 |
|
} |
433 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
434 |
41528 |
@Override... |
435 |
|
public final XWikiDBVersion getLatestVersion() |
436 |
|
{ |
437 |
41535 |
return this.targetVersion; |
438 |
|
} |
439 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (4) |
Complexity: 1 |
Complexity Density: 0.25 |
|
440 |
38 |
@Override... |
441 |
|
public synchronized void initNewDB() throws DataMigrationException |
442 |
|
{ |
443 |
38 |
this.lock.lock(); |
444 |
38 |
try { |
445 |
38 |
initializeEmptyDB(); |
446 |
|
} finally { |
447 |
38 |
this.lock.unlock(); |
448 |
|
} |
449 |
|
} |
450 |
|
|
451 |
|
|
452 |
|
@throws |
453 |
|
|
454 |
|
protected abstract void initializeEmptyDB() throws DataMigrationException; |
455 |
|
|
456 |
|
|
457 |
|
@param |
458 |
|
@throws |
459 |
|
|
460 |
|
protected abstract void setDBVersionToDatabase(XWikiDBVersion version) throws DataMigrationException; |
461 |
|
|
462 |
|
|
463 |
|
|
464 |
|
|
465 |
|
@param |
466 |
|
@throws |
467 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
468 |
39 |
protected final void setDBVersion(XWikiDBVersion version) throws DataMigrationException... |
469 |
|
{ |
470 |
39 |
updateMigrationStatus(version, false, null); |
471 |
|
} |
472 |
|
|
473 |
|
|
474 |
|
|
475 |
|
|
476 |
|
@param |
477 |
|
@throws |
478 |
|
|
|
|
| 0% |
Uncovered Elements: 1 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
479 |
0 |
private void updateMigrationStatus(XWikiDBVersion version) throws DataMigrationException... |
480 |
|
{ |
481 |
0 |
updateMigrationStatus(version, true, null); |
482 |
|
} |
483 |
|
|
484 |
|
|
485 |
|
|
486 |
|
|
487 |
|
@param |
488 |
|
@param |
489 |
|
@throws |
490 |
|
|
|
|
| 0% |
Uncovered Elements: 1 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
491 |
0 |
private void updateMigrationStatus(XWikiDBVersion version, Exception e) throws DataMigrationException... |
492 |
|
{ |
493 |
0 |
updateMigrationStatus(version, true, e); |
494 |
|
} |
495 |
|
|
496 |
|
|
497 |
|
|
498 |
|
|
499 |
|
@param |
500 |
|
@param |
501 |
|
@param |
502 |
|
@throws |
503 |
|
|
|
|
| 72.7% |
Uncovered Elements: 3 (11) |
Complexity: 5 |
Complexity Density: 1 |
|
504 |
39 |
private synchronized void updateMigrationStatus(XWikiDBVersion version, boolean migrationAttempted, Exception e)... |
505 |
|
throws DataMigrationException |
506 |
|
{ |
507 |
39 |
String wikiName = getXWikiContext().getWikiId(); |
508 |
39 |
if (!migrationAttempted || e == null) { |
509 |
39 |
setDBVersionToDatabase(version); |
510 |
|
} |
511 |
39 |
if (version != null) { |
512 |
39 |
this.statusCache.put(wikiName, |
513 |
39 |
(migrationAttempted) ? new MigrationStatus(version, e) : new MigrationStatus(version)); |
514 |
|
} |
515 |
|
} |
516 |
|
|
517 |
|
|
518 |
|
|
519 |
|
|
520 |
|
@param |
521 |
|
@throws |
522 |
|
|
523 |
|
protected abstract void updateSchema(Collection<XWikiMigration> migrations) throws DataMigrationException; |
524 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (15) |
Complexity: 4 |
Complexity Density: 0.44 |
|
525 |
41941 |
@Override... |
526 |
|
public void checkDatabase() throws MigrationRequiredException, DataMigrationException |
527 |
|
{ |
528 |
41928 |
if (!this.lock.tryLock()) { |
529 |
452 |
return; |
530 |
|
} |
531 |
41476 |
try { |
532 |
41480 |
if (getDatabaseStatus() == null) { |
533 |
38 |
initializeCurrentDatabase(); |
534 |
|
} |
535 |
|
|
536 |
|
|
537 |
41472 |
if (this.migrations != null) { |
538 |
16595 |
tryToProcceedToMigration(); |
539 |
|
} |
540 |
|
|
541 |
41461 |
preventAccessToOutdatedDb(); |
542 |
|
} finally { |
543 |
41462 |
this.lock.unlock(); |
544 |
|
} |
545 |
|
} |
546 |
|
|
|
|
| 40% |
Uncovered Elements: 3 (5) |
Complexity: 2 |
Complexity Density: 0.4 |
|
547 |
38 |
private void initializeCurrentDatabase() throws DataMigrationException... |
548 |
|
{ |
549 |
38 |
try { |
550 |
38 |
initNewDB(); |
551 |
|
} catch (DataMigrationException e) { |
552 |
0 |
String message = String.format( |
553 |
|
"The empty database %s seems to be not writable, please check your configuration!", |
554 |
|
getXWikiContext().getWikiId()); |
555 |
0 |
this.logger.error(message, e); |
556 |
0 |
throw new DataMigrationException(message, e); |
557 |
|
} |
558 |
|
} |
559 |
|
|
|
|
| 57.1% |
Uncovered Elements: 3 (7) |
Complexity: 2 |
Complexity Density: 0.29 |
|
560 |
41479 |
private DataMigrationStatus getDatabaseStatus() throws DataMigrationException... |
561 |
|
{ |
562 |
41478 |
DataMigrationStatus status; |
563 |
41477 |
try { |
564 |
41474 |
status = getDataMigrationStatus(); |
565 |
|
} catch (DataMigrationException e) { |
566 |
0 |
String message = String.format( |
567 |
|
"Database %s seems to be inaccessible, please check your configuration!", |
568 |
|
getXWikiContext().getWikiId()); |
569 |
0 |
this.logger.error(message, e); |
570 |
0 |
throw new DataMigrationException(message, e); |
571 |
|
} |
572 |
41472 |
return status; |
573 |
|
} |
574 |
|
|
575 |
|
|
576 |
|
|
577 |
|
|
578 |
|
@throws |
579 |
|
@throws |
580 |
|
|
|
|
| 27.3% |
Uncovered Elements: 8 (11) |
Complexity: 4 |
Complexity Density: 0.57 |
|
581 |
41445 |
private void preventAccessToOutdatedDb()... |
582 |
|
throws DataMigrationException, MigrationRequiredException |
583 |
|
{ |
584 |
41454 |
DataMigrationStatus status = getDataMigrationStatus(); |
585 |
|
|
586 |
41472 |
if (getLatestVersion().compareTo(status.getDBVersion()) > 0) { |
587 |
0 |
if (status.hasDataMigrationBeenAttempted() && !status.hasBeenSuccessfullyMigrated()) { |
588 |
0 |
String message = String.format( |
589 |
|
"Migration of database [%s] has failed, it could not be safely used! Database is currently in" |
590 |
|
+ " version [%d] while the required version is [%d].", |
591 |
|
getXWikiContext().getWikiId(), |
592 |
|
status.getDBVersion().getVersion(), |
593 |
|
getLatestVersion().getVersion()); |
594 |
0 |
throw new DataMigrationException(message, status.getLastMigrationException()); |
595 |
|
} else { |
596 |
0 |
String message = String.format( |
597 |
|
"Since database [%s] needs to be migrated, it couldn't be safely used! Please check your" |
598 |
|
+ " configuration to enable required migration for upgrading database from version [%d]" |
599 |
|
+ " to version [%d].", |
600 |
|
getXWikiContext().getWikiId(), |
601 |
|
status.getDBVersion().getVersion(), |
602 |
|
getLatestVersion().getVersion()); |
603 |
0 |
throw new MigrationRequiredException(message); |
604 |
|
} |
605 |
|
} |
606 |
|
} |
607 |
|
|
608 |
|
|
609 |
|
|
610 |
|
|
611 |
|
@throws |
612 |
|
|
|
|
| 72.7% |
Uncovered Elements: 3 (11) |
Complexity: 4 |
Complexity Density: 0.57 |
|
613 |
16596 |
private void tryToProcceedToMigration() throws DataMigrationException... |
614 |
|
{ |
615 |
16596 |
XWikiConfig config = getXWikiConfig(); |
616 |
16596 |
if ("1".equals(config.getProperty("xwiki.store.migration", "0")) |
617 |
|
&& !"0".equals(config.getProperty("xwiki.store.hibernate.updateschema"))) { |
618 |
|
|
619 |
32 |
this.logger.info("Storage schema updates and data migrations are enabled"); |
620 |
|
|
621 |
32 |
startMigrationsOnlyOnce(); |
622 |
|
|
623 |
|
|
624 |
32 |
if ("1".equals(config.getProperty("xwiki.store.migration.exitAfterEnd", "0"))) { |
625 |
0 |
this.logger.error("Exiting because xwiki.store.migration.exitAfterEnd is set"); |
626 |
0 |
System.exit(0); |
627 |
|
} |
628 |
|
} |
629 |
|
} |
630 |
|
|
631 |
|
|
632 |
|
|
633 |
|
|
634 |
|
@throws |
635 |
|
|
|
|
| 71.4% |
Uncovered Elements: 2 (7) |
Complexity: 2 |
Complexity Density: 0.4 |
|
636 |
32 |
private synchronized void startMigrationsOnlyOnce() throws DataMigrationException... |
637 |
|
{ |
638 |
|
|
639 |
32 |
if (this.migrations == null) { |
640 |
0 |
return; |
641 |
|
} |
642 |
|
|
643 |
32 |
try { |
644 |
32 |
startMigrations(); |
645 |
|
} finally { |
646 |
32 |
this.migrations = null; |
647 |
|
} |
648 |
|
} |
649 |
|
|
650 |
|
|
651 |
|
|
652 |
|
|
653 |
|
|
654 |
|
@throws |
655 |
|
|
|
|
| 43.5% |
Uncovered Elements: 13 (23) |
Complexity: 4 |
Complexity Density: 0.24 |
|
656 |
33 |
protected void startMigrations() throws DataMigrationException... |
657 |
|
{ |
658 |
33 |
Set<String> databasesToMigrate = getDatabasesToMigrate(); |
659 |
|
|
660 |
33 |
this.progress.pushLevelProgress(databasesToMigrate.size() + 1, this); |
661 |
|
|
662 |
33 |
try { |
663 |
|
|
664 |
33 |
if (!migrateDatabase(getMainXWiki())) { |
665 |
0 |
String message = "Main wiki database migration failed, it is not safe to continue!"; |
666 |
0 |
this.logger.error(message); |
667 |
0 |
throw new DataMigrationException(message); |
668 |
|
} |
669 |
|
|
670 |
33 |
int errorCount = 0; |
671 |
33 |
for (String database : databasesToMigrate) { |
672 |
0 |
this.progress.startStep(this); |
673 |
|
|
674 |
0 |
if (!migrateDatabase(database)) { |
675 |
0 |
errorCount++; |
676 |
|
} |
677 |
|
} |
678 |
|
|
679 |
33 |
if (errorCount > 0) { |
680 |
0 |
String message = String.format("%s wiki database migration(s) failed.", errorCount); |
681 |
0 |
this.logger.error(message); |
682 |
0 |
throw new DataMigrationException(message); |
683 |
|
} |
684 |
|
} finally { |
685 |
33 |
this.progress.popLevelProgress(this); |
686 |
|
} |
687 |
|
} |
688 |
|
|
689 |
|
|
690 |
|
|
691 |
|
|
692 |
|
|
693 |
|
|
694 |
|
|
695 |
|
@return |
696 |
|
@throws |
697 |
|
|
|
|
| 80% |
Uncovered Elements: 2 (10) |
Complexity: 4 |
Complexity Density: 0.5 |
|
698 |
33 |
private Set<String> getDatabasesToMigrate() throws DataMigrationException... |
699 |
|
{ |
700 |
33 |
Set<String> databasesToMigrate = new HashSet<String>(); |
701 |
|
|
702 |
|
|
703 |
|
|
704 |
33 |
String[] databases = getXWikiConfig().getPropertyAsList("xwiki.store.migration.databases"); |
705 |
33 |
if ((databases.length == 0) || ((databases.length == 1) && databases[0].equalsIgnoreCase("all"))) { |
706 |
|
|
707 |
33 |
List<String> allwikis = getVirtualWikisDatabaseNames(); |
708 |
33 |
databasesToMigrate.addAll(allwikis); |
709 |
|
} else { |
710 |
0 |
Collections.addAll(databasesToMigrate, databases); |
711 |
|
} |
712 |
|
|
713 |
|
|
714 |
33 |
databasesToMigrate.remove(getMainXWiki()); |
715 |
|
|
716 |
33 |
return databasesToMigrate; |
717 |
|
} |
718 |
|
|
719 |
|
|
720 |
|
|
721 |
|
|
722 |
|
@param |
723 |
|
@return |
724 |
|
|
|
|
| 70.6% |
Uncovered Elements: 5 (17) |
Complexity: 3 |
Complexity Density: 0.18 |
|
725 |
33 |
private boolean migrateDatabase(String database)... |
726 |
|
{ |
727 |
33 |
XWikiContext context = getXWikiContext(); |
728 |
|
|
729 |
|
|
730 |
33 |
String currentDatabase = context.getWikiId(); |
731 |
33 |
String currentOriginalDatabase = context.getOriginalWikiId(); |
732 |
|
|
733 |
33 |
try { |
734 |
|
|
735 |
|
|
736 |
33 |
context.setWikiId(database); |
737 |
33 |
context.setOriginalWikiId(database); |
738 |
|
|
739 |
33 |
Collection<XWikiMigration> neededMigrations = getNeededMigrations(); |
740 |
33 |
updateSchema(neededMigrations); |
741 |
33 |
startMigrations(neededMigrations); |
742 |
|
} catch (Exception e) { |
743 |
0 |
try { |
744 |
0 |
updateMigrationStatus(getDBVersion(), e); |
745 |
|
} catch (DataMigrationException e1) { |
746 |
|
|
747 |
|
} |
748 |
0 |
String message = String.format("Failed to migrate database [%s]...", database); |
749 |
0 |
this.logger.error(message, e); |
750 |
0 |
return false; |
751 |
|
} finally { |
752 |
33 |
context.setWikiId(currentDatabase); |
753 |
33 |
context.setOriginalWikiId(currentOriginalDatabase); |
754 |
|
} |
755 |
33 |
return true; |
756 |
|
} |
757 |
|
|
758 |
|
|
759 |
|
@return@link |
760 |
|
@throws |
761 |
|
|
|
|
| 91.7% |
Uncovered Elements: 1 (12) |
Complexity: 5 |
Complexity Density: 0.62 |
|
762 |
36 |
protected Collection<XWikiMigration> getNeededMigrations() throws DataMigrationException... |
763 |
|
{ |
764 |
36 |
XWikiDBVersion curversion = getDBVersion(); |
765 |
36 |
Collection<XWikiMigration> neededMigrations = new ArrayList<XWikiMigration>(); |
766 |
|
|
767 |
36 |
for (XWikiMigration migration : this.migrations) { |
768 |
593 |
if (migration.isForced || (migration.dataMigration.getVersion().compareTo(curversion) > 0 |
769 |
|
&& migration.dataMigration.shouldExecute(curversion))) |
770 |
|
{ |
771 |
3 |
neededMigrations.add(migration); |
772 |
|
} |
773 |
|
} |
774 |
|
|
775 |
36 |
if (this.logger.isInfoEnabled()) { |
776 |
36 |
logNeededMigrationReport(curversion, neededMigrations); |
777 |
|
} |
778 |
|
|
779 |
36 |
return neededMigrations; |
780 |
|
} |
781 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (14) |
Complexity: 4 |
Complexity Density: 0.5 |
|
782 |
36 |
private void logNeededMigrationReport(XWikiDBVersion curversion,... |
783 |
|
Collection<XWikiMigration> neededMigrations) |
784 |
|
{ |
785 |
36 |
String database = getXWikiContext().getWikiId(); |
786 |
36 |
if (!neededMigrations.isEmpty()) { |
787 |
2 |
this.logger.info( |
788 |
|
"The following data migration(s) will be applied for wiki [{}] currently in version [{}]:", |
789 |
|
database, curversion); |
790 |
2 |
for (XWikiMigration migration : neededMigrations) { |
791 |
3 |
this.logger.info(" {} - {}{}", migration.dataMigration.getName(), |
792 |
3 |
migration.dataMigration.getDescription(), (migration.isForced ? " (forced)" : "")); |
793 |
|
} |
794 |
|
} else { |
795 |
34 |
if (curversion != null) { |
796 |
32 |
this.logger.info("No data migration to apply for wiki [{}] currently in version [{}]", |
797 |
|
database, curversion); |
798 |
|
} else { |
799 |
2 |
this.logger.info("No data migration to apply for empty wiki [{}]", |
800 |
|
database); |
801 |
|
} |
802 |
|
} |
803 |
|
} |
804 |
|
|
805 |
|
|
806 |
|
@return@link |
807 |
|
@throws |
808 |
|
|
|
|
| 85.7% |
Uncovered Elements: 1 (7) |
Complexity: 2 |
Complexity Density: 0.29 |
|
809 |
90 |
protected Map<XWikiDBVersion, XWikiMigration> getForcedMigrations() throws DataMigrationException... |
810 |
|
{ |
811 |
90 |
SortedMap<XWikiDBVersion, XWikiMigration> forcedMigrations = new TreeMap<XWikiDBVersion, XWikiMigration>(); |
812 |
90 |
for (String hint : getXWikiConfig().getPropertyAsList("xwiki.store.migration.force")) { |
813 |
1 |
try { |
814 |
1 |
DataMigration dataMigration = this.componentManager.getInstance(DataMigration.class, hint); |
815 |
1 |
forcedMigrations.put(dataMigration.getVersion(), new XWikiMigration(dataMigration, true)); |
816 |
|
} catch (ComponentLookupException e) { |
817 |
0 |
throw new DataMigrationException("Forced dataMigration " + hint + " component could not be found", e); |
818 |
|
} |
819 |
|
} |
820 |
90 |
return forcedMigrations; |
821 |
|
} |
822 |
|
|
823 |
|
|
824 |
|
@param |
825 |
|
@throws |
826 |
|
|
|
|
| 33.3% |
Uncovered Elements: 20 (30) |
Complexity: 6 |
Complexity Density: 0.3 |
|
827 |
33 |
protected void startMigrations(Collection<XWikiMigration> migrations) throws DataMigrationException... |
828 |
|
{ |
829 |
33 |
XWikiDBVersion curversion = getDBVersion(); |
830 |
33 |
String database = null; |
831 |
33 |
if (this.logger.isInfoEnabled()) { |
832 |
33 |
database = getXWikiContext().getWikiId(); |
833 |
|
} |
834 |
|
|
835 |
33 |
this.progress.pushLevelProgress(migrations.size(), this); |
836 |
|
|
837 |
33 |
try { |
838 |
33 |
for (XWikiMigration migration : migrations) { |
839 |
0 |
this.progress.startStep(this); |
840 |
|
|
841 |
0 |
if (this.logger.isInfoEnabled()) { |
842 |
0 |
this.logger.info("Starting data migration [{}] with version [{}] on database [{}]", |
843 |
|
migration.dataMigration.getName(), migration.dataMigration.getVersion(), database); |
844 |
|
} |
845 |
|
|
846 |
0 |
migration.dataMigration.migrate(); |
847 |
|
|
848 |
0 |
if (migration.dataMigration.getVersion().compareTo(curversion) > 0) { |
849 |
0 |
curversion = migration.dataMigration.getVersion(); |
850 |
0 |
updateMigrationStatus(curversion); |
851 |
0 |
if (this.logger.isInfoEnabled()) { |
852 |
0 |
this.logger.info( |
853 |
|
"Data migration [{}] applied successfully, database [{}] upgraded to version [{}]", |
854 |
|
migration.dataMigration.getName(), database, getDBVersion()); |
855 |
|
} |
856 |
0 |
} else if (this.logger.isInfoEnabled()) { |
857 |
0 |
this.logger.info("Data migration [{}] applied successfully, database [{}] stay in version [{}]", |
858 |
|
migration.dataMigration.getName(), database, getDBVersion()); |
859 |
|
} |
860 |
|
} |
861 |
|
} finally { |
862 |
33 |
this.progress.popLevelProgress(this); |
863 |
|
} |
864 |
|
|
865 |
|
|
866 |
33 |
setDatabaseToLastestVersion(curversion); |
867 |
|
} |
868 |
|
|
869 |
|
|
870 |
|
|
871 |
|
|
872 |
|
|
873 |
|
@param |
874 |
|
@throws |
875 |
|
|
|
|
| 42.9% |
Uncovered Elements: 8 (14) |
Complexity: 5 |
Complexity Density: 0.83 |
|
876 |
33 |
private void setDatabaseToLastestVersion(XWikiDBVersion currentVersion) throws DataMigrationException... |
877 |
|
{ |
878 |
33 |
if (currentVersion == null) { |
879 |
1 |
setDBVersion(getLatestVersion()); |
880 |
32 |
} else if (getLatestVersion().compareTo(currentVersion) > 0) { |
881 |
0 |
updateMigrationStatus(getLatestVersion()); |
882 |
0 |
if (this.logger.isInfoEnabled()) { |
883 |
0 |
this.logger.info("Database [{}] upgraded to latest version [{}] without needing{} data migration", |
884 |
0 |
getXWikiContext().getWikiId(), getDBVersion(), (this.migrations.size() > 0) ? " further" : ""); |
885 |
|
} |
886 |
|
} |
887 |
|
} |
888 |
|
|
889 |
|
|
890 |
|
@return@link |
891 |
|
@throws |
892 |
|
|
893 |
|
protected abstract List<? extends DataMigration> getAllMigrations() throws DataMigrationException; |
894 |
|
} |