1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.felix.obrplugin;
20
21
22 import java.io.File;
23 import java.io.FileOutputStream;
24 import java.io.IOException;
25 import java.net.URI;
26 import java.text.SimpleDateFormat;
27 import java.util.ArrayList;
28 import java.util.Date;
29 import java.util.List;
30 import java.util.Properties;
31
32 import javax.xml.parsers.DocumentBuilder;
33 import javax.xml.parsers.DocumentBuilderFactory;
34 import javax.xml.parsers.ParserConfigurationException;
35 import javax.xml.transform.Result;
36 import javax.xml.transform.Transformer;
37 import javax.xml.transform.TransformerConfigurationException;
38 import javax.xml.transform.TransformerException;
39 import javax.xml.transform.TransformerFactory;
40 import javax.xml.transform.dom.DOMSource;
41 import javax.xml.transform.stream.StreamResult;
42
43 import org.apache.maven.artifact.repository.ArtifactRepository;
44 import org.apache.maven.plugin.AbstractMojo;
45 import org.apache.maven.plugin.MojoExecutionException;
46 import org.apache.maven.plugins.annotations.LifecyclePhase;
47 import org.apache.maven.plugins.annotations.Mojo;
48 import org.apache.maven.plugins.annotations.Parameter;
49 import org.codehaus.plexus.util.FileUtils;
50 import org.w3c.dom.Document;
51 import org.w3c.dom.Element;
52 import org.w3c.dom.Node;
53 import org.w3c.dom.NodeList;
54 import org.xml.sax.SAXException;
55
56
57
58
59
60
61
62 @Mojo( name = "clean", requiresProject = false, defaultPhase = LifecyclePhase.CLEAN )
63 public class ObrCleanRepo extends AbstractMojo
64 {
65
66
67
68 @Parameter( property = "obrRepository" )
69 private String obrRepository;
70
71
72
73
74 @Parameter( defaultValue = "${localRepository}", readonly = true, required = true )
75 private ArtifactRepository localRepository;
76
77
78 public void execute()
79 {
80 if ( "NONE".equalsIgnoreCase( obrRepository ) || "false".equalsIgnoreCase( obrRepository ) )
81 {
82 getLog().info( "Local OBR clean disabled (enable with -DobrRepository)" );
83 return;
84 }
85
86 try
87 {
88
89 URI repositoryXml = ObrUtils.findRepositoryXml( localRepository.getBasedir(), obrRepository );
90 if ( !"file".equals( repositoryXml.getScheme() ) )
91 {
92 getLog().error( "The repository URI " + repositoryXml + " is not a local file" );
93 return;
94 }
95
96 File repositoryFile = new File( repositoryXml );
97
98
99 if ( !repositoryFile.exists() )
100 {
101 getLog().error( "The repository file " + repositoryFile + " does not exist" );
102 return;
103 }
104
105 getLog().info( "Cleaning..." );
106
107 Document doc = parseFile( repositoryFile, initConstructor() );
108 Node finalDocument = cleanDocument( doc.getDocumentElement() );
109
110 if ( finalDocument == null )
111 {
112 getLog().info( "Nothing to clean in " + repositoryFile );
113 }
114 else
115 {
116 writeToFile( repositoryXml, finalDocument );
117 getLog().info( "Repository " + repositoryFile + " cleaned" );
118 }
119 }
120 catch ( Exception e )
121 {
122 getLog().error( "Exception while cleaning local OBR: " + e.getLocalizedMessage(), e );
123 }
124 }
125
126
127
128
129
130
131
132
133 private Element cleanDocument( Element elem )
134 {
135 String localRepoPath = localRepository.getBasedir();
136 URI baseURI = new File( localRepoPath + '/' ).toURI();
137 NodeList nodes = elem.getElementsByTagName( "resource" );
138 List toRemove = new ArrayList();
139
140
141 for ( int i = 0; i < nodes.getLength(); i++ )
142 {
143 Element n = ( Element ) nodes.item( i );
144 String value = n.getAttribute( "uri" );
145
146 URI resource;
147 try
148 {
149 resource = baseURI.resolve( value );
150 }
151 catch ( IllegalArgumentException e )
152 {
153 getLog().error( "Malformed URL when creating the resource absolute URI : " + e.getMessage() );
154 return null;
155 }
156
157 if ( "file".equals( resource.getScheme() ) && !new File( resource ).exists() )
158 {
159 getLog().info(
160 "The bundle " + n.getAttribute( "presentationname" ) + " - " + n.getAttribute( "version" )
161 + " will be removed" );
162 toRemove.add( n );
163 }
164 }
165
166 Date d = new Date();
167 if ( toRemove.size() > 0 )
168 {
169
170 for ( int i = 0; i < toRemove.size(); i++ )
171 {
172 elem.removeChild( ( Node ) toRemove.get( i ) );
173 }
174
175
176 SimpleDateFormat format = new SimpleDateFormat( "yyyyMMddHHmmss.SSS" );
177 d.setTime( System.currentTimeMillis() );
178 elem.setAttribute( "lastmodified", format.format( d ) );
179 return elem;
180 }
181
182 return null;
183 }
184
185
186
187
188
189
190
191
192 private DocumentBuilder initConstructor() throws MojoExecutionException
193 {
194 DocumentBuilder constructor = null;
195 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
196 try
197 {
198 constructor = factory.newDocumentBuilder();
199 }
200 catch ( ParserConfigurationException e )
201 {
202 getLog().error( "Unable to create a new xml document" );
203 throw new MojoExecutionException( "Cannot create the Document Builder : " + e.getMessage() );
204 }
205 return constructor;
206 }
207
208
209
210
211
212
213
214
215
216
217 private Document parseFile( File file, DocumentBuilder constructor ) throws MojoExecutionException
218 {
219 if ( constructor == null )
220 {
221 return null;
222 }
223
224 File targetFile = file.getAbsoluteFile();
225 getLog().info( "Parsing " + targetFile );
226 Document doc = null;
227 try
228 {
229 doc = constructor.parse( targetFile );
230 }
231 catch ( SAXException e )
232 {
233 getLog().error( "Cannot parse " + targetFile + " : " + e.getMessage() );
234 throw new MojoExecutionException( "Cannot parse " + targetFile + " : " + e.getMessage() );
235 }
236 catch ( IOException e )
237 {
238 getLog().error( "Cannot open " + targetFile + " : " + e.getMessage() );
239 throw new MojoExecutionException( "Cannot open " + targetFile + " : " + e.getMessage() );
240 }
241 return doc;
242 }
243
244
245
246
247
248
249
250
251
252 private void writeToFile( URI outputFilename, Node treeToBeWrite ) throws MojoExecutionException
253 {
254
255 Transformer transformer = null;
256 TransformerFactory tfabrique = TransformerFactory.newInstance();
257 try
258 {
259 transformer = tfabrique.newTransformer();
260 }
261 catch ( TransformerConfigurationException e )
262 {
263 getLog().error( "Unable to write to file: " + outputFilename.toString() );
264 throw new MojoExecutionException( "Unable to write to file: " + outputFilename.toString() + " : "
265 + e.getMessage() );
266 }
267 Properties proprietes = new Properties();
268 proprietes.put( "method", "xml" );
269 proprietes.put( "version", "1.0" );
270 proprietes.put( "encoding", "ISO-8859-1" );
271 proprietes.put( "standalone", "yes" );
272 proprietes.put( "indent", "yes" );
273 proprietes.put( "omit-xml-declaration", "no" );
274 transformer.setOutputProperties( proprietes );
275
276 DOMSource input = new DOMSource( treeToBeWrite );
277
278 File fichier = null;
279 FileOutputStream flux = null;
280 try
281 {
282 fichier = File.createTempFile( "repository", ".xml" );
283 flux = new FileOutputStream( fichier );
284 }
285 catch ( IOException e )
286 {
287 getLog().error( "Unable to write to file: " + fichier.getName() );
288 throw new MojoExecutionException( "Unable to write to file: " + fichier.getName() + " : " + e.getMessage() );
289 }
290 Result output = new StreamResult( flux );
291 try
292 {
293 transformer.transform( input, output );
294 }
295 catch ( TransformerException e )
296 {
297 throw new MojoExecutionException( "Unable to write to file: " + outputFilename.toString() + " : "
298 + e.getMessage() );
299 }
300
301 try
302 {
303 flux.flush();
304 flux.close();
305
306 FileUtils.rename( fichier, new File( outputFilename ) );
307 }
308 catch ( IOException e )
309 {
310 throw new MojoExecutionException( "IOException when closing file : " + e.getMessage() );
311 }
312 }
313 }