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 java.util.Map; 23 import java.util.Objects; 24 25 /** 26 * Maven 2 Index record. 27 * 28 * @since 5.1.2 29 */ 30 public final class Record 31 { 32 /** 33 * Entry key is field key with some metadata. 34 * 35 * @param <T> The type of the value belonging to this key instance. 36 */ 37 public static final class EntryKey<T> 38 { 39 private final String name; 40 41 private final Class<T> proto; 42 43 public EntryKey( final String name, final Class<T> proto ) 44 { 45 Objects.requireNonNull( name, "name is null" ); 46 Objects.requireNonNull( proto, "proto is null" ); 47 this.name = name; 48 this.proto = proto; 49 } 50 51 public T coerce( final Object object ) 52 { 53 return proto.cast( object ); 54 } 55 56 public String getName() 57 { 58 return name; 59 } 60 61 @Override 62 public boolean equals( Object o ) 63 { 64 if ( this == o ) 65 { 66 return true; 67 } 68 if ( o == null || getClass() != o.getClass() ) 69 { 70 return false; 71 } 72 EntryKey<?> entryKey = (EntryKey<?>) o; 73 return Objects.equals( name, entryKey.name ); 74 } 75 76 @Override 77 public int hashCode() 78 { 79 return Objects.hash( name ); 80 } 81 82 @Override 83 public String toString() 84 { 85 return "Key{" + "name='" + name + '\'' + ", type=" + proto.getSimpleName() + '}'; 86 } 87 } 88 89 /** 90 * Key of repository ID entry, that contains {@link String}. 91 */ 92 public static final EntryKey<String> REPOSITORY_ID = new EntryKey<>( "repositoryId", String.class ); 93 94 /** 95 * Key of all groups list entry, that contains {@link java.util.List<String>}. 96 */ 97 public static final EntryKey<String[]> ALL_GROUPS = new EntryKey<>( "allGroups", String[].class ); 98 99 /** 100 * Key of root groups list entry, that contains {@link java.util.List<String>}. 101 */ 102 public static final EntryKey<String[]> ROOT_GROUPS = new EntryKey<>( "rootGroups", String[].class ); 103 104 /** 105 * Key of index record modification (added to index or removed from index) timestamp entry, that contains {@link 106 * Long}. 107 */ 108 public static final EntryKey<Long> REC_MODIFIED = new EntryKey<>( "recordModified", Long.class ); 109 110 /** 111 * Key of artifact groupId entry, that contains {@link String}. 112 */ 113 public static final EntryKey<String> GROUP_ID = new EntryKey<>( "groupId", String.class ); 114 115 /** 116 * Key of artifact artifactId entry, that contains {@link String}. 117 */ 118 public static final EntryKey<String> ARTIFACT_ID = new EntryKey<>( "artifactId", String.class ); 119 120 /** 121 * Key of artifact version entry, that contains {@link String}. 122 */ 123 public static final EntryKey<String> VERSION = new EntryKey<>( "version", String.class ); 124 125 /** 126 * Key of artifact classifier entry, that contains {@link String}. 127 */ 128 public static final EntryKey<String> CLASSIFIER = new EntryKey<>( "classifier", String.class ); 129 130 /** 131 * Key of artifact packaging entry, that contains {@link String}. 132 */ 133 public static final EntryKey<String> PACKAGING = new EntryKey<>( "packaging", String.class ); 134 135 /** 136 * Key of artifact file extension, that contains {@link String}. 137 */ 138 public static final EntryKey<String> FILE_EXTENSION = new EntryKey<>( "fileExtension", String.class ); 139 140 /** 141 * Key of artifact file last modified timestamp, that contains {@link Long}. 142 */ 143 public static final EntryKey<Long> FILE_MODIFIED = new EntryKey<>( "fileModified", Long.class ); 144 145 /** 146 * Key of artifact file size in bytes, that contains {@link Long}. 147 */ 148 public static final EntryKey<Long> FILE_SIZE = new EntryKey<>( "fileSize", Long.class ); 149 150 /** 151 * Key of artifact Sources presence flag, that contains {@link Boolean}. 152 */ 153 public static final EntryKey<Boolean> HAS_SOURCES = new EntryKey<>( "hasSources", Boolean.class ); 154 155 /** 156 * Key of artifact Javadoc presence flag, that contains {@link Boolean}. 157 */ 158 public static final EntryKey<Boolean> HAS_JAVADOC = new EntryKey<>( "hasJavadoc", Boolean.class ); 159 160 /** 161 * Key of artifact signature presence flag, that contains {@link Boolean}. 162 */ 163 public static final EntryKey<Boolean> HAS_SIGNATURE = new EntryKey<>( "hasSignature", Boolean.class ); 164 165 /** 166 * Key of artifact name (as set in POM), that contains {@link String}. 167 */ 168 public static final EntryKey<String> NAME = new EntryKey<>( "name", String.class ); 169 170 /** 171 * Key of artifact description (as set in POM), that contains {@link String}. 172 */ 173 public static final EntryKey<String> DESCRIPTION = new EntryKey<>( "description", String.class ); 174 175 /** 176 * Key of artifact SHA1 digest, that contains {@link String}. 177 */ 178 public static final EntryKey<String> SHA1 = new EntryKey<>( "sha1", String.class ); 179 180 /** 181 * Key of artifact contained class names, that contains {@link java.util.List<String>}. Extracted by {@code 182 * JarFileContentsIndexCreator}. 183 */ 184 public static final EntryKey<String[]> CLASSNAMES = new EntryKey<>( "classNames", String[].class ); 185 186 /** 187 * Key of plugin artifact prefix, that contains {@link String}. Extracted by {@code 188 * MavenPluginArtifactInfoIndexCreator}. 189 */ 190 public static final EntryKey<String> PLUGIN_PREFIX = new EntryKey<>( "pluginPrefix", String.class ); 191 192 /** 193 * Key of plugin artifact goals, that contains {@link java.util.List<String>}. Extracted by {@code 194 * MavenPluginArtifactInfoIndexCreator}. 195 */ 196 public static final EntryKey<String[]> PLUGIN_GOALS = new EntryKey<>( "pluginGoals", String[].class ); 197 198 /** 199 * Key of OSGi "Bundle-SymbolicName" manifest entry, that contains {@link String}. Extracted by {@code 200 * OsgiArtifactIndexCreator}. 201 */ 202 public static final EntryKey<String> OSGI_BUNDLE_SYMBOLIC_NAME = new EntryKey<>( "Bundle-SymbolicName", 203 String.class ); 204 205 /** 206 * Key of OSGi "Bundle-Version" manifest entry, that contains {@link String}. Extracted by {@code 207 * OsgiArtifactIndexCreator}. 208 */ 209 public static final EntryKey<String> OSGI_BUNDLE_VERSION = new EntryKey<>( "Bundle-Version", String.class ); 210 211 /** 212 * Key of OSGi "Export-Package" manifest entry, that contains {@link String}. Extracted by {@code 213 * OsgiArtifactIndexCreator}. 214 */ 215 public static final EntryKey<String> OSGI_EXPORT_PACKAGE = new EntryKey<>( "Export-Package", String.class ); 216 217 /** 218 * Key of OSGi "Export-Service" manifest entry, that contains {@link String}. Extracted by {@code 219 * OsgiArtifactIndexCreator}. 220 */ 221 public static final EntryKey<String> OSGI_EXPORT_SERVICE = new EntryKey<>( "Export-Service", String.class ); 222 223 /** 224 * Key of OSGi "Bundle-Description" manifest entry, that contains {@link String}. Extracted by {@code 225 * OsgiArtifactIndexCreator}. 226 */ 227 public static final EntryKey<String> OSGI_BUNDLE_DESCRIPTION = new EntryKey<>( "Bundle-Description", String.class ); 228 229 /** 230 * Key of OSGi "Bundle-Name" manifest entry, that contains {@link String}. Extracted by {@code 231 * OsgiArtifactIndexCreator}. 232 */ 233 public static final EntryKey<String> OSGI_BUNDLE_NAME = new EntryKey<>( "Bundle-Name", String.class ); 234 235 /** 236 * Key of OSGi "Bundle-License" manifest entry, that contains {@link String}. Extracted by {@code 237 * OsgiArtifactIndexCreator}. 238 */ 239 public static final EntryKey<String> OSGI_BUNDLE_LICENSE = new EntryKey<>( "Bundle-License", String.class ); 240 241 /** 242 * Key of OSGi "Bundle-DocURL" manifest entry, that contains {@link String}. Extracted by {@code 243 * OsgiArtifactIndexCreator}. 244 */ 245 public static final EntryKey<String> OSGI_EXPORT_DOCURL = new EntryKey<>( "Bundle-DocURL", String.class ); 246 247 /** 248 * Key of OSGi "Import-Package" manifest entry, that contains {@link String}. Extracted by {@code 249 * OsgiArtifactIndexCreator}. 250 */ 251 public static final EntryKey<String> OSGI_IMPORT_PACKAGE = new EntryKey<>( "Import-Package", String.class ); 252 253 /** 254 * Key of OSGi "Require-Bundle" manifest entry, that contains {@link String}. Extracted by {@code 255 * OsgiArtifactIndexCreator}. 256 */ 257 public static final EntryKey<String> OSGI_REQUIRE_BUNDLE = new EntryKey<>( "Require-Bundle", String.class ); 258 259 /** 260 * Key of OSGi "Provide-Capability" manifest entry, that contains {@link String}. Extracted by {@code 261 * OsgiArtifactIndexCreator}. 262 */ 263 public static final EntryKey<String> OSGI_PROVIDE_CAPABILITY = new EntryKey<>( "Provide-Capability", String.class ); 264 265 /** 266 * Key of OSGi "Require-Capability" manifest entry, that contains {@link String}. Extracted by {@code 267 * OsgiArtifactIndexCreator}. 268 */ 269 public static final EntryKey<String> OSGI_REQUIRE_CAPABILITY = new EntryKey<>( "Require-Capability", String.class ); 270 271 /** 272 * Key of OSGi "Fragment-Host" manifest entry, that contains {@link String}. Extracted by {@code 273 * OsgiArtifactIndexCreator}. 274 */ 275 public static final EntryKey<String> OSGI_FRAGMENT_HOST = new EntryKey<>( "Fragment-Host", String.class ); 276 277 /** 278 * Key of deprecated OSGi "Bundle-RequiredExecutionEnvironment" manifest entry, that contains {@link String}. 279 * Extracted by {@code OsgiArtifactIndexCreator}. 280 */ 281 public static final EntryKey<String> OSGI_BREE = new EntryKey<>( "Bundle-RequiredExecutionEnvironment", 282 String.class ); 283 284 /** 285 * Key for SHA-256 checksum needed for OSGI content capability that contains {@link String}. Extracted by {@code 286 * OsgiArtifactIndexCreator}. 287 */ 288 public static final EntryKey<String> SHA_256 = new EntryKey<>( "sha256", String.class ); 289 290 291 /** 292 * Types of returned records returned from index. 293 */ 294 public enum Type 295 { 296 /** 297 * Descriptor record. Can be safely ignored. 298 * Contains following entries: 299 * <ul> 300 * <li>{@link #REPOSITORY_ID}</li> 301 * </ul> 302 */ 303 DESCRIPTOR, 304 305 /** 306 * Artifact ADD record. Records of this type should be added to your indexing system. 307 * Contains following entries: 308 * <ul> 309 * <li>{@link #REC_MODIFIED} (when record was added/modified on index)</li> 310 * <li>{@link #GROUP_ID}</li> 311 * <li>{@link #ARTIFACT_ID}</li> 312 * <li>{@link #VERSION}</li> 313 * <li>{@link #CLASSIFIER} (optional)</li> 314 * <li>{@link #FILE_EXTENSION}</li> 315 * <li>{@link #FILE_MODIFIED}</li> 316 * <li>{@link #FILE_SIZE}</li> 317 * <li>{@link #PACKAGING}</li> 318 * <li>{@link #HAS_SOURCES}</li> 319 * <li>{@link #HAS_JAVADOC}</li> 320 * <li>{@link #HAS_SIGNATURE}</li> 321 * <li>{@link #NAME}</li> 322 * <li>{@link #DESCRIPTION}</li> 323 * <li>{@link #SHA1}</li> 324 * <li>{@link #CLASSNAMES} (optional)</li> 325 * <li>{@link #PLUGIN_PREFIX} (optional, for maven-plugins only)</li> 326 * <li>{@link #PLUGIN_GOALS} (optional, for maven-plugins only)</li> 327 * </ul> 328 */ 329 ARTIFACT_ADD, 330 331 /** 332 * Artifact REMOVE record. In case of incremental updates, signals that this artifact was removed. Records of 333 * this type should be removed from your indexing system. 334 * Contains following entries: 335 * <ul> 336 * <li>{@link #REC_MODIFIED} (when record was deleted from index)</li> 337 * <li>{@link #GROUP_ID}</li> 338 * <li>{@link #ARTIFACT_ID}</li> 339 * <li>{@link #VERSION}</li> 340 * <li>{@link #CLASSIFIER} (optional)</li> 341 * <li>{@link #FILE_EXTENSION} (if {@link #CLASSIFIER} present)</li> 342 * <li>{@link #PACKAGING} (optional)</li> 343 * </ul> 344 */ 345 ARTIFACT_REMOVE, 346 347 /** 348 * Special record, containing all the Maven "groupId"s that are enlisted on the index. Can be safely ignored. 349 * Contains following entries: 350 * <ul> 351 * <li>{@link #ALL_GROUPS}</li> 352 * </ul> 353 */ 354 ALL_GROUPS, 355 356 /** 357 * Special record, containing all the root groups of Maven "groupId"s that are enlisted on the index. Can be 358 * safely ignored. 359 * Contains following entries: 360 * <ul> 361 * <li>{@link #ROOT_GROUPS}</li> 362 * </ul> 363 */ 364 ROOT_GROUPS 365 } 366 367 private final Type type; 368 369 private final Map<EntryKey, Object> expanded; 370 371 public Record( final Type type, final Map<EntryKey, Object> expanded ) 372 { 373 this.type = type; 374 this.expanded = expanded; 375 } 376 377 /** 378 * Returns the {@link Type} of this record. Usually users would be interested in {@link Type#ARTIFACT_ADD} and 379 * {@link Type#ARTIFACT_REMOVE} types only to maintain their own index. Still, indexer offers extra records too, 380 * see {@link Type} for all existing types. 381 */ 382 public Type getType() 383 { 384 return type; 385 } 386 387 /** 388 * Returns the expanded (processed and expanded synthetic fields) record as {@link Map} ready for consumption. 389 */ 390 public Map<EntryKey, Object> getExpanded() 391 { 392 return expanded; 393 } 394 395 /** 396 * Returns {@code true} if this record contains given {@link EntryKey}. 397 */ 398 boolean containsKey( final EntryKey<?> entryKey ) 399 { 400 return expanded.containsKey( entryKey ); 401 } 402 403 /** 404 * Type safe handy method to get value from expanded map. 405 */ 406 public <T> T get( final EntryKey<T> entryKey ) 407 { 408 return entryKey.coerce( expanded.get( entryKey ) ); 409 } 410 411 /** 412 * Type safe handy method to put value to expanded map. Accepts {@code null} values, that removes the mapping. 413 */ 414 public <T> T put( final EntryKey<T> entryKey, final T value ) 415 { 416 if ( value == null ) 417 { 418 return entryKey.coerce( expanded.remove( entryKey ) ); 419 } 420 else 421 { 422 if ( !entryKey.proto.isAssignableFrom( value.getClass() ) ) 423 { 424 throw new IllegalArgumentException( "Key " + entryKey + " does not accepts value " + value ); 425 } 426 return entryKey.coerce( expanded.put( entryKey, value ) ); 427 } 428 } 429 430 @Override 431 public String toString() 432 { 433 return "Record{" + "type=" + type + ", expanded=" + expanded + '}'; 434 } 435 }