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.maven.continuum.model.project.v1_0_9.BuildDefinition;
23  import org.apache.maven.continuum.model.project.v1_0_9.BuildResult;
24  import org.apache.maven.continuum.model.project.v1_0_9.ContinuumDatabase;
25  import org.apache.maven.continuum.model.project.v1_0_9.Project;
26  import org.apache.maven.continuum.model.project.v1_0_9.ProjectDependency;
27  import org.apache.maven.continuum.model.project.v1_0_9.ProjectDeveloper;
28  import org.apache.maven.continuum.model.project.v1_0_9.ProjectGroup;
29  import org.apache.maven.continuum.model.project.v1_0_9.ProjectNotifier;
30  import org.apache.maven.continuum.model.project.v1_0_9.Schedule;
31  import org.apache.maven.continuum.model.project.v1_0_9.io.stax.ContinuumStaxReader;
32  import org.apache.maven.continuum.model.project.v1_0_9.io.stax.ContinuumStaxWriter;
33  import org.apache.maven.continuum.model.scm.v1_0_9.ChangeFile;
34  import org.apache.maven.continuum.model.scm.v1_0_9.ChangeSet;
35  import org.apache.maven.continuum.model.scm.v1_0_9.ScmResult;
36  import org.apache.maven.continuum.model.scm.v1_0_9.SuiteResult;
37  import org.apache.maven.continuum.model.scm.v1_0_9.TestCaseFailure;
38  import org.apache.maven.continuum.model.scm.v1_0_9.TestResult;
39  import org.apache.maven.continuum.model.system.v1_0_9.SystemConfiguration;
40  import org.apache.maven.continuum.store.ContinuumStoreException;
41  import org.codehaus.plexus.jdo.DefaultConfigurableJdoFactory;
42  import org.codehaus.plexus.jdo.PlexusJdoUtils;
43  import org.codehaus.plexus.util.IOUtil;
44  
45  import java.io.File;
46  import java.io.FileOutputStream;
47  import java.io.FileReader;
48  import java.io.IOException;
49  import java.io.OutputStream;
50  import java.io.OutputStreamWriter;
51  import java.io.Writer;
52  import java.nio.charset.Charset;
53  import java.util.ArrayList;
54  import java.util.Arrays;
55  import java.util.Collection;
56  import java.util.HashMap;
57  import java.util.Iterator;
58  import java.util.List;
59  import java.util.Map;
60  import java.util.Properties;
61  import javax.jdo.FetchPlan;
62  import javax.jdo.JDOHelper;
63  import javax.jdo.PersistenceManager;
64  import javax.jdo.PersistenceManagerFactory;
65  import javax.xml.stream.XMLStreamException;
66  
67  /**
68   * JDO implementation the database management tool API.
69   *
70   * @version $Id: LegacyJdoDataManagementTool.java 1372260 2012-08-13 04:29:09Z brett $
71   * @plexus.component role="org.apache.maven.continuum.management.DataManagementTool" role-hint="legacy-continuum-jdo"
72   */
73  public class LegacyJdoDataManagementTool
74      implements DataManagementTool
75  {
76      protected static final String BUILDS_XML = "builds.xml";
77  
78      /**
79       * @plexus.requirement role="org.codehaus.plexus.jdo.JdoFactory" role-hint="continuum"
80       */
81      protected DefaultConfigurableJdoFactory factory;
82  
83      public void backupDatabase( File backupDirectory )
84          throws IOException
85      {
86          PersistenceManagerFactory pmf = getPersistenceManagerFactory( "jdo109" );
87  
88          ContinuumDatabase database = new ContinuumDatabase();
89          try
90          {
91              database.setSystemConfiguration( retrieveSystemConfiguration( pmf ) );
92          }
93          catch ( ContinuumStoreException e )
94          {
95              throw new DataManagementException( e );
96          }
97  
98          Collection<ProjectGroup> projectGroups = retrieveAllProjectGroups( pmf );
99          database.setProjectGroups( new ArrayList<ProjectGroup>( projectGroups ) );
100 
101         database.setSchedules( retrieveAllSchedules( pmf ) );
102 
103         ContinuumStaxWriter writer = new ContinuumStaxWriter();
104 
105         backupDirectory.mkdirs();
106         OutputStream out = new FileOutputStream( new File( backupDirectory, BUILDS_XML ) );
107         Writer fileWriter = new OutputStreamWriter( out, Charset.forName( database.getModelEncoding() ) );
108 
109         try
110         {
111             writer.write( fileWriter, database );
112         }
113         catch ( XMLStreamException e )
114         {
115             throw new DataManagementException( "Modello failure: unable to write data to StAX writer", e );
116         }
117         finally
118         {
119             IOUtil.close( fileWriter );
120         }
121     }
122 
123     private List retrieveAllSchedules( PersistenceManagerFactory pmf )
124     {
125         return PlexusJdoUtils.getAllObjectsDetached( getPersistenceManager( pmf ), Schedule.class, "name ascending",
126                                                      (String) null );
127     }
128 
129     private Collection<ProjectGroup> retrieveAllProjectGroups( PersistenceManagerFactory pmf )
130     {
131         List<String> fetchGroups = Arrays.asList( "project-with-builds", "projectgroup-projects",
132                                                   "build-result-with-details", "project-with-checkout-result",
133                                                   "project-all-details", "project-build-details" );
134         return PlexusJdoUtils.getAllObjectsDetached( getPersistenceManager( pmf ), ProjectGroup.class, "name ascending",
135                                                      fetchGroups );
136     }
137 
138     private SystemConfiguration retrieveSystemConfiguration( PersistenceManagerFactory pmf )
139         throws ContinuumStoreException
140     {
141         SystemConfiguration result;
142         List systemConfs = PlexusJdoUtils.getAllObjectsDetached( getPersistenceManager( pmf ),
143                                                                  SystemConfiguration.class, null, (String) null );
144 
145         if ( systemConfs == null || systemConfs.isEmpty() )
146         {
147             result = null;
148         }
149         else if ( systemConfs.size() > 1 )
150         {
151             throw new ContinuumStoreException(
152                 "Database is corrupted. There are more than one systemConfiguration object." );
153         }
154         else
155         {
156             result = (SystemConfiguration) systemConfs.get( 0 );
157         }
158         return result;
159     }
160 
161     @SuppressWarnings( {"OverlyCoupledMethod"} )
162     public void eraseDatabase()
163     {
164         PersistenceManagerFactory pmf = getPersistenceManagerFactory( "jdo109" );
165         PersistenceManager persistenceManager = getPersistenceManager( pmf );
166         PlexusJdoUtils.removeAll( persistenceManager, ProjectGroup.class );
167         PlexusJdoUtils.removeAll( persistenceManager, Project.class );
168         PlexusJdoUtils.removeAll( persistenceManager, Schedule.class );
169         PlexusJdoUtils.removeAll( persistenceManager, ScmResult.class );
170         PlexusJdoUtils.removeAll( persistenceManager, BuildResult.class );
171         PlexusJdoUtils.removeAll( persistenceManager, TestResult.class );
172         PlexusJdoUtils.removeAll( persistenceManager, SuiteResult.class );
173         PlexusJdoUtils.removeAll( persistenceManager, TestCaseFailure.class );
174         PlexusJdoUtils.removeAll( persistenceManager, SystemConfiguration.class );
175         PlexusJdoUtils.removeAll( persistenceManager, ProjectNotifier.class );
176         PlexusJdoUtils.removeAll( persistenceManager, ProjectDeveloper.class );
177         PlexusJdoUtils.removeAll( persistenceManager, ProjectDependency.class );
178         PlexusJdoUtils.removeAll( persistenceManager, ChangeSet.class );
179         PlexusJdoUtils.removeAll( persistenceManager, ChangeFile.class );
180         PlexusJdoUtils.removeAll( persistenceManager, BuildDefinition.class );
181     }
182 
183     private PersistenceManager getPersistenceManager( PersistenceManagerFactory pmf )
184     {
185         PersistenceManager pm = pmf.getPersistenceManager();
186 
187         pm.getFetchPlan().setMaxFetchDepth( -1 );
188         pm.getFetchPlan().setDetachmentOptions( FetchPlan.DETACH_LOAD_FIELDS );
189 
190         return pm;
191     }
192 
193     public void restoreDatabase( File backupDirectory, boolean strict )
194         throws IOException
195     {
196         ContinuumStaxReader reader = new ContinuumStaxReader();
197 
198         FileReader fileReader = new FileReader( new File( backupDirectory, BUILDS_XML ) );
199 
200         ContinuumDatabase database;
201         try
202         {
203             database = reader.read( fileReader, strict );
204         }
205         catch ( XMLStreamException e )
206         {
207             throw new DataManagementException( e );
208         }
209         finally
210         {
211             IOUtil.close( fileReader );
212         }
213 
214         PersistenceManagerFactory pmf = getPersistenceManagerFactory( "jdorepl109" );
215 
216         PlexusJdoUtils.addObject( pmf.getPersistenceManager(), database.getSystemConfiguration() );
217 
218         Map<Integer, Schedule> schedules = new HashMap<Integer, Schedule>();
219         for ( Iterator i = database.getSchedules().iterator(); i.hasNext(); )
220         {
221             Schedule schedule = (Schedule) i.next();
222 
223             schedule = (Schedule) PlexusJdoUtils.addObject( pmf.getPersistenceManager(), schedule );
224             schedules.put( Integer.valueOf( schedule.getId() ), schedule );
225         }
226 
227         for ( Iterator i = database.getProjectGroups().iterator(); i.hasNext(); )
228         {
229             ProjectGroup projectGroup = (ProjectGroup) i.next();
230 
231             // first, we must map up any schedules, etc.
232             processBuildDefinitions( projectGroup.getBuildDefinitions(), schedules );
233 
234             for ( Iterator j = projectGroup.getProjects().iterator(); j.hasNext(); )
235             {
236                 Project project = (Project) j.next();
237 
238                 processBuildDefinitions( project.getBuildDefinitions(), schedules );
239             }
240 
241             PlexusJdoUtils.addObject( pmf.getPersistenceManager(), projectGroup );
242         }
243         pmf.close();
244     }
245 
246     private PersistenceManagerFactory getPersistenceManagerFactory( String ext )
247     {
248         // Take control of the JDO instead of using the store, and configure a new persistence factory
249         // that won't generate new object IDs.
250         Properties properties = new Properties();
251         //noinspection UseOfPropertiesAsHashtable
252         properties.putAll( factory.getProperties() );
253         properties.setProperty( "org.jpox.metadata.jdoFileExtension", ext );
254         return JDOHelper.getPersistenceManagerFactory( properties );
255     }
256 
257     private static void processBuildDefinitions( List buildDefinitions, Map<Integer, Schedule> schedules )
258     {
259         for ( Iterator i = buildDefinitions.iterator(); i.hasNext(); )
260         {
261             BuildDefinition def = (BuildDefinition) i.next();
262 
263             if ( def.getSchedule() != null )
264             {
265                 def.setSchedule( schedules.get( Integer.valueOf( def.getSchedule().getId() ) ) );
266             }
267         }
268     }
269 }