xref: /OpenGrok/opengrok-indexer/src/main/java/org/opengrok/indexer/index/IndexAnalysisSettings3.java (revision e779faac6ac01c406f41e81a4354cd6ed590f968)
17d004396SChris Fraire /*
27d004396SChris Fraire  * CDDL HEADER START
37d004396SChris Fraire  *
47d004396SChris Fraire  * The contents of this file are subject to the terms of the
57d004396SChris Fraire  * Common Development and Distribution License (the "License").
67d004396SChris Fraire  * You may not use this file except in compliance with the License.
77d004396SChris Fraire  *
87d004396SChris Fraire  * See LICENSE.txt included in this distribution for the specific
97d004396SChris Fraire  * language governing permissions and limitations under the License.
107d004396SChris Fraire  *
117d004396SChris Fraire  * When distributing Covered Code, include this CDDL HEADER in each
127d004396SChris Fraire  * file and include the License file at LICENSE.txt.
137d004396SChris Fraire  * If applicable, add the following below this CDDL HEADER, with the
147d004396SChris Fraire  * fields enclosed by brackets "[]" replaced with your own identifying
157d004396SChris Fraire  * information: Portions Copyright [yyyy] [name of copyright owner]
167d004396SChris Fraire  *
177d004396SChris Fraire  * CDDL HEADER END
187d004396SChris Fraire  */
197d004396SChris Fraire 
207d004396SChris Fraire /*
215d9f3aa0SAdam Hornáček  * Copyright (c) 2018, 2019, Chris Fraire <cfraire@me.com>.
227d004396SChris Fraire  */
237d004396SChris Fraire package org.opengrok.indexer.index;
247d004396SChris Fraire 
25*e779faacSAdam Hornacek import org.opengrok.indexer.util.WhitelistObjectInputFilter;
26*e779faacSAdam Hornacek 
277d004396SChris Fraire import java.io.ByteArrayInputStream;
287d004396SChris Fraire import java.io.ByteArrayOutputStream;
297d004396SChris Fraire import java.io.IOException;
30*e779faacSAdam Hornacek import java.io.ObjectInputFilter;
317d004396SChris Fraire import java.io.ObjectInputStream;
327d004396SChris Fraire import java.io.ObjectOutputStream;
337d004396SChris Fraire import java.io.Serializable;
347d004396SChris Fraire import java.util.Collections;
357d004396SChris Fraire import java.util.HashMap;
367d004396SChris Fraire import java.util.Map;
377d004396SChris Fraire 
387d004396SChris Fraire /**
397d004396SChris Fraire  * Represents a serializable gathering of some top-level metadata concerning the
407d004396SChris Fraire  * operation of {@link IndexDatabase} -- and persisted therein too -- which are
417d004396SChris Fraire  * re-compared upon each indexing run since changes to them might require
427d004396SChris Fraire  * re-indexing particular files or in certain cases all files.
437d004396SChris Fraire  */
447d004396SChris Fraire public final class IndexAnalysisSettings3 implements Serializable {
457d004396SChris Fraire 
467d004396SChris Fraire     private static final long serialVersionUID = -4700122690707062276L;
477d004396SChris Fraire 
48*e779faacSAdam Hornacek     private static final ObjectInputFilter serialFilter = new WhitelistObjectInputFilter(IndexAnalysisSettings3.class);
49*e779faacSAdam Hornacek 
507d004396SChris Fraire     private String projectName;
517d004396SChris Fraire 
527d004396SChris Fraire     /**
537d004396SChris Fraire      * Nullable to allow easing this object into existing OpenGrok indexes
547d004396SChris Fraire      * without forcing a re-indexing.
557d004396SChris Fraire      * @serial
567d004396SChris Fraire      */
577d004396SChris Fraire     private Integer tabSize;
587d004396SChris Fraire 
597d004396SChris Fraire     /**
607d004396SChris Fraire      * Nullable to allow easing this object into existing OpenGrok indexes
617d004396SChris Fraire      * without forcing a re-indexing.
627d004396SChris Fraire      * @serial
637d004396SChris Fraire      */
647d004396SChris Fraire     private Long analyzerGuruVersion;
657d004396SChris Fraire 
667d004396SChris Fraire     /**
677d004396SChris Fraire      * Nullable because otherwise custom de-serialization does not work, as a
687d004396SChris Fraire      * {@code final} initialized value may not actually happen because Java
697d004396SChris Fraire      * de-serialization circumvents normal construction.
707d004396SChris Fraire      * @serial
717d004396SChris Fraire      */
727d004396SChris Fraire     private Map<String, Long> analyzersVersions = new HashMap<>();
737d004396SChris Fraire 
747d004396SChris Fraire     /**
757d004396SChris Fraire      * Nullable because otherwise custom de-serialization does not work, as a
767d004396SChris Fraire      * {@code final} initialized value may not actually happen because Java
777d004396SChris Fraire      * de-serialization circumvents normal construction. We don't bother with
787d004396SChris Fraire      * anything but a simple {@link HashMap} here.
797d004396SChris Fraire      * @serial
807d004396SChris Fraire      */
817d004396SChris Fraire     private Map<String, IndexedSymlink> indexedSymlinks = new HashMap<>();
827d004396SChris Fraire 
837d004396SChris Fraire     /**
847d004396SChris Fraire      * Gets the project name to be used to distinguish different instances of
857d004396SChris Fraire      * {@link IndexAnalysisSettings3} that might be returned by a Lucene
867d004396SChris Fraire      * {@code MultiReader} search across projects.
877d004396SChris Fraire      * @return projectName
887d004396SChris Fraire      */
getProjectName()897d004396SChris Fraire     public String getProjectName() {
907d004396SChris Fraire         return projectName;
917d004396SChris Fraire     }
927d004396SChris Fraire 
937d004396SChris Fraire     /**
947d004396SChris Fraire      * Sets the project name to be used to distinguish different instances of
957d004396SChris Fraire      * {@link IndexAnalysisSettings3} that might be returned by a Lucene
967d004396SChris Fraire      * {@code MultiReader} search across projects.
977d004396SChris Fraire      * @param value project name
987d004396SChris Fraire      */
setProjectName(String value)997d004396SChris Fraire     public void setProjectName(String value) {
1007d004396SChris Fraire         this.projectName = value;
1017d004396SChris Fraire     }
1027d004396SChris Fraire 
getTabSize()1037d004396SChris Fraire     public Integer getTabSize() {
1047d004396SChris Fraire         return tabSize;
1057d004396SChris Fraire     }
1067d004396SChris Fraire 
setTabSize(Integer value)1077d004396SChris Fraire     public void setTabSize(Integer value) {
1087d004396SChris Fraire         this.tabSize = value;
1097d004396SChris Fraire     }
1107d004396SChris Fraire 
getAnalyzerGuruVersion()1117d004396SChris Fraire     public Long getAnalyzerGuruVersion() {
1127d004396SChris Fraire         return analyzerGuruVersion;
1137d004396SChris Fraire     }
1147d004396SChris Fraire 
setAnalyzerGuruVersion(Long value)1157d004396SChris Fraire     public void setAnalyzerGuruVersion(Long value) {
1167d004396SChris Fraire         this.analyzerGuruVersion = value;
1177d004396SChris Fraire     }
1187d004396SChris Fraire 
1197d004396SChris Fraire     /**
1207d004396SChris Fraire      * Gets the version number for the specified file type name if it exists.
1217d004396SChris Fraire      * @param fileTypeName name of the file type
1227d004396SChris Fraire      * @return a defined value or {@code null} if unknown
1237d004396SChris Fraire      */
getAnalyzerVersion(String fileTypeName)1247d004396SChris Fraire     public Long getAnalyzerVersion(String fileTypeName) {
1257d004396SChris Fraire         return analyzersVersions.get(fileTypeName);
1267d004396SChris Fraire     }
1277d004396SChris Fraire 
1287d004396SChris Fraire     /**
1297d004396SChris Fraire      * Gets an unmodifiable view of the map of file type names to version
1307d004396SChris Fraire      * numbers.
1317d004396SChris Fraire      * @return a defined instance
1327d004396SChris Fraire      */
getAnalyzersVersions()1337d004396SChris Fraire     public Map<String, Long> getAnalyzersVersions() {
1347d004396SChris Fraire         return Collections.unmodifiableMap(analyzersVersions);
1357d004396SChris Fraire     }
1367d004396SChris Fraire 
1377d004396SChris Fraire     /**
1387d004396SChris Fraire      * Replaces the contents of the instance's map with the {@code values}.
1397d004396SChris Fraire      * @param values a defined instance
1407d004396SChris Fraire      */
setAnalyzersVersions(Map<String, Long> values)1417d004396SChris Fraire     public void setAnalyzersVersions(Map<String, Long> values) {
1427d004396SChris Fraire         analyzersVersions.clear();
1437d004396SChris Fraire         analyzersVersions.putAll(values);
1447d004396SChris Fraire     }
1457d004396SChris Fraire 
1467d004396SChris Fraire     /**
1477d004396SChris Fraire      * Gets an unmodifiable view of the map of canonical file names to symlinks.
1487d004396SChris Fraire      * @return a defined instance
1497d004396SChris Fraire      */
getIndexedSymlinks()1507d004396SChris Fraire     public Map<String, IndexedSymlink> getIndexedSymlinks() {
1517d004396SChris Fraire         return Collections.unmodifiableMap(indexedSymlinks);
1527d004396SChris Fraire     }
1537d004396SChris Fraire 
1547d004396SChris Fraire     /**
1557d004396SChris Fraire      * Replaces the contents of the instance's map with the {@code values}.
1567d004396SChris Fraire      * @param values a defined instance
1577d004396SChris Fraire      */
setIndexedSymlinks(Map<String, IndexedSymlink> values)1587d004396SChris Fraire     public void setIndexedSymlinks(Map<String, IndexedSymlink> values) {
1597d004396SChris Fraire         indexedSymlinks.clear();
1607d004396SChris Fraire         indexedSymlinks.putAll(values);
1617d004396SChris Fraire     }
1627d004396SChris Fraire 
1637d004396SChris Fraire     /**
1647d004396SChris Fraire      * Creates a binary representation of this object.
1657d004396SChris Fraire      * @return a byte array representing this object
1667d004396SChris Fraire      * @throws  IOException Any exception thrown by the underlying
1677d004396SChris Fraire      * OutputStream.
1687d004396SChris Fraire      */
serialize()1697d004396SChris Fraire     public byte[] serialize() throws IOException {
170*e779faacSAdam Hornacek         try (ByteArrayOutputStream bytes = new ByteArrayOutputStream(); var oos = new ObjectOutputStream(bytes)) {
171*e779faacSAdam Hornacek             oos.writeObject(this);
1727d004396SChris Fraire             return bytes.toByteArray();
1737d004396SChris Fraire         }
174*e779faacSAdam Hornacek     }
1757d004396SChris Fraire 
1767d004396SChris Fraire     /**
1777d004396SChris Fraire      * De-serializes a binary representation of an {@link IndexAnalysisSettings3}
1787d004396SChris Fraire      * object.
1797d004396SChris Fraire      * @param bytes a byte array containing the serialization
1807d004396SChris Fraire      * @return a defined instance
1817d004396SChris Fraire      * @throws IOException Any of the usual Input/Output related exceptions.
1827d004396SChris Fraire      * @throws ClassNotFoundException Class of a serialized object cannot be
1837d004396SChris Fraire      * found.
1847d004396SChris Fraire      * @throws ClassCastException if the array contains an object of another
1857d004396SChris Fraire      * type than {@code IndexAnalysisSettings}
1867d004396SChris Fraire      */
deserialize(byte[] bytes)187*e779faacSAdam Hornacek     public static IndexAnalysisSettings3 deserialize(byte[] bytes) throws IOException, ClassNotFoundException {
188*e779faacSAdam Hornacek         try (ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(bytes))) {
189*e779faacSAdam Hornacek             in.setObjectInputFilter(serialFilter);
1907d004396SChris Fraire             return (IndexAnalysisSettings3) in.readObject();
1917d004396SChris Fraire         }
192*e779faacSAdam Hornacek     }
1937d004396SChris Fraire 
1947d004396SChris Fraire     @SuppressWarnings("Duplicates")
readObject(ObjectInputStream in)1957d004396SChris Fraire     private void readObject(ObjectInputStream in) throws ClassNotFoundException,
1967d004396SChris Fraire             IOException {
1977d004396SChris Fraire 
1987d004396SChris Fraire         boolean hasValue = in.readBoolean();
1997d004396SChris Fraire         String vString = in.readUTF();
2007d004396SChris Fraire         projectName = hasValue ? vString : null;
2017d004396SChris Fraire 
2027d004396SChris Fraire         hasValue = in.readBoolean();
2037d004396SChris Fraire         int vInteger = in.readInt();
2047d004396SChris Fraire         tabSize = hasValue ? vInteger : null;
2057d004396SChris Fraire 
2067d004396SChris Fraire         hasValue = in.readBoolean();
2077d004396SChris Fraire         long vLong = in.readLong();
2087d004396SChris Fraire         analyzerGuruVersion = hasValue ? vLong : null;
2097d004396SChris Fraire 
2107d004396SChris Fraire         /*
2117d004396SChris Fraire          * De-serialization circumvents normal construction, so the following
2127d004396SChris Fraire          * field could be null.
2137d004396SChris Fraire          */
2147d004396SChris Fraire         if (analyzersVersions == null) {
2157d004396SChris Fraire             analyzersVersions = new HashMap<>();
2167d004396SChris Fraire         }
2177d004396SChris Fraire         int analyzerCount = in.readInt();
2187d004396SChris Fraire         for (int i = 0; i < analyzerCount; ++i) {
2197d004396SChris Fraire             vString = in.readUTF();
2207d004396SChris Fraire             vLong = in.readLong();
2217d004396SChris Fraire             analyzersVersions.put(vString, vLong);
2227d004396SChris Fraire         }
2237d004396SChris Fraire 
2247d004396SChris Fraire         /*
2257d004396SChris Fraire          * De-serialization circumvents normal construction, so the following
2267d004396SChris Fraire          * field could be null.
2277d004396SChris Fraire          */
2287d004396SChris Fraire         if (indexedSymlinks == null) {
2297d004396SChris Fraire             indexedSymlinks = new HashMap<>();
2307d004396SChris Fraire         }
2317d004396SChris Fraire         int symlinkCount = in.readInt();
2327d004396SChris Fraire         for (int i = 0; i < symlinkCount; ++i) {
2337d004396SChris Fraire             String absolute = in.readUTF();
2347d004396SChris Fraire             String canonical = in.readUTF();
2357d004396SChris Fraire             boolean isLocal = in.readBoolean();
2367d004396SChris Fraire             IndexedSymlink indexed = new IndexedSymlink(absolute, canonical, isLocal);
2377d004396SChris Fraire             indexedSymlinks.put(canonical, indexed);
2387d004396SChris Fraire         }
2397d004396SChris Fraire     }
2407d004396SChris Fraire 
2417d004396SChris Fraire     @SuppressWarnings("Duplicates")
writeObject(ObjectOutputStream out)2427d004396SChris Fraire     private void writeObject(ObjectOutputStream out) throws IOException {
2437d004396SChris Fraire         out.writeBoolean(projectName != null); // hasValue
2447d004396SChris Fraire         out.writeUTF(projectName == null ? "" : projectName);
2457d004396SChris Fraire 
2467d004396SChris Fraire         out.writeBoolean(tabSize != null); // hasValue
2477d004396SChris Fraire         out.writeInt(tabSize == null ? 0 : tabSize);
2487d004396SChris Fraire 
2497d004396SChris Fraire         out.writeBoolean(analyzerGuruVersion != null); // hasValue
2507d004396SChris Fraire         out.writeLong(analyzerGuruVersion == null ? 0 : analyzerGuruVersion);
2517d004396SChris Fraire 
2527d004396SChris Fraire         int collectionCount = analyzersVersions.size();
2537d004396SChris Fraire         out.writeInt(collectionCount);
2547d004396SChris Fraire         for (Map.Entry<String, Long> entry : analyzersVersions.entrySet()) {
2557d004396SChris Fraire             out.writeUTF(entry.getKey());
2567d004396SChris Fraire             out.writeLong(entry.getValue());
2577d004396SChris Fraire             --collectionCount;
2587d004396SChris Fraire         }
2597d004396SChris Fraire         if (collectionCount != 0) {
2607d004396SChris Fraire             throw new IllegalStateException("analyzersVersions were modified");
2617d004396SChris Fraire         }
2627d004396SChris Fraire 
2637d004396SChris Fraire         collectionCount = indexedSymlinks.size();
2647d004396SChris Fraire         out.writeInt(collectionCount);
2657d004396SChris Fraire         for (IndexedSymlink entry : indexedSymlinks.values()) {
2667d004396SChris Fraire             out.writeUTF(entry.getAbsolute());
2677d004396SChris Fraire             out.writeUTF(entry.getCanonical());
2687d004396SChris Fraire             out.writeBoolean(entry.isLocal());
2697d004396SChris Fraire             --collectionCount;
2707d004396SChris Fraire         }
2717d004396SChris Fraire         if (collectionCount != 0) {
2727d004396SChris Fraire             throw new IllegalStateException("indexedSymlinks were modified");
2737d004396SChris Fraire         }
2747d004396SChris Fraire     }
2757d004396SChris Fraire }
276