1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * See LICENSE.txt included in this distribution for the specific 9 * language governing permissions and limitations under the License. 10 * 11 * When distributing Covered Code, include this CDDL HEADER in each 12 * file and include the License file at LICENSE.txt. 13 * If applicable, add the following below this CDDL HEADER, with the 14 * fields enclosed by brackets "[]" replaced with your own identifying 15 * information: Portions Copyright [yyyy] [name of copyright owner] 16 * 17 * CDDL HEADER END 18 */ 19 20 /* 21 * Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved. 22 * Portions Copyright (c) 2011, Jens Elkner. 23 * Portions Copyright (c) 2017, 2019, Chris Fraire <cfraire@me.com>. 24 */ 25 package org.opengrok.indexer.search; 26 27 import org.apache.lucene.index.IndexReader; 28 import org.opengrok.indexer.configuration.Project; 29 import org.opengrok.indexer.index.IndexAnalysisSettings3; 30 import org.opengrok.indexer.index.IndexAnalysisSettingsAccessor; 31 import org.opengrok.indexer.index.IndexedSymlink; 32 33 import java.io.IOException; 34 import java.util.Collections; 35 import java.util.Comparator; 36 import java.util.HashMap; 37 import java.util.Map; 38 import java.util.TreeMap; 39 40 /** 41 * Represents a helper class for accessing settings. 42 * @author Jens Elkner 43 */ 44 public class SettingsHelper { 45 46 private final IndexReader reader; 47 48 /** 49 * Key is Project name or empty string for null Project. 50 */ 51 private Map<String, IndexAnalysisSettings3> mappedAnalysisSettings; 52 53 /** 54 * Key is Project name or empty string for null Project. Map is ordered by 55 * canonical length (ASC) and then canonical value (ASC). 56 */ 57 private Map<String, Map<String, IndexedSymlink>> mappedIndexedSymlinks; 58 SettingsHelper(IndexReader reader)59 public SettingsHelper(IndexReader reader) { 60 if (reader == null) { 61 throw new IllegalArgumentException("reader is null"); 62 } 63 this.reader = reader; 64 } 65 66 /** 67 * Gets any mapped symlinks (after having called {@link #getSettings(String)}). 68 * @return either a defined map or {@code null} 69 */ getSymlinks(String projectName)70 public Map<String, IndexedSymlink> getSymlinks(String projectName) throws IOException { 71 getSettings(projectName); 72 String projectKey = projectName != null ? projectName : ""; 73 Map<String, IndexedSymlink> indexSymlinks = mappedIndexedSymlinks.get(projectKey); 74 if (indexSymlinks != null) { 75 return Collections.unmodifiableMap(indexSymlinks); 76 } 77 return null; 78 } 79 80 /** 81 * Gets the persisted tabSize via {@link #getSettings(String)} if 82 * available or returns the {@code proj} tabSize if available -- or zero. 83 * @param proj a defined instance or {@code null} if no project is active 84 * @return tabSize 85 * @throws IOException if an I/O error occurs querying the initialized 86 * reader 87 */ getTabSize(Project proj)88 public int getTabSize(Project proj) throws IOException { 89 String projectName = proj != null ? proj.getName() : null; 90 IndexAnalysisSettings3 settings = getSettings(projectName); 91 int tabSize; 92 if (settings != null && settings.getTabSize() != null) { 93 tabSize = settings.getTabSize(); 94 } else { 95 tabSize = proj != null ? proj.getTabSize() : 0; 96 } 97 return tabSize; 98 } 99 100 /** 101 * Gets the settings for a specified project. 102 * @param projectName a defined instance or {@code null} if no project is 103 * active (or empty string to mean the same thing) 104 * @return a defined instance or {@code null} if none is found 105 * @throws IOException if an I/O error occurs querying the initialized reader 106 */ getSettings(String projectName)107 public IndexAnalysisSettings3 getSettings(String projectName) throws IOException { 108 if (mappedAnalysisSettings == null) { 109 IndexAnalysisSettingsAccessor dao = new IndexAnalysisSettingsAccessor(); 110 IndexAnalysisSettings3[] setts = dao.read(reader, Short.MAX_VALUE); 111 map(setts); 112 } 113 114 String projectKey = projectName != null ? projectName : ""; 115 return mappedAnalysisSettings.get(projectKey); 116 } 117 map(IndexAnalysisSettings3[] setts)118 private void map(IndexAnalysisSettings3[] setts) { 119 120 Map<String, IndexAnalysisSettings3> settingsMap = new HashMap<>(); 121 Map<String, Map<String, IndexedSymlink>> symlinksMap = new HashMap<>(); 122 123 for (IndexAnalysisSettings3 settings : setts) { 124 String projectName = settings.getProjectName(); 125 String projectKey = projectName != null ? projectName : ""; 126 settingsMap.put(projectKey, settings); 127 symlinksMap.put(projectKey, mapSymlinks(settings)); 128 } 129 mappedAnalysisSettings = settingsMap; 130 mappedIndexedSymlinks = symlinksMap; 131 } 132 mapSymlinks(IndexAnalysisSettings3 settings)133 private Map<String, IndexedSymlink> mapSymlinks(IndexAnalysisSettings3 settings) { 134 135 Map<String, IndexedSymlink> res = new TreeMap<>( 136 Comparator.comparingInt(String::length).thenComparing(o -> o)); 137 for (IndexedSymlink entry : settings.getIndexedSymlinks().values()) { 138 res.put(entry.getCanonical(), entry); 139 } 140 return res; 141 } 142 } 143