View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.felix.obrplugin;
20  
21  
22  import java.io.File;
23  import java.io.FileFilter;
24  import java.io.FileWriter;
25  import java.io.IOException;
26  import java.io.Writer;
27  import java.net.URI;
28  import java.net.URISyntaxException;
29  import java.util.ArrayList;
30  import java.util.List;
31  
32  import org.apache.felix.bundlerepository.Property;
33  import org.apache.felix.bundlerepository.Resource;
34  import org.apache.felix.bundlerepository.impl.DataModelHelperImpl;
35  import org.apache.felix.bundlerepository.impl.RepositoryImpl;
36  import org.apache.felix.bundlerepository.impl.ResourceImpl;
37  import org.apache.maven.artifact.repository.ArtifactRepository;
38  import org.apache.maven.plugin.AbstractMojo;
39  import org.apache.maven.plugin.MojoExecutionException;
40  import org.apache.maven.plugin.logging.Log;
41  import org.apache.maven.plugins.annotations.Mojo;
42  import org.apache.maven.plugins.annotations.Parameter;
43  
44  
45  /**
46   * Index the content of a maven repository using OBR
47   *
48   * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
49   */
50  @Mojo( name = "index", requiresProject = false )
51  public final class ObrIndex extends AbstractMojo
52  {
53  
54      /**
55       * OBR Repository.
56       */
57      @Parameter( property = "obrRepository" )
58      private String obrRepository;
59  
60      /**
61       * Template for urls
62       */
63      @Parameter( property = "urlTemplate" )
64      private String urlTemplate;
65  
66      /**
67       * The repository to index
68       */
69      @Parameter( property = "mavenRepository" )
70      private String mavenRepository;
71  
72      /**
73       * Local Repository.
74       */
75      @Parameter( defaultValue = "${localRepository}", readonly = true, required = true )
76      private ArtifactRepository localRepository;
77  
78  
79      public void execute() throws MojoExecutionException
80      {
81          Log log = getLog();
82          try
83          {
84              log.info( "Indexing..." );
85  
86              String repo = mavenRepository;
87              if ( repo == null )
88              {
89                  repo = localRepository.getBasedir();
90              }
91              URI mavenRepoUri = new File( repo ).toURI();
92  
93              URI repositoryXml = ObrUtils.findRepositoryXml( repo, obrRepository );
94  
95              log.info( "Repository:   " + mavenRepoUri );
96              log.info( "OBR xml:      " + repositoryXml );
97              log.info( "URL template: " + urlTemplate );
98  
99              List<File> files = new ArrayList<File>();
100             findAllJars( new File( repo ), files );
101 
102             DataModelHelperImpl dmh = new DataModelHelperImpl();
103             RepositoryImpl repository;
104 
105             File obrRepoFile = new File( repositoryXml );
106             if ( obrRepoFile.isFile() )
107             {
108                 repository = ( RepositoryImpl ) dmh.repository( repositoryXml.toURL() );
109             }
110             else
111             {
112                 repository = new RepositoryImpl();
113             }
114 
115             for ( File file : files )
116             {
117                 try
118                 {
119                     ResourceImpl resource = ( ResourceImpl ) dmh.createResource( file.toURI().toURL() );
120                     if ( resource != null )
121                     {
122                         repository.addResource( resource );
123                         doTemplate( mavenRepoUri, file, resource );
124                         log.info( "Adding resource: " + file );
125                     }
126                     else
127                     {
128                         log.info( "Ignoring non OSGi bundle: " + file );
129                     }
130                 }
131                 catch ( Exception e )
132                 {
133                     log.warn( "Error processing bundle: " + file + " " + e.getMessage() );
134                 }
135             }
136             Writer writer = new FileWriter( obrRepoFile );
137             try
138             {
139                 dmh.writeRepository( repository, writer );
140             }
141             finally
142             {
143                 writer.close();
144             }
145         }
146         catch ( Exception e )
147         {
148             log.warn( "Exception while updating local OBR: " + e.getLocalizedMessage(), e );
149         }
150     }
151 
152 
153     protected void doTemplate( URI root, File path, ResourceImpl resource ) throws IOException, URISyntaxException
154     {
155         path = path.getAbsoluteFile().getCanonicalFile();
156         String finalUri = root.relativize( path.toURI() ).toString();
157         if ( "maven".equals( urlTemplate ) )
158         {
159             String dir = root.relativize( path.toURI() ).toString();
160             String[] p = dir.split( "/" );
161             if ( p.length >= 4 && p[p.length - 1].startsWith( p[p.length - 3] + "-" + p[p.length - 2] ) )
162             {
163                 String artifactId = p[p.length - 3];
164                 String version = p[p.length - 2];
165                 String classifier;
166                 String type;
167                 String artifactIdVersion = artifactId + "-" + version;
168                 StringBuffer sb = new StringBuffer();
169                 if ( p[p.length - 1].charAt( artifactIdVersion.length() ) == '-' )
170                 {
171                     classifier = p[p.length - 1].substring( artifactIdVersion.length() + 1,
172                         p[p.length - 1].lastIndexOf( '.' ) );
173                 }
174                 else
175                 {
176                     classifier = null;
177                 }
178                 type = p[p.length - 1].substring( p[p.length - 1].lastIndexOf( '.' ) + 1 );
179                 sb.append( "mvn:" );
180                 for ( int j = 0; j < p.length - 3; j++ )
181                 {
182                     if ( j > 0 )
183                     {
184                         sb.append( '.' );
185                     }
186                     sb.append( p[j] );
187                 }
188                 sb.append( '/' ).append( artifactId ).append( '/' ).append( version );
189                 if ( !"jar".equals( type ) || classifier != null )
190                 {
191                     sb.append( '/' );
192                     if ( !"jar".equals( type ) )
193                     {
194                         sb.append( type );
195                     }
196                     if ( classifier != null )
197                     {
198                         sb.append( '/' ).append( classifier );
199                     }
200                 }
201                 finalUri = sb.toString();
202             }
203         }
204         else if ( urlTemplate != null )
205         {
206             URI parentDir = path.getParentFile().toURI();
207 
208             String absoluteDir = trim( root.toString(), parentDir.toURL().toString() );
209             String relativeDir = trim( root.toString(), root.relativize( parentDir ).toString() );
210 
211             String url = urlTemplate.replaceAll( "%v", "" + resource.getVersion() );
212             url = url.replaceAll( "%s", resource.getSymbolicName() );
213             url = url.replaceAll( "%f", path.getName() );
214             url = url.replaceAll( "%p", absoluteDir );
215             url = url.replaceAll( "%rp", relativeDir );
216             finalUri = url;
217         }
218         resource.put( Resource.URI, finalUri, Property.URI );
219     }
220 
221 
222     private String trim( String prefix, String path )
223     {
224         if ( path.endsWith( "/" ) )
225             path = path.substring( 0, path.length() - 1 );
226 
227         if ( path.startsWith( prefix ) )
228             path = path.substring( prefix.length() );
229 
230         return path;
231     }
232 
233 
234     private final FileFilter filter = new FileFilter()
235     {
236         public boolean accept( File pathname )
237         {
238             return pathname.getName().endsWith( "ar" );
239         }
240     };
241 
242 
243     private void findAllJars( File mainRoot, List<File> files )
244     {
245         List<File> roots = new ArrayList<File>();
246         roots.add( mainRoot );
247         while ( !roots.isEmpty() )
248         {
249             File root = roots.remove( 0 );
250             File[] children = root.listFiles();
251             if ( children != null )
252             {
253                 for ( File child : children )
254                 {
255                     if ( child.isFile() && filter.accept( child ) )
256                     {
257                         files.add( child );
258                     }
259                     else if ( child.isDirectory() )
260                     {
261                         roots.add( child );
262                     }
263                 }
264             }
265         }
266     }
267 
268 }