package org.apache.tuscany.sca.domain.manager.impl;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringWriter;
import java.io.Writer;
import java.net.URL;
import java.util.Arrays;
import java.util.Map;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.tuscany.sca.contribution.Contribution;
import org.apache.tuscany.sca.data.collection.Entry;
import org.apache.tuscany.sca.data.collection.Item;
import org.apache.tuscany.sca.data.collection.ItemCollection;
import org.apache.tuscany.sca.data.collection.LocalItemCollection;
import org.apache.tuscany.sca.data.collection.NotFoundException;
import org.apache.tuscany.sca.domain.search.DomainSearch;
import org.apache.tuscany.sca.domain.search.Result;
import org.apache.tuscany.sca.domain.search.impl.DomainSearchFormatter;
import org.apache.tuscany.sca.domain.search.impl.HighlightingUtil;
import org.apache.tuscany.sca.domain.search.impl.SearchFields;
import org.osoa.sca.annotations.Reference;
import org.osoa.sca.annotations.Scope;
import org.osoa.sca.annotations.Service;
@Scope("COMPOSITE")
@Service(interfaces = {ItemCollection.class, LocalItemCollection.class})
public class Searcher implements ItemCollection, LocalItemCollection {
static char[] characters = {'\u0001'/* */, '\u0003'/* */, '\u0004'/* */,};
final private static String HTML_NEW_LINE = "
";
final private static String PATH_SEPARATOR = "/";
final private static int MAX_CONTENT_LINE_WIDTH = 300;
final private static String HIGHLIGHT_START = "";
final private static String HIGHLIGHT_END = "";
@Reference
public ContributionsReader contributionReader;
@Reference
public LocalItemCollection contributionCollection;
@Reference
public DomainSearch domainSearch;
private int elementCounter;
public void delete(String key) throws NotFoundException {
System.out.println("delete");
}
private static void startIndentation(int size, StringWriter writer) {
writer.write("
");
}
private static void endIndentation(StringWriter writer) {
writer.write("
");
}
public Item get(String key) throws NotFoundException {
try {
if (key.startsWith("highlight")) {
int lastSemicolonIndex = key.lastIndexOf(";");
String artifact = key.substring(lastSemicolonIndex + 1);
int secondLastSemicolonIndex = key.lastIndexOf(";", lastSemicolonIndex - 1);
String contribution = key.substring(secondLastSemicolonIndex + 1, lastSemicolonIndex);
String query = key.substring("highlight".length(), secondLastSemicolonIndex);
return highlightArtifact(contribution, artifact, query);
} else if (key.startsWith("query")) {
return executeQuery(key.substring("query".length()));
} else {
throw new NotFoundException("Invalid operation!");
}
} catch (Exception t) {
if (t instanceof NotFoundException) {
throw (NotFoundException)t;
}
throw new NotFoundException("Internal error!");
}
}
private Item highlightArtifact(String contribution, String artifact, String query) throws NotFoundException {
Item item = this.contributionCollection.get(contribution);
if (item == null) {
throw new NotFoundException("contribution not found: " + contribution);
}
String location = item.getAlternate();
if (location.endsWith(".jar") || location.endsWith(".zip")) {
location =
"jar:" + (location.startsWith("file:") ? "" : "file:")
+ location
+ '!'
+ (artifact.startsWith("/") ? "" : "/")
+ artifact;
} else {
location += (location.endsWith("/") ? "" : "/") + artifact;
}
try {
Reader reader = new InputStreamReader(new URL(location).openStream());
StringBuilder sb = new StringBuilder();
int c;
// TODO: load the chars into an array buffer instead of one
// at a
// time
while ((c = reader.read()) != -1) {
char character = (char)c;
if (!Character.isIdentifierIgnorable(character)) {
sb.append(character);
}
}
String highlightedText = this.domainSearch.highlight(SearchFields.FILE_CONTENT_FIELD, sb.toString(), query);
highlightedText = highlightedText.replaceAll("\n", "
");
highlightedText = highlightedText.replaceAll(" ", " ");
highlightedText =
HighlightingUtil.replaceHighlightMarkupBy(highlightedText, HIGHLIGHT_START, HIGHLIGHT_END);
item = new Item();
item.setTitle(contribution + ";" + artifact);
item.setContents(highlightedText);
return item;
} catch (Exception e) {
throw new NotFoundException("Could not highlight artifact: " + e.getMessage(), e);
}
}
private Item executeQuery(String query) throws NotFoundException {
if (!this.domainSearch.indexExists()) {
Contribution[] contributions = this.contributionReader.readContributions();
for (Contribution contribution : contributions) {
if (!contribution.getURI().equals(DomainManagerUtil.DEPLOYMENT_CONTRIBUTION_URI)) {
this.domainSearch.contributionUpdated(contribution, contribution);
}
}
}
Result[] results;
try {
results = this.domainSearch.parseAndSearch(query, true);
} catch (Exception e1) {
throw new NotFoundException("Exception while searching: " + e1.getMessage(), e1);
}
Item item = new Item();
item.setTitle("Results");
StringWriter sw = new StringWriter();
this.elementCounter = 0;
if (results.length > 0) {
for (Result result : results) {
try {
writeToHTML(0, result, sw);
} catch (IOException e) {
// ignore result
}
}
String contents = HighlightingUtil.replaceHighlightMarkupBy(sw.getBuffer(), HIGHLIGHT_START, HIGHLIGHT_END);
item.setContents(replaceAll(contents, 40));
} else {
item.setContents("No results match: " + query + "");
}
System.out.println(item.getContents());
return item;
}
private static String replaceAll(CharSequence c, int less) {
StringBuilder sb = new StringBuilder();
// HashSet set = new HashSet();
Arrays.sort(characters);
// int start = 0, end = 4;
// char[] chars = new char[end - start];
// System.arraycopy(characters, start, chars, 0, end - start);
for (int i = 0; i < c.length(); i++) {
char actual = c.charAt(i);
// if (Arrays.binarySearch(characters, actual) < 0) {
// if (actual != '\u000b' && actual != '\u0020' &&
// actual != '\u000c' && actual != '\u0009' &&
// actual != ')' && actual != '(') {
if (actual > less || actual == '&'
|| actual == '#'
|| actual == '\''
|| actual == ' '
|| actual == '%'
|| actual == ':'
|| actual == '('
|| actual == ')'
|| actual == '"') {
sb.append(actual);
} else {
// sb.append('0');
}
}
//
// System.out.println("set-size: " + set.size());
// for (char character : set) {
// System.out.print(",");
// System.out.print((int) character);
// System.out.print("/*" + character + "*/");
//
// }
//
// System.out.println();
return sb.toString();
}
private static String getIconLocationForResult(Result result) {
if (SearchFields.COMPONENT_FIELD.equals(result.getField())) {
return "icons/component.png' title='Component";
} else if (SearchFields.COMPOSITE_FIELD.equals(result.getField())) {
return "icons/composite.png' title='Composite";
} else if (SearchFields.ARTIFACT_FIELD.equals(result.getField())) {
return "icons/artifact.png' title='Artifact";
}
return "icons/feed-icon.png";
}
private static void writeResultIcon(Writer writer, Result result) throws IOException {
writer.write(" ");
}
private static Result writeFileContentResultToHTML(int indentation, Result result, StringWriter writer)
throws IOException {
Map contents = result.getContents();
writeResultIcon(writer, result);
if (contents.size() == 1 && SearchFields.ARTIFACT_FIELD.equals(contents.values().iterator().next().getField())) {
writer.write(result.getValue());
contents = result.getContents();
while (contents.size() == 1 && SearchFields.ARTIFACT_FIELD.equals(contents.values().iterator().next()
.getField())) {
result = contents.values().iterator().next();
writer.write(PATH_SEPARATOR);
StringEscapeUtils.escapeHtml(writer, result.getValue());
contents = result.getContents();
}
} else {
StringEscapeUtils.escapeHtml(writer, result.getValue());
}
return result;
}
private static String removeHighlighting(String text) {
return HighlightingUtil.replaceHighlightMarkupBy(text, "", "");
}
private static void writeResultName(Result result, StringWriter writer) throws IOException {
if (SearchFields.CONTRIBUTION_FIELD.equals(result.getField())) {
writer.write("");
writer.write(StringEscapeUtils.escapeHtml(result.getValue()));
writer.write("");
} else if (SearchFields.COMPOSITE_FIELD.equals(result.getField())) {
writer.write("");
writer.write(StringEscapeUtils.escapeHtml(result.getValue()));
writer.write("");
} else {
StringEscapeUtils.escapeHtml(writer, result.getValue());
}
}
private static String getContributionURI(Result result) {
if (result == null) {
return "";
} else if (SearchFields.CONTRIBUTION_FIELD.equals(result.getField())) {
return removeHighlighting(result.getValue());
} else {
return getContributionURI(result.getContainer());
}
}
private void writeToHTML(int indentation, Result result, StringWriter writer) throws IOException {
startIndentation(indentation++, writer);
String field = result.getField();
if (SearchFields.FILE_CONTENT_FIELD.equals(field)) {
String content = result.getValue();
if (content != null && content.length() > 0 && DomainSearchFormatter.isHighlighted(content)) {
String contributionPlusArtifact =
getContributionURI(result) + ";" + removeHighlighting(result.getContainer().getValue());
writer.write(HTML_NEW_LINE);
this.elementCounter++;
writer.write("");
writer.write("
");
// + "view all view all ");
writer.write("download
");
int i = 0;
while (i < content.length()) {
StringEscapeUtils.escapeHtml(writer, content.substring(i, Math.min(i + MAX_CONTENT_LINE_WIDTH,
content.length())));
writer.write(HTML_NEW_LINE);
i += MAX_CONTENT_LINE_WIDTH;
}
writer.write("
");
writer.write("
");
}
} else if (SearchFields.ARTIFACT_FIELD.equals(field)) {
result = writeFileContentResultToHTML(indentation, result, writer);
} else {
writeResultIcon(writer, result);
writeResultName(result, writer);
}
endIndentation(writer);
for (Result actualResult : result.getContents().values()) {
writeToHTML(indentation, actualResult, writer);
}
}
public Entry[] getAll() {
System.out.println("getAll");
return null;
}
public String post(String key, Item item) {
System.out.println("post");
return null;
}
public void put(String key, Item item) throws NotFoundException {
System.out.println("put");
}
@SuppressWarnings("unchecked")
public Entry[] query(String queryString) {
try {
Item item;
String key;
if (queryString.startsWith("highlight")) {
int lastSemicolonIndex = queryString.lastIndexOf(";");
String artifact = queryString.substring(lastSemicolonIndex + 1);
int secondLastSemicolonIndex = queryString.lastIndexOf(";", lastSemicolonIndex - 1);
String contribution = queryString.substring(secondLastSemicolonIndex + 1, lastSemicolonIndex);
String query = queryString.substring("highlight".length(), secondLastSemicolonIndex);
item = highlightArtifact(contribution, artifact, query);
key = queryString.substring("highlight".length());
} else if (queryString.startsWith("query")) {
key = queryString.substring("query".length());
item = executeQuery(key);
} else {
throw new NotFoundException("Invalid operation!");
}
Entry[] returnArray = new Entry[1];
returnArray[0] = new Entry(key, item);
return returnArray;
} catch (Exception t) {
return new Entry[0];
}
}
}