Skip to content

Commit 2453f15

Browse files
committed
Show AnalyzerGuru help with --detailed
Also: - JarAnalyzerFactory gets its own specific Matcher, and ZipAnalyzerFactory's Matcher is revised to only apply to ZipAnalyzerFactory. - Add FileAnalyzerFactory.Matcher.forFactory() method. - Only return unmodifiable collections from AnalyzerGuru. - Fix to use Locale.ROOT for --profiler input.
1 parent 1a0291e commit 2453f15

File tree

18 files changed

+624
-87
lines changed

18 files changed

+624
-87
lines changed

OpenGrok

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -139,10 +139,11 @@ Usage()
139139

140140
exec >&2
141141
echo ""
142-
echo "Usage: ${progname} <bootstrap|deploy|update|updateQuietly|updateDesc|usage|help>"
142+
echo "Usage: ${progname} <bootstrap|deploy|update|updateQuietly|updateDesc>"
143143
echo " ${progname} index [<directory>]"
144144
echo " ${progname} indexpart <directory_1> [<directory_2> ..]"
145145
echo " ${progname} clearHistory <src_root> <repository_name>"
146+
echo " ${progname} usage|help [--detailed]"
146147
echo ""
147148
echo " The \"indexpart\" assumes that it will be run with configuration"
148149
echo " pointed to via the OPENGROK_READ_XML_CONFIGURATION environment"
@@ -920,8 +921,9 @@ UpdateDescriptionCache()
920921

921922
OpenGrokUsage()
922923
{
924+
[ "$1" == "--detailed" ] && helpargs=$1
923925
echo "Options for opengrok.jar:" 1>&2
924-
${DO} ${JAVA} ${JAVA_OPTS} -jar "${OPENGROK_JAR}" '-?'
926+
${DO} ${JAVA} ${JAVA_OPTS} -jar "${OPENGROK_JAR}" '-?' $helpargs
925927
}
926928

927929
DeployWar()
@@ -1108,7 +1110,7 @@ case "${1}" in
11081110
;;
11091111

11101112
usage|help)
1111-
OpenGrokUsage
1113+
OpenGrokUsage $2
11121114
Usage
11131115
;;
11141116
*)

opengrok-indexer/pom.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,13 @@ Portions Copyright (c) 2017, Chris Fraire <[email protected]>.
9595
<exclude>*.java</exclude>
9696
</excludes>
9797
</testResource>
98+
<testResource>
99+
<targetPath>org/opensolaris/opengrok/analysis/archive/</targetPath>
100+
<directory>../test/org/opensolaris/opengrok/analysis/archive/</directory>
101+
<excludes>
102+
<exclude>*.java</exclude>
103+
</excludes>
104+
</testResource>
98105
<testResource>
99106
<targetPath>org/opensolaris/opengrok/analysis/clojure/</targetPath>
100107
<directory>../test/org/opensolaris/opengrok/analysis/clojure/</directory>

src/org/opensolaris/opengrok/analysis/AnalyzerGuru.java

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import java.lang.reflect.InvocationTargetException;
3535
import java.util.ArrayList;
3636
import java.util.Arrays;
37+
import java.util.Collections;
3738
import java.util.Comparator;
3839
import java.util.HashMap;
3940
import java.util.List;
@@ -54,6 +55,7 @@
5455
import org.apache.lucene.document.TextField;
5556
import org.apache.lucene.util.BytesRef;
5657
import org.opensolaris.opengrok.analysis.FileAnalyzer.Genre;
58+
import org.opensolaris.opengrok.analysis.FileAnalyzerFactory.Matcher;
5759
import org.opensolaris.opengrok.analysis.ada.AdaAnalyzerFactory;
5860
import org.opensolaris.opengrok.analysis.archive.BZip2AnalyzerFactory;
5961
import org.opensolaris.opengrok.analysis.archive.GZIPAnalyzerFactory;
@@ -279,12 +281,28 @@ public class AnalyzerGuru {
279281

280282
}
281283

284+
public static Map<String, FileAnalyzerFactory> getExtensionsMap() {
285+
return Collections.unmodifiableMap(ext);
286+
}
287+
288+
public static Map<String, FileAnalyzerFactory> getPrefixesMap() {
289+
return Collections.unmodifiableMap(pre);
290+
}
291+
292+
public static Map<String, FileAnalyzerFactory> getMagicsMap() {
293+
return Collections.unmodifiableMap(magics);
294+
}
295+
296+
public static List<Matcher> getAnalyzerFactoryMatchers() {
297+
return Collections.unmodifiableList(matchers);
298+
}
299+
282300
public static Map<String, String> getfileTypeDescriptions() {
283-
return fileTypeDescriptions;
301+
return Collections.unmodifiableMap(fileTypeDescriptions);
284302
}
285303

286304
public List<FileAnalyzerFactory> getAnalyzerFactories() {
287-
return factories;
305+
return Collections.unmodifiableList(factories);
288306
}
289307

290308
/**
Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
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) 2017-2018, Chris Fraire <[email protected]>.
22+
*/
23+
24+
package org.opensolaris.opengrok.analysis;
25+
26+
import java.util.ArrayList;
27+
import java.util.List;
28+
import java.util.Locale;
29+
import java.util.Map;
30+
import java.util.stream.Collectors;
31+
32+
/**
33+
* Represents a utility class to show the user details of {@link AnalyzerGuru}.
34+
*/
35+
public class AnalyzerGuruHelp {
36+
/**
37+
* Gets a reportable hunk of text that details
38+
* {@link AnalyzerGuru#getPrefixesMap()},
39+
* {@link AnalyzerGuru#getExtensionsMap()},
40+
* {@link AnalyzerGuru#getMagicsMap()}, and
41+
* {@link AnalyzerGuru#getAnalyzerFactoryMatchers()}.
42+
* @return a defined, multi-line String
43+
*/
44+
public static String getUsage() {
45+
StringBuilder b = new StringBuilder();
46+
b.append("AnalyzerGuru prefixes:\n");
47+
byKey(AnalyzerGuru.getPrefixesMap()).forEach((kv) -> {
48+
b.append(String.format("%-10s : %s\n", reportable(kv.key + '*'),
49+
reportable(kv.fac)));
50+
});
51+
52+
b.append("\nAnalyzerGuru extensions:\n");
53+
byKey(AnalyzerGuru.getExtensionsMap()).forEach((kv) -> {
54+
b.append(String.format("*.%-7s : %s\n",
55+
reportable(kv.key.toLowerCase(Locale.ROOT)),
56+
reportable(kv.fac)));
57+
});
58+
59+
b.append("\nAnalyzerGuru magic strings:\n");
60+
byFactory(AnalyzerGuru.getMagicsMap()).forEach((kv) -> {
61+
b.append(String.format("%-23s : %s\n", reportable(kv.key),
62+
reportable(kv.fac)));
63+
});
64+
65+
b.append("\nAnalyzerGuru magic matchers:\n");
66+
AnalyzerGuru.getAnalyzerFactoryMatchers().forEach((m) -> {
67+
if (m.getIsPreciseMagic()) b.append(reportable(m));
68+
});
69+
AnalyzerGuru.getAnalyzerFactoryMatchers().forEach((m) -> {
70+
if (!m.getIsPreciseMagic()) b.append(reportable(m));
71+
});
72+
73+
return b.toString();
74+
}
75+
76+
private static String reportable(FileAnalyzerFactory fac) {
77+
String nm = fac.getName();
78+
return nm == null ? fac.getClass().getSimpleName() : nm;
79+
}
80+
81+
private static String reportable(String value) {
82+
if (value.startsWith("#!")) return value;
83+
84+
boolean allAsciiPrintable = true;
85+
for (int i = 0; i < value.length(); ++i) {
86+
char c = value.charAt(i);
87+
if (c < ' ' || c > '~') {
88+
allAsciiPrintable = false;
89+
break;
90+
}
91+
}
92+
if (allAsciiPrintable) return value;
93+
94+
StringBuilder b = new StringBuilder();
95+
int i = 0;
96+
while (i < value.length()) {
97+
int cp = Character.codePointAt(value, i);
98+
i += Character.charCount(cp);
99+
if (Character.isAlphabetic(cp)) {
100+
b.appendCodePoint(cp);
101+
} else {
102+
b.append("\\{");
103+
b.append(String.format("%x", cp));
104+
b.append("}");
105+
}
106+
}
107+
return b.toString();
108+
}
109+
110+
private static String reportable(FileAnalyzerFactory.Matcher m) {
111+
final String MATCHER_FMT = "%-11s %-1s %s\n";
112+
StringBuilder b = new StringBuilder();
113+
String[] lines = splitLines(m.description(), 66);
114+
for (int i = 0; i < lines.length; ++i) {
115+
if (i < 1) {
116+
b.append(String.format(MATCHER_FMT, reportable(m.forFactory()),
117+
":", lines[i]));
118+
} else {
119+
b.append(String.format(MATCHER_FMT, "", "", lines[i]));
120+
}
121+
}
122+
return b.toString();
123+
}
124+
125+
private static String[] splitLines(String str, int width) {
126+
List<String> res = new ArrayList<>();
127+
StringBuilder b = new StringBuilder();
128+
129+
int llen = 0;
130+
int i = 0;
131+
while (i < str.length()) {
132+
int wlen = nextTestWhitespaceLength(false, str, i);
133+
if (wlen > 0) {
134+
String word = str.substring(i, i + wlen);
135+
if (llen < 1) {
136+
b.append(word);
137+
llen = word.length();
138+
} else if (llen + 1 + wlen <= width) {
139+
b.append(" ");
140+
b.append(word);
141+
llen += word.length() + 1;
142+
} else {
143+
res.add(b.toString());
144+
b.setLength(0);
145+
b.append(word);
146+
llen = word.length();
147+
}
148+
i += wlen;
149+
}
150+
151+
int slen = nextTestWhitespaceLength(true, str, i);
152+
i += slen;
153+
}
154+
if (b.length() > 0) {
155+
res.add(b.toString());
156+
b.setLength(0);
157+
}
158+
159+
return res.stream().toArray(String[]::new);
160+
}
161+
162+
private static int nextTestWhitespaceLength(boolean match, String str,
163+
int off) {
164+
int i = 0;
165+
while (off + i < str.length()) {
166+
int cp = Character.codePointAt(str, off + i);
167+
if ((Character.isWhitespace(cp) || Character.isISOControl(cp)) !=
168+
match) {
169+
return i;
170+
}
171+
i += Character.charCount(cp);
172+
}
173+
return str.length() - off;
174+
}
175+
176+
private static List<MappedFactory> byKey(
177+
Map<String, FileAnalyzerFactory> mapped) {
178+
179+
List<MappedFactory> res = mapped.entrySet().stream().map((t) -> {
180+
return new MappedFactory(t.getKey(), t.getValue());
181+
}).collect(Collectors.toList());
182+
183+
res.sort((mf1, mf2) -> {
184+
return mf1.key.toLowerCase(Locale.ROOT).compareTo(
185+
mf2.key.toLowerCase(Locale.ROOT));
186+
});
187+
return res;
188+
}
189+
190+
private static List<MappedFactory> byFactory(
191+
Map<String, FileAnalyzerFactory> mapped) {
192+
193+
List<MappedFactory> res = mapped.entrySet().stream().map((t) -> {
194+
return new MappedFactory(t.getKey(), t.getValue());
195+
}).collect(Collectors.toList());
196+
197+
res.sort((mf1, mf2) -> {
198+
String r1 = reportable(mf1.fac);
199+
String r2 = reportable(mf2.fac);
200+
int cmp = r1.toLowerCase(Locale.ROOT).compareTo(
201+
r2.toLowerCase(Locale.ROOT));
202+
if (cmp != 0) return cmp;
203+
return mf1.key.toLowerCase(Locale.ROOT).compareTo(
204+
mf2.key.toLowerCase(Locale.ROOT));
205+
});
206+
return res;
207+
}
208+
209+
private static class MappedFactory {
210+
public final String key;
211+
public final FileAnalyzerFactory fac;
212+
public MappedFactory(String key, FileAnalyzerFactory fac) {
213+
this.key = key;
214+
this.fac = fac;
215+
}
216+
}
217+
}

src/org/opensolaris/opengrok/analysis/FileAnalyzerFactory.java

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919

2020
/*
2121
* Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
22-
* Portions Copyright (c) 2017, Chris Fraire <[email protected]>.
22+
* Portions Copyright (c) 2017-2018, Chris Fraire <[email protected]>.
2323
*/
2424
package org.opensolaris.opengrok.analysis;
2525

@@ -224,6 +224,19 @@ public interface Matcher {
224224
*/
225225
default boolean getIsPreciseMagic() { return false; }
226226

227+
/**
228+
* Gets a default, reportable description of the matcher.
229+
* <p>
230+
* Subclasses can override to report a more informative description,
231+
* with line length up to 50 characters before starting a new line with
232+
* {@code \n}.
233+
* @return a defined, reportable String
234+
*/
235+
default String description() {
236+
return getIsPreciseMagic() ? "precise matcher" :
237+
"heuristic matcher";
238+
}
239+
227240
/**
228241
* Try to match the file contents with an analyzer factory.
229242
* If the method reads from the input stream, it must reset the
@@ -237,5 +250,12 @@ public interface Matcher {
237250
*/
238251
FileAnalyzerFactory isMagic(byte[] contents, InputStream in)
239252
throws IOException;
253+
254+
/**
255+
* Gets the instance which the matcher produces if
256+
* {@link #isMagic(byte[], java.io.InputStream)} matches a file.
257+
* @return a defined instance
258+
*/
259+
FileAnalyzerFactory forFactory();
240260
}
241261
}

0 commit comments

Comments
 (0)