View Javadoc

1   package org.apache.maven.continuum.management;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import org.apache.continuum.dao.BuildDefinitionDao;
23  import org.apache.continuum.dao.BuildDefinitionTemplateDao;
24  import org.apache.continuum.dao.BuildQueueDao;
25  import org.apache.continuum.dao.ContinuumReleaseResultDao;
26  import org.apache.continuum.dao.DaoUtils;
27  import org.apache.continuum.dao.DirectoryPurgeConfigurationDao;
28  import org.apache.continuum.dao.DistributedDirectoryPurgeConfigurationDao;
29  import org.apache.continuum.dao.InstallationDao;
30  import org.apache.continuum.dao.LocalRepositoryDao;
31  import org.apache.continuum.dao.ProfileDao;
32  import org.apache.continuum.dao.ProjectGroupDao;
33  import org.apache.continuum.dao.ProjectScmRootDao;
34  import org.apache.continuum.dao.RepositoryPurgeConfigurationDao;
35  import org.apache.continuum.dao.ScheduleDao;
36  import org.apache.continuum.dao.SystemConfigurationDao;
37  import org.apache.continuum.model.project.ProjectScmRoot;
38  import org.apache.continuum.model.release.ContinuumReleaseResult;
39  import org.apache.continuum.model.repository.DirectoryPurgeConfiguration;
40  import org.apache.continuum.model.repository.LocalRepository;
41  import org.apache.continuum.utils.ProjectSorter;
42  import org.apache.maven.continuum.model.project.BuildDefinition;
43  import org.apache.maven.continuum.model.project.BuildDefinitionTemplate;
44  import org.apache.maven.continuum.model.project.BuildQueue;
45  import org.apache.maven.continuum.model.project.ContinuumDatabase;
46  import org.apache.maven.continuum.model.project.Project;
47  import org.apache.maven.continuum.model.project.ProjectGroup;
48  import org.apache.maven.continuum.model.project.Schedule;
49  import org.apache.maven.continuum.model.project.io.stax.ContinuumStaxReader;
50  import org.apache.maven.continuum.model.project.io.stax.ContinuumStaxWriter;
51  import org.apache.maven.continuum.model.system.Installation;
52  import org.apache.maven.continuum.model.system.Profile;
53  import org.apache.maven.continuum.store.ContinuumStoreException;
54  import org.codehaus.plexus.jdo.ConfigurableJdoFactory;
55  import org.codehaus.plexus.jdo.PlexusJdoUtils;
56  import org.codehaus.plexus.util.IOUtil;
57  import org.slf4j.Logger;
58  import org.slf4j.LoggerFactory;
59  
60  import java.io.File;
61  import java.io.FileOutputStream;
62  import java.io.FileReader;
63  import java.io.IOException;
64  import java.io.OutputStream;
65  import java.io.OutputStreamWriter;
66  import java.io.Writer;
67  import java.nio.charset.Charset;
68  import java.util.ArrayList;
69  import java.util.Collection;
70  import java.util.HashMap;
71  import java.util.Iterator;
72  import java.util.List;
73  import java.util.Map;
74  import java.util.Properties;
75  import java.util.Set;
76  import javax.jdo.JDOHelper;
77  import javax.jdo.PersistenceManagerFactory;
78  import javax.xml.stream.XMLStreamException;
79  
80  /**
81   * JDO implementation the database management tool API.
82   *
83   * @version $Id: JdoDataManagementTool.java 1372260 2012-08-13 04:29:09Z brett $
84   * @plexus.component role="org.apache.maven.continuum.management.DataManagementTool" role-hint="continuum-jdo"
85   */
86  public class JdoDataManagementTool
87      implements DataManagementTool
88  {
89      private Logger log = LoggerFactory.getLogger( JdoDataManagementTool.class );
90  
91      /**
92       * @plexus.requirement
93       */
94      private DaoUtils daoUtils;
95  
96      /**
97       * @plexus.requirement
98       */
99      private LocalRepositoryDao localRepositoryDao;
100 
101     /**
102      * @plexus.requirement
103      */
104     private DirectoryPurgeConfigurationDao directoryPurgeConfigurationDao;
105 
106     /**
107      * @plexus.requirement
108      */
109     private RepositoryPurgeConfigurationDao repositoryPurgeConfigurationDao;
110 
111     /**
112      * @plexus.requirement
113      */
114     private DistributedDirectoryPurgeConfigurationDao distributedDirectoryPurgeConfigurationDao;
115 
116     /**
117      * @plexus.requirement
118      */
119     private InstallationDao installationDao;
120 
121     /**
122      * @plexus.requirement
123      */
124     private ProfileDao profileDao;
125 
126     /**
127      * @plexus.requirement
128      */
129     private ProjectGroupDao projectGroupDao;
130 
131     /**
132      * @plexus.requirement
133      */
134     private ScheduleDao scheduleDao;
135 
136     /**
137      * @plexus.requirement
138      */
139     private SystemConfigurationDao systemConfigurationDao;
140 
141     /**
142      * @plexus.requirement
143      */
144     private ProjectScmRootDao projectScmRootDao;
145 
146     /**
147      * @plexus.requirement
148      */
149     private BuildDefinitionTemplateDao buildDefinitionTemplateDao;
150 
151     /**
152      * @plexus.requirement
153      */
154     private ContinuumReleaseResultDao releaseResultDao;
155 
156     /**
157      * @plexus.requirement
158      */
159     private BuildQueueDao buildQueueDao;
160 
161     /**
162      * @plexus.requirement
163      */
164     private BuildDefinitionDao buildDefinitionDao;
165 
166     protected static final String BUILDS_XML = "builds.xml";
167 
168     /**
169      * @plexus.requirement role="org.codehaus.plexus.jdo.JdoFactory" role-hint="continuum"
170      */
171     protected ConfigurableJdoFactory factory;
172 
173     public void backupDatabase( File backupDirectory )
174         throws IOException
175     {
176         ContinuumDatabase database = new ContinuumDatabase();
177         try
178         {
179             database.setSystemConfiguration( systemConfigurationDao.getSystemConfiguration() );
180         }
181         catch ( ContinuumStoreException e )
182         {
183             throw new DataManagementException( e );
184         }
185 
186         // TODO: need these to lazy load to conserve memory while we stream out the model
187         Collection projectGroups = projectGroupDao.getAllProjectGroupsWithTheLot();
188         database.setProjectGroups( new ArrayList( projectGroups ) );
189         try
190         {
191             database.setInstallations( installationDao.getAllInstallations() );
192 
193             database.setBuildDefinitionTemplates( buildDefinitionTemplateDao.getAllBuildDefinitionTemplate() );
194 
195             database.setBuildQueues( buildQueueDao.getAllBuildQueues() );
196 
197             database.setBuildDefinitions( buildDefinitionDao.getAllTemplates() );
198         }
199         catch ( ContinuumStoreException e )
200         {
201             throw new DataManagementException( e );
202         }
203         database.setSchedules( scheduleDao.getAllSchedulesByName() );
204         database.setProfiles( profileDao.getAllProfilesByName() );
205         database.setLocalRepositories( localRepositoryDao.getAllLocalRepositories() );
206         database.setRepositoryPurgeConfigurations(
207             repositoryPurgeConfigurationDao.getAllRepositoryPurgeConfigurations() );
208         database.setDirectoryPurgeConfigurations( directoryPurgeConfigurationDao.getAllDirectoryPurgeConfigurations() );
209         database.setDistributedDirectoryPurgeConfigurations(
210             distributedDirectoryPurgeConfigurationDao.getAllDistributedDirectoryPurgeConfigurations() );
211         database.setProjectScmRoots( projectScmRootDao.getAllProjectScmRoots() );
212         database.setContinuumReleaseResults( releaseResultDao.getAllContinuumReleaseResults() );
213 
214         ContinuumStaxWriter writer = new ContinuumStaxWriter();
215 
216         File backupFile = new File( backupDirectory, BUILDS_XML );
217         File parentFile = backupFile.getParentFile();
218         parentFile.mkdirs();
219 
220         OutputStream out = new FileOutputStream( backupFile );
221         Writer fileWriter = new OutputStreamWriter( out, Charset.forName( database.getModelEncoding() ) );
222 
223         try
224         {
225             writer.write( fileWriter, database );
226         }
227         catch ( XMLStreamException e )
228         {
229             throw new DataManagementException( "Modello failure: unable to write data to StAX writer", e );
230         }
231         finally
232         {
233             IOUtil.close( fileWriter );
234         }
235     }
236 
237     public void eraseDatabase()
238     {
239         daoUtils.eraseDatabase();
240     }
241 
242     public void restoreDatabase( File backupDirectory, boolean strict )
243         throws IOException
244     {
245         ContinuumStaxReader reader = new ContinuumStaxReader();
246 
247         FileReader fileReader = new FileReader( new File( backupDirectory, BUILDS_XML ) );
248 
249         ContinuumDatabase database;
250         try
251         {
252             database = reader.read( fileReader, strict );
253         }
254         catch ( XMLStreamException e )
255         {
256             throw new DataManagementException( e );
257         }
258         finally
259         {
260             IOUtil.close( fileReader );
261         }
262 
263         // Take control of the JDO instead of using the store, and configure a new persistence factory
264         // that won't generate new object IDs.
265         Properties properties = new Properties();
266         properties.putAll( factory.getProperties() );
267         properties.setProperty( "org.jpox.metadata.jdoFileExtension", "jdorepl" );
268         PersistenceManagerFactory pmf = JDOHelper.getPersistenceManagerFactory( properties );
269 
270         PlexusJdoUtils.addObject( pmf.getPersistenceManager(), database.getSystemConfiguration() );
271 
272         Map<Integer, BuildQueue> buildQueues = new HashMap<Integer, BuildQueue>();
273         for ( BuildQueue buildQueue : (List<BuildQueue>) database.getBuildQueues() )
274         {
275             buildQueue = (BuildQueue) PlexusJdoUtils.addObject( pmf.getPersistenceManager(), buildQueue );
276             buildQueues.put( buildQueue.getId(), buildQueue );
277         }
278 
279         Map<Integer, Schedule> schedules = new HashMap<Integer, Schedule>();
280         for ( Iterator i = database.getSchedules().iterator(); i.hasNext(); )
281         {
282             Schedule schedule = (Schedule) i.next();
283             schedule.setBuildQueues( getBuildQueuesBySchedule( buildQueues, schedule ) );
284 
285             schedule = (Schedule) PlexusJdoUtils.addObject( pmf.getPersistenceManager(), schedule );
286             schedules.put( Integer.valueOf( schedule.getId() ), schedule );
287         }
288 
289         Map<Integer, Installation> installations = new HashMap<Integer, Installation>();
290         for ( Iterator i = database.getInstallations().iterator(); i.hasNext(); )
291         {
292             Installation installation = (Installation) i.next();
293 
294             installation = (Installation) PlexusJdoUtils.addObject( pmf.getPersistenceManager(), installation );
295             installations.put( Integer.valueOf( installation.getInstallationId() ), installation );
296         }
297 
298         Map<Integer, Profile> profiles = new HashMap<Integer, Profile>();
299         for ( Iterator i = database.getProfiles().iterator(); i.hasNext(); )
300         {
301             Profile profile = (Profile) i.next();
302 
303             // process installations
304             if ( profile.getJdk() != null )
305             {
306                 profile.setJdk( installations.get( profile.getJdk().getInstallationId() ) );
307             }
308             if ( profile.getBuilder() != null )
309             {
310                 profile.setBuilder( installations.get( profile.getBuilder().getInstallationId() ) );
311             }
312             List environmentVariables = new ArrayList();
313             for ( Iterator envIt = profile.getEnvironmentVariables().listIterator(); envIt.hasNext(); )
314             {
315                 Installation installation = (Installation) envIt.next();
316                 environmentVariables.add( installations.get( installation.getInstallationId() ) );
317                 envIt.remove();
318             }
319             profile.setEnvironmentVariables( environmentVariables );
320             profile = (Profile) PlexusJdoUtils.addObject( pmf.getPersistenceManager(), profile );
321             profiles.put( Integer.valueOf( profile.getId() ), profile );
322         }
323 
324         Map<Integer, BuildDefinition> buildDefinitions = new HashMap<Integer, BuildDefinition>();
325         for ( BuildDefinition buildDefinition : (List<BuildDefinition>) database.getBuildDefinitions() )
326         {
327             if ( buildDefinition.getSchedule() != null )
328             {
329                 buildDefinition.setSchedule( schedules.get( Integer.valueOf(
330                     buildDefinition.getSchedule().getId() ) ) );
331             }
332 
333             if ( buildDefinition.getProfile() != null )
334             {
335                 buildDefinition.setProfile( profiles.get( Integer.valueOf( buildDefinition.getProfile().getId() ) ) );
336             }
337 
338             buildDefinition = (BuildDefinition) PlexusJdoUtils.addObject( pmf.getPersistenceManager(),
339                                                                           buildDefinition );
340             buildDefinitions.put( Integer.valueOf( buildDefinition.getId() ), buildDefinition );
341         }
342 
343         Map<Integer, LocalRepository> localRepositories = new HashMap<Integer, LocalRepository>();
344         for ( LocalRepository localRepository : (List<LocalRepository>) database.getLocalRepositories() )
345         {
346             localRepository = (LocalRepository) PlexusJdoUtils.addObject( pmf.getPersistenceManager(),
347                                                                           localRepository );
348             localRepositories.put( Integer.valueOf( localRepository.getId() ), localRepository );
349         }
350 
351         Map<Integer, ProjectGroup> projectGroups = new HashMap<Integer, ProjectGroup>();
352         for ( Iterator i = database.getProjectGroups().iterator(); i.hasNext(); )
353         {
354             ProjectGroup projectGroup = (ProjectGroup) i.next();
355 
356             // first, we must map up any schedules, etc.
357             projectGroup.setBuildDefinitions( processBuildDefinitions( projectGroup.getBuildDefinitions(), schedules,
358                                                                        profiles, buildDefinitions ) );
359 
360             for ( Iterator j = projectGroup.getProjects().iterator(); j.hasNext(); )
361             {
362                 Project project = (Project) j.next();
363 
364                 project.setBuildDefinitions( processBuildDefinitions( project.getBuildDefinitions(), schedules,
365                                                                       profiles, buildDefinitions ) );
366             }
367 
368             if ( projectGroup.getLocalRepository() != null )
369             {
370                 projectGroup.setLocalRepository( localRepositories.get( Integer.valueOf(
371                     projectGroup.getLocalRepository().getId() ) ) );
372             }
373 
374             projectGroup = (ProjectGroup) PlexusJdoUtils.addObject( pmf.getPersistenceManager(), projectGroup );
375             projectGroups.put( Integer.valueOf( projectGroup.getId() ), projectGroup );
376         }
377 
378         // create project scm root data (CONTINUUM-2040)
379         Map<Integer, ProjectScmRoot> projectScmRoots = new HashMap<Integer, ProjectScmRoot>();
380         Set<Integer> keys = projectGroups.keySet();
381         int id = 1;
382         for ( Integer key : keys )
383         {
384             ProjectGroup projectGroup = projectGroups.get( key );
385             String url = " ";
386             List<Project> projects = ProjectSorter.getSortedProjects( getProjectsByGroupIdWithDependencies( pmf,
387                                                                                                             projectGroup.getId() ),
388                                                                       log );
389             for ( Iterator j = projects.iterator(); j.hasNext(); )
390             {
391                 Project project = (Project) j.next();
392                 if ( !project.getScmUrl().trim().startsWith( url ) )
393                 {
394                     url = project.getScmUrl();
395                     ProjectScmRoot projectScmRoot = new ProjectScmRoot();
396                     projectScmRoot.setId( id );
397                     projectScmRoot.setProjectGroup( projectGroup );
398                     projectScmRoot.setScmRootAddress( url );
399                     projectScmRoot.setState( project.getState() );
400 
401                     projectScmRoot = (ProjectScmRoot) PlexusJdoUtils.addObject( pmf.getPersistenceManager(),
402                                                                                 projectScmRoot );
403                     projectScmRoots.put( Integer.valueOf( projectScmRoot.getId() ), projectScmRoot );
404                     id++;
405                 }
406             }
407         }
408 
409         /*
410         for ( RepositoryPurgeConfiguration repoPurge : (List<RepositoryPurgeConfiguration>) database.getRepositoryPurgeConfigurations() )
411         {
412             repoPurge.setRepository( localRepositories.get(
413                                      Integer.valueOf( repoPurge.getRepository().getId() ) ) );
414 
415             if ( repoPurge.getSchedule() != null )
416             {
417                 repoPurge.setSchedule( schedules.get(
418                                        Integer.valueOf( repoPurge.getSchedule().getId() ) ) );
419             }
420 
421             repoPurge = (RepositoryPurgeConfiguration) PlexusJdoUtils.addObject( pmf.getPersistenceManager(), repoPurge );
422         }*/
423 
424         for ( DirectoryPurgeConfiguration dirPurge : (List<DirectoryPurgeConfiguration>) database.getDirectoryPurgeConfigurations() )
425         {
426             if ( dirPurge.getSchedule() != null )
427             {
428                 dirPurge.setSchedule( schedules.get( Integer.valueOf( dirPurge.getSchedule().getId() ) ) );
429             }
430 
431             dirPurge = (DirectoryPurgeConfiguration) PlexusJdoUtils.addObject( pmf.getPersistenceManager(), dirPurge );
432         }
433 
434         for ( ContinuumReleaseResult releaseResult : (List<ContinuumReleaseResult>) database.getContinuumReleaseResults() )
435         {
436             releaseResult.setProjectGroup( projectGroups.get( Integer.valueOf(
437                 releaseResult.getProjectGroup().getId() ) ) );
438 
439             ProjectGroup group = releaseResult.getProjectGroup();
440 
441             for ( Project project : (List<Project>) group.getProjects() )
442             {
443                 if ( project.getId() == releaseResult.getProject().getId() )
444                 {
445                     try
446                     {
447                         Project proj = (Project) PlexusJdoUtils.getObjectById( pmf.getPersistenceManager(),
448                                                                                Project.class, project.getId(), null );
449                         releaseResult.setProject( proj );
450                     }
451                     catch ( Exception e )
452                     {
453                         throw new DataManagementException( e );
454                     }
455                 }
456             }
457 
458             releaseResult = (ContinuumReleaseResult) PlexusJdoUtils.addObject( pmf.getPersistenceManager(),
459                                                                                releaseResult );
460         }
461 
462         for ( BuildDefinitionTemplate template : (List<BuildDefinitionTemplate>) database.getBuildDefinitionTemplates() )
463         {
464             template.setBuildDefinitions( processBuildDefinitions( template.getBuildDefinitions(), buildDefinitions ) );
465 
466             template = (BuildDefinitionTemplate) PlexusJdoUtils.addObject( pmf.getPersistenceManager(), template );
467         }
468     }
469 
470     private List<Project> getProjectsByGroupIdWithDependencies( PersistenceManagerFactory pmf, int projectGroupId )
471     {
472         List<Project> allProjects = PlexusJdoUtils.getAllObjectsDetached( pmf.getPersistenceManager(), Project.class,
473                                                                           "name ascending", "project-dependencies" );
474         List<Project> groupProjects = new ArrayList<Project>();
475 
476         for ( Project project : allProjects )
477         {
478             if ( project.getProjectGroup().getId() == projectGroupId )
479             {
480                 groupProjects.add( project );
481             }
482         }
483 
484         return groupProjects;
485     }
486 
487     private List<BuildDefinition> processBuildDefinitions( List<BuildDefinition> buildDefinitions,
488                                                            Map<Integer, Schedule> schedules,
489                                                            Map<Integer, Profile> profiles,
490                                                            Map<Integer, BuildDefinition> buildDefs )
491     {
492         List<BuildDefinition> buildDefsList = new ArrayList<BuildDefinition>();
493 
494         for ( BuildDefinition def : buildDefinitions )
495         {
496             if ( buildDefs.get( Integer.valueOf( def.getId() ) ) != null )
497             {
498                 buildDefsList.add( buildDefs.get( Integer.valueOf( def.getId() ) ) );
499             }
500             else
501             {
502                 if ( def.getSchedule() != null )
503                 {
504                     def.setSchedule( schedules.get( Integer.valueOf( def.getSchedule().getId() ) ) );
505                 }
506 
507                 if ( def.getProfile() != null )
508                 {
509                     def.setProfile( profiles.get( Integer.valueOf( def.getProfile().getId() ) ) );
510                 }
511 
512                 buildDefsList.add( def );
513             }
514         }
515 
516         return buildDefsList;
517     }
518 
519     private List<BuildDefinition> processBuildDefinitions( List<BuildDefinition> buildDefinitions,
520                                                            Map<Integer, BuildDefinition> buildDefs )
521     {
522         List<BuildDefinition> buildDefsList = new ArrayList<BuildDefinition>();
523 
524         for ( BuildDefinition buildDefinition : buildDefinitions )
525         {
526             buildDefsList.add( buildDefs.get( Integer.valueOf( buildDefinition.getId() ) ) );
527         }
528 
529         return buildDefsList;
530     }
531 
532     private List<BuildQueue> getBuildQueuesBySchedule( Map<Integer, BuildQueue> allBuildQueues, Schedule schedule )
533     {
534         List<BuildQueue> buildQueues = new ArrayList<BuildQueue>();
535 
536         for ( BuildQueue buildQueue : (List<BuildQueue>) schedule.getBuildQueues() )
537         {
538             buildQueues.add( allBuildQueues.get( Integer.valueOf( buildQueue.getId() ) ) );
539         }
540 
541         return buildQueues;
542     }
543 }