View Javadoc
1   package org.apache.maven.index.reader;
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.index.reader.Record.EntryKey;
23  import org.apache.maven.index.reader.Record.Type;
24  
25  import java.util.HashMap;
26  import java.util.Map;
27  
28  import static org.apache.maven.index.reader.Utils.FIELD_SEPARATOR;
29  import static org.apache.maven.index.reader.Utils.FS_PATTERN;
30  import static org.apache.maven.index.reader.Utils.INFO;
31  import static org.apache.maven.index.reader.Utils.NOT_AVAILABLE;
32  import static org.apache.maven.index.reader.Utils.UINFO;
33  import static org.apache.maven.index.reader.Utils.renvl;
34  
35  
36  /**
37   * Maven 2 Index record transformer, that transforms "native" Maven Indexer records into {@link Record}s.
38   *
39   * @since 5.1.2
40   */
41  public class RecordExpander
42  {
43      /**
44       * Expands MI low level record into {@link Record}.
45       */
46      public Record apply( final Map<String, String> recordMap )
47      {
48          if ( recordMap.containsKey( "DESCRIPTOR" ) )
49          {
50              return expandDescriptor( recordMap );
51          }
52          else if ( recordMap.containsKey( "allGroups" ) )
53          {
54              return expandAllGroups( recordMap );
55          }
56          else if ( recordMap.containsKey( "rootGroups" ) )
57          {
58              return expandRootGroups( recordMap );
59          }
60          else if ( recordMap.containsKey( "del" ) )
61          {
62              return expandDeletedArtifact( recordMap );
63          }
64          else
65          {
66              // Fix up UINFO field wrt MINDEXER-41
67              final String uinfo = recordMap.get( UINFO );
68              final String info = recordMap.get( INFO );
69              if ( uinfo != null && !( info == null || info.trim().length() == 0 ) )
70              {
71                  final String[] splitInfo = FS_PATTERN.split( info );
72                  if ( splitInfo.length > 6 )
73                  {
74                      final String extension = splitInfo[6];
75                      if ( uinfo.endsWith( FIELD_SEPARATOR + NOT_AVAILABLE ) )
76                      {
77                          recordMap.put( UINFO, uinfo + FIELD_SEPARATOR + extension );
78                      }
79                  }
80              }
81              return expandAddedArtifact( recordMap );
82          }
83      }
84  
85      private static Record expandDescriptor( final Map<String, String> raw )
86      {
87          final Record result = new Record( Type.DESCRIPTOR, new HashMap<>() );
88          String[] r = FS_PATTERN.split( raw.get( "IDXINFO" ) );
89          result.put( Record.REPOSITORY_ID, r[1] );
90          return result;
91      }
92  
93      private static Record expandAllGroups( final Map<String, String> raw )
94      {
95          final Record result = new Record( Type.ALL_GROUPS, new HashMap<>() );
96          putIfNotNullAsStringArray( raw, "allGroupsList", result, Record.ALL_GROUPS );
97          return result;
98      }
99  
100     private static Record expandRootGroups( final Map<String, String> raw )
101     {
102         final Record result = new Record( Type.ROOT_GROUPS, new HashMap<>() );
103         putIfNotNullAsStringArray( raw, "rootGroupsList", result, Record.ROOT_GROUPS );
104         return result;
105     }
106 
107     private static Record expandDeletedArtifact( final Map<String, String> raw )
108     {
109         final Record result = new Record( Type.ARTIFACT_REMOVE, new HashMap<>() );
110         putIfNotNullTS( raw, "m", result, Record.REC_MODIFIED );
111         if ( raw.containsKey( "del" ) )
112         {
113             expandUinfo( raw.get( "del" ), result );
114         }
115         return result;
116     }
117 
118     /**
119      * Expands the "encoded" Maven Indexer record by splitting the synthetic fields and applying expanded field naming.
120      */
121     private static Record expandAddedArtifact( final Map<String, String> raw )
122     {
123         final Record result = new Record( Type.ARTIFACT_ADD, new HashMap<>() );
124 
125         // Minimal
126         expandUinfo( raw.get( UINFO ), result );
127         final String info = raw.get( INFO );
128         if ( info != null )
129         {
130             String[] r = FS_PATTERN.split( info );
131             result.put( Record.PACKAGING, renvl( r[0] ) );
132             result.put( Record.FILE_MODIFIED, Long.valueOf( r[1] ) );
133             result.put( Record.FILE_SIZE, Long.valueOf( r[2] ) );
134             result.put( Record.HAS_SOURCES, "1".equals( r[3] ) ? Boolean.TRUE : Boolean.FALSE );
135             result.put( Record.HAS_JAVADOC, "1".equals( r[4] ) ? Boolean.TRUE : Boolean.FALSE );
136             result.put( Record.HAS_SIGNATURE, "1".equals( r[5] ) ? Boolean.TRUE : Boolean.FALSE );
137             if ( r.length > 6 )
138             {
139                 result.put( Record.FILE_EXTENSION, r[6] );
140             }
141             else
142             {
143                 final String packaging = Record.PACKAGING.coerce( result.get( Record.PACKAGING ) );
144                 if ( result.containsKey( Record.CLASSIFIER ) || "pom".equals( packaging ) || "war".equals( packaging )
145                     || "ear".equals( packaging ) )
146                 {
147                     result.put( Record.FILE_EXTENSION, packaging );
148                 }
149                 else
150                 {
151                     result.put( Record.FILE_EXTENSION, "jar" ); // best guess
152                 }
153             }
154         }
155         putIfNotNullTS( raw, "m", result, Record.REC_MODIFIED );
156         putIfNotNull( raw, "n", result, Record.NAME );
157         putIfNotNull( raw, "d", result, Record.DESCRIPTION );
158         putIfNotNull( raw, "1", result, Record.SHA1 );
159 
160         // Jar file contents (optional)
161         putIfNotNullAsStringArray( raw, "classnames", result, Record.CLASSNAMES );
162 
163         // Maven Plugin (optional)
164         putIfNotNull( raw, "px", result, Record.PLUGIN_PREFIX );
165         putIfNotNullAsStringArray( raw, "gx", result, Record.PLUGIN_GOALS );
166 
167         // OSGi (optional)
168         putIfNotNull( raw, "Bundle-SymbolicName", result, Record.OSGI_BUNDLE_SYMBOLIC_NAME );
169         putIfNotNull( raw, "Bundle-Version", result, Record.OSGI_BUNDLE_VERSION );
170         putIfNotNull( raw, "Export-Package", result, Record.OSGI_EXPORT_PACKAGE );
171         putIfNotNull( raw, "Export-Service", result, Record.OSGI_EXPORT_SERVICE );
172         putIfNotNull( raw, "Bundle-Description", result, Record.OSGI_BUNDLE_DESCRIPTION );
173         putIfNotNull( raw, "Bundle-Name", result, Record.OSGI_BUNDLE_NAME );
174         putIfNotNull( raw, "Bundle-License", result, Record.OSGI_BUNDLE_LICENSE );
175         putIfNotNull( raw, "Bundle-DocURL", result, Record.OSGI_EXPORT_DOCURL );
176         putIfNotNull( raw, "Import-Package", result, Record.OSGI_IMPORT_PACKAGE );
177         putIfNotNull( raw, "Require-Bundle", result, Record.OSGI_REQUIRE_BUNDLE );
178         putIfNotNull( raw, "Provide-Capability", result, Record.OSGI_PROVIDE_CAPABILITY );
179         putIfNotNull( raw, "Require-Capability", result, Record.OSGI_REQUIRE_CAPABILITY );
180         putIfNotNull( raw, "Fragment-Host", result, Record.OSGI_FRAGMENT_HOST );
181         putIfNotNull( raw, "Bundle-RequiredExecutionEnvironment", result, Record.OSGI_BREE );
182         putIfNotNull( raw, "sha256", result, Record.SHA_256 );
183 
184         return result;
185     }
186 
187     /**
188      * Expands UINFO synthetic field. Handles {@code null} String inputs.
189      */
190     private static void expandUinfo( final String uinfo, final Record result )
191     {
192         if ( uinfo != null )
193         {
194             String[] r = FS_PATTERN.split( uinfo );
195             result.put( Record.GROUP_ID, r[0] );
196             result.put( Record.ARTIFACT_ID, r[1] );
197             result.put( Record.VERSION, r[2] );
198             String classifier = renvl( r[3] );
199             if ( classifier != null )
200             {
201                 result.put( Record.CLASSIFIER, classifier );
202                 if ( r.length > 4 )
203                 {
204                     result.put( Record.FILE_EXTENSION, r[4] );
205                 }
206             }
207             else if ( r.length > 4 )
208             {
209                 result.put( Record.PACKAGING, r[4] );
210             }
211         }
212     }
213 
214     /**
215      * Helper to put a value from source map into target map, if not null.
216      */
217     private static void putIfNotNull( final Map<String, String> source, final String sourceName, final Record target,
218                                       final EntryKey targetName )
219     {
220         String value = source.get( sourceName );
221         if ( value != null && value.trim().length() != 0 )
222         {
223             target.put( targetName, value );
224         }
225     }
226 
227     /**
228      * Helper to put a {@link Long} value from source map into target map, if not null.
229      */
230     private static void putIfNotNullTS( final Map<String, String> source, final String sourceName, final Record target,
231                                         final EntryKey targetName )
232     {
233         String value = source.get( sourceName );
234         if ( value != null && value.trim().length() != 0 )
235         {
236             target.put( targetName, Long.valueOf( value ) );
237         }
238     }
239 
240     /**
241      * Helper to put a collection value from source map into target map as {@link java.util.List}, if not null.
242      */
243     private static void putIfNotNullAsStringArray( final Map<String, String> source, final String sourceName,
244                                                    final Record target, final EntryKey targetName )
245     {
246         String value = source.get( sourceName );
247         if ( value != null && value.trim().length() != 0 )
248         {
249             target.put( targetName, FS_PATTERN.split( value ) );
250         }
251     }
252 }