package org.apache.maven.index.context; /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.HashSet; import java.util.List; import java.util.Set; import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.index.IndexWriter; import org.apache.lucene.search.IndexSearcher; import org.apache.lucene.store.Directory; import org.apache.lucene.store.FSDirectory; import org.apache.maven.index.artifact.GavCalculator; import org.apache.maven.index.artifact.M2GavCalculator; /** * A merged indexing context that offers read only "view" on multiple other indexing contexts merged and presented as * one. Usable for searching and publishing, but all write operations are basically noop. * * @author cstamas */ public class MergedIndexingContext extends AbstractIndexingContext { private final String id; private final String repositoryId; private final File repository; private final ContextMemberProvider membersProvider; private final GavCalculator gavCalculator; private final Directory directory; private File directoryFile; private boolean searchable; private MergedIndexingContext( ContextMemberProvider membersProvider, String id, String repositoryId, File repository, Directory indexDirectory, boolean searchable ) throws IOException { this.id = id; this.repositoryId = repositoryId; this.repository = repository; this.membersProvider = membersProvider; this.gavCalculator = new M2GavCalculator(); this.directory = indexDirectory; this.searchable = searchable; setIndexDirectoryFile( null ); } public MergedIndexingContext( String id, String repositoryId, File repository, File indexDirectoryFile, boolean searchable, ContextMemberProvider membersProvider ) throws IOException { this( membersProvider, id, repositoryId, repository, FSDirectory.open( indexDirectoryFile.toPath() ), searchable ); setIndexDirectoryFile( indexDirectoryFile ); } @Deprecated public MergedIndexingContext( String id, String repositoryId, File repository, Directory indexDirectory, boolean searchable, ContextMemberProvider membersProvider ) throws IOException { this( membersProvider, id, repositoryId, repository, indexDirectory, searchable ); if ( indexDirectory instanceof FSDirectory ) { setIndexDirectoryFile( ( (FSDirectory) indexDirectory ).getDirectory().toFile() ); } } public Collection<IndexingContext> getMembers() { return membersProvider.getMembers(); } public String getId() { return id; } public String getRepositoryId() { return repositoryId; } public File getRepository() { return repository; } public String getRepositoryUrl() { return null; } public String getIndexUpdateUrl() { return null; } public boolean isSearchable() { return searchable; } public void setSearchable( boolean searchable ) { this.searchable = searchable; } public Date getTimestamp() { Date ts = null; for ( IndexingContext ctx : getMembers() ) { Date cts = ctx.getTimestamp(); if ( cts != null ) { if ( ts == null || cts.after( ts ) ) { ts = cts; } } } return ts; } public void updateTimestamp() throws IOException { // noop } public void updateTimestamp( boolean save ) throws IOException { // noop } public void updateTimestamp( boolean save, Date date ) throws IOException { // noop } public int getSize() throws IOException { int size = 0; for ( IndexingContext ctx : getMembers() ) { size += ctx.getSize(); } return size; } public IndexSearcher acquireIndexSearcher() throws IOException { final NexusIndexMultiReader mr = new NexusIndexMultiReader( getMembers() ); return new NexusIndexMultiSearcher( mr ); } public void releaseIndexSearcher( IndexSearcher indexSearcher ) throws IOException { if ( indexSearcher instanceof NexusIndexMultiSearcher ) { ( (NexusIndexMultiSearcher) indexSearcher ).release(); } else { throw new IllegalArgumentException( String.format( "Illegal argument to merged idexing context: it emits class %s but and cannot release class %s!", NexusIndexMultiSearcher.class.getName(), indexSearcher.getClass().getName() ) ); } } public IndexWriter getIndexWriter() throws IOException { throw new UnsupportedOperationException( getClass().getName() + " indexing context is read-only!" ); } public List<IndexCreator> getIndexCreators() { HashSet<IndexCreator> creators = new HashSet<IndexCreator>(); for ( IndexingContext ctx : getMembers() ) { creators.addAll( ctx.getIndexCreators() ); } return new ArrayList<IndexCreator>( creators ); } public Analyzer getAnalyzer() { return new NexusAnalyzer(); } public void commit() throws IOException { // noop } public void rollback() throws IOException { // noop } public void optimize() throws IOException { // noop } public void close( boolean deleteFiles ) throws IOException { // noop } public void purge() throws IOException { // noop } public void merge( Directory directory ) throws IOException { // noop } public void merge( Directory directory, DocumentFilter filter ) throws IOException { // noop } public void replace( Directory directory ) throws IOException { // noop } public void replace( Directory directory, Set<String> allGroups, Set<String> rootGroups ) throws IOException { // noop } public Directory getIndexDirectory() { return directory; } public File getIndexDirectoryFile() { return directoryFile; } /** * Sets index location. As usually index is persistent (is on disk), this will point to that value, but in * some circumstances (ie, using RAMDisk for index), this will point to an existing tmp directory. */ protected void setIndexDirectoryFile(File dir) throws IOException { if ( dir == null ) { // best effort, to have a directory thru the life of a ctx File tmpFile = File.createTempFile( "mindexer-ctx" + id, "tmp" ); tmpFile.delete(); tmpFile.mkdirs(); this.directoryFile = tmpFile; } else { this.directoryFile = dir; } } public GavCalculator getGavCalculator() { return gavCalculator; } public void setAllGroups( Collection<String> groups ) throws IOException { // noop } public Set<String> getAllGroups() throws IOException { HashSet<String> result = new HashSet<String>(); for ( IndexingContext ctx : getMembers() ) { result.addAll( ctx.getAllGroups() ); } return result; } public void setRootGroups( Collection<String> groups ) throws IOException { // noop } public Set<String> getRootGroups() throws IOException { HashSet<String> result = new HashSet<String>(); for ( IndexingContext ctx : getMembers() ) { result.addAll( ctx.getRootGroups() ); } return result; } public void rebuildGroups() throws IOException { // noop } }