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) 2015, 2021, Oracle and/or its affiliates. All rights reserved. 22 */ 23 package org.opengrok.indexer.analysis; 24 25 import org.opengrok.indexer.util.WhitelistObjectInputFilter; 26 27 import java.io.ByteArrayInputStream; 28 import java.io.ByteArrayOutputStream; 29 import java.io.IOException; 30 import java.io.ObjectInputFilter; 31 import java.io.ObjectInputStream; 32 import java.io.ObjectOutputStream; 33 import java.io.Serializable; 34 import java.util.TreeSet; 35 36 /** 37 * 38 * @author Tomas Kotal 39 */ 40 public class Scopes implements Serializable { 41 42 private static final long serialVersionUID = 1191703801007779489L; 43 44 private static final ObjectInputFilter serialFilter = new WhitelistObjectInputFilter( 45 Scopes.class, 46 TreeSet.class, 47 Scope.class 48 ); 49 50 /** 51 * Note: this class has a natural ordering that is inconsistent with equals. 52 */ 53 public static class Scope implements Serializable, Comparable<Scope> { 54 55 private static final long serialVersionUID = 1191703801007779489L; 56 57 private int lineFrom; 58 private int lineTo; 59 private String name; 60 private String namespace; 61 private String signature; 62 Scope(int lineFrom, int lineTo, String name, String namespace)63 public Scope(int lineFrom, int lineTo, String name, String namespace) { 64 this(lineFrom, lineTo, name, namespace, ""); 65 } 66 Scope(int lineFrom, int lineTo, String name, String namespace, String signature)67 public Scope(int lineFrom, int lineTo, String name, String namespace, String signature) { 68 this.lineFrom = lineFrom; 69 this.lineTo = lineTo; 70 this.name = name; 71 this.namespace = namespace; 72 this.signature = signature; 73 } 74 Scope(int lineFrom)75 public Scope(int lineFrom) { 76 this.lineFrom = lineFrom; 77 } 78 matches(int line)79 public boolean matches(int line) { 80 return line >= lineFrom && line <= lineTo; 81 } 82 83 @Override compareTo(Scope o)84 public int compareTo(Scope o) { 85 return Integer.compare(lineFrom, o.lineFrom); 86 } 87 getLineFrom()88 public int getLineFrom() { 89 return lineFrom; 90 } 91 setLineFrom(int lineFrom)92 public void setLineFrom(int lineFrom) { 93 this.lineFrom = lineFrom; 94 } 95 getLineTo()96 public int getLineTo() { 97 return lineTo; 98 } 99 setLineTo(int lineTo)100 public void setLineTo(int lineTo) { 101 this.lineTo = lineTo; 102 } 103 getName()104 public String getName() { 105 return name; 106 } 107 setName(String name)108 public void setName(String name) { 109 this.name = name; 110 } 111 getNamespace()112 public String getNamespace() { 113 return namespace; 114 } 115 setNamespace(String namespace)116 public void setNamespace(String namespace) { 117 this.namespace = namespace; 118 } 119 getSignature()120 public String getSignature() { 121 return signature; 122 } 123 setSignature(String signature)124 public void setSignature(String signature) { 125 this.signature = signature; 126 } 127 } 128 129 // default global scope 130 public static final Scope GLOBAL_SCOPE = new Scope(0, 0, "global", null, null); 131 132 // tree of scopes sorted by starting line 133 private final TreeSet<Scope> scopes = new TreeSet<>(); 134 Scopes()135 public Scopes() { 136 // nothing to do here 137 } 138 size()139 public int size() { 140 return scopes.size(); 141 } 142 addScope(Scope scope)143 public void addScope(Scope scope) { 144 scopes.add(scope); 145 } 146 getScope(int line)147 public Scope getScope(int line) { 148 // find closest scope that starts before or on given line 149 Scope s = scopes.floor(new Scope(line)); 150 return (s != null && s.matches(line)) ? s : GLOBAL_SCOPE; 151 } 152 153 /** 154 * Create a binary representation of this object. 155 * 156 * @return a byte array representing this object 157 * @throws IOException if an error happens when writing to the array 158 */ serialize()159 public byte[] serialize() throws IOException { 160 ByteArrayOutputStream bytes = new ByteArrayOutputStream(); 161 new ObjectOutputStream(bytes).writeObject(this); 162 return bytes.toByteArray(); 163 } 164 165 /** 166 * De-serialize a binary representation of a {@code Definitions} object. 167 * 168 * @param bytes a byte array containing the {@code Definitions} object 169 * @return a {@code Definitions} object 170 * @throws IOException if an I/O error happens when reading the array 171 * @throws ClassNotFoundException if the class definition for an object 172 * stored in the byte array cannot be found 173 * @throws ClassCastException if the array contains an object of another 174 * type than {@code Definitions} 175 */ deserialize(byte[] bytes)176 public static Scopes deserialize(byte[] bytes) throws IOException, ClassNotFoundException { 177 try (ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(bytes))) { 178 in.setObjectInputFilter(serialFilter); 179 return (Scopes) in.readObject(); 180 } 181 } 182 } 183