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