Skip to content

Commit

Permalink
JBIDE-12860 - JAX-RS validation problems are not linked
Browse files Browse the repository at this point in the history
Added a custom JAXRS_PROBLEM_TYPE attribute in JAX-RS markers.
Those JAX-RS Problem markers are now indexed with Lucene.
Thus, it becomes possible to look for resource that have the same
error as a given resource, even if this later one has been deleted.
(eg: looking for duplicate application problem after an application
has been removed).
When a JAX-RS Element is removed, its associated JAX-RS Markers are
removed from the index *during the validation phase* (the markers
still exist and are still indexed until the validation is performed).
Added some JUnit tests to verify the good behaviour againts the case
where a project has 2 JAX-RS application then one is removed.
  • Loading branch information
xcoulon authored and dgolovin committed Sep 26, 2013
1 parent 68a7a43 commit 2fa9be0
Show file tree
Hide file tree
Showing 24 changed files with 698 additions and 344 deletions.
Expand Up @@ -11,6 +11,7 @@
package org.jboss.tools.ws.jaxrs.core.internal.metamodel.domain;

import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.jboss.tools.ws.jaxrs.core.internal.utils.Logger;
import org.jboss.tools.ws.jaxrs.core.metamodel.domain.IJaxrsElement;
Expand Down Expand Up @@ -47,7 +48,8 @@ public boolean exists() {
/**
* Resets the problem level for this given element.
*/
public void resetProblemLevel() {
public void resetMarkers() {
metamodel.unregisterMarkers(getResource());
this.problemLevel = 0;
}

Expand All @@ -59,9 +61,24 @@ public void resetProblemLevel() {
* level: the incoming new problem level.
* @throws CoreException
*/
@Deprecated
public void setProblemLevel(final int problemLevel) {
this.problemLevel = Math.max(this.problemLevel, problemLevel);
}

/**
* Registers a marker (from the underlying {@link IResource}) and sets the
* problem level on this element. If this element already has a problem
* level, the highest value is kept.
*
* @param marker: the marker that has been added to the underlying resource.
*
* @throws CoreException
*/
public void registerMarker(final IMarker marker) {
metamodel.registerMarker(marker);
this.problemLevel = Math.max(this.problemLevel, marker.getAttribute(IMarker.SEVERITY, 0));
}

/**
* @return the problem level.
Expand Down

Large diffs are not rendered by default.

Expand Up @@ -15,9 +15,12 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.CorruptIndexException;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
Expand All @@ -36,10 +39,11 @@
import org.apache.lucene.store.LockObtainFailedException;
import org.apache.lucene.store.RAMDirectory;
import org.apache.lucene.util.Version;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.Status;
import org.jboss.tools.ws.jaxrs.core.JBossJaxrsCorePlugin;
import org.jboss.tools.ws.jaxrs.core.internal.metamodel.domain.JaxrsEndpoint;
import org.jboss.tools.ws.jaxrs.core.internal.utils.Logger;
import org.jboss.tools.ws.jaxrs.core.metamodel.domain.IJaxrsElement;
import org.jboss.tools.ws.jaxrs.core.metamodel.domain.IJaxrsEndpoint;
Expand Down Expand Up @@ -113,7 +117,7 @@ public void indexElement(final IJaxrsElement element) {
Logger.debugIndexing("Adding JAX-RS Element into index with following fields: {}", doc.getFields());
indexWriter.addDocument(doc);
indexWriter.commit();
} catch (Exception e) {
} catch (IOException e) {
Logger.error("Failed to index the JAX-RS Element " + element, e);
} finally {
Logger.traceIndexing(" Done indexing {}.", element.getName());
Expand All @@ -127,7 +131,7 @@ public void indexElement(final IJaxrsEndpoint endpoint) {
Logger.debugIndexing("Adding JAX-RS Endpoint into index with following fields: {}", doc.getFields());
indexWriter.addDocument(doc);
indexWriter.commit();
} catch (Exception e) {
} catch (IOException e) {
Logger.error("Failed to index the JAX-RS Endpoint " + endpoint, e);
} finally {
Logger.traceIndexing(" Done indexing {}.", endpoint);
Expand All @@ -143,7 +147,7 @@ public void reindexElement(final IJaxrsElement element) {
indexWriter.commit();
Logger.debugIndexing("Updated JAX-RS Element index with following fields: {}. Writer.hasDeletions={}",
doc.getFields(), indexWriter.hasDeletions());
} catch (Exception e) {
} catch (IOException e) {
Logger.error("Failed to re-index the JAX-RS Element " + element, e);
} finally {
Logger.traceIndexing(" Done re-indexing {}.", element);
Expand All @@ -159,15 +163,15 @@ public void reindexElement(final IJaxrsEndpoint endpoint) {
indexWriter.commit();
Logger.debugIndexing("Updated JAX-RS Endpoint index with following fields: {}. Writer.hasDeletions={}",
doc.getFields(), indexWriter.hasDeletions());
} catch (Exception e) {
} catch (IOException e) {
Logger.error("Failed to re-index the JAX-RS Endpoint " + endpoint, e);
} finally {
Logger.traceIndexing(" Done re-indexing {}.", endpoint);
}
}

/**
* Removes the given element from the index.
* Removes the given {@link IJaxrsElement} from the index.
*
* @param element
*/
Expand All @@ -177,32 +181,79 @@ public void unindexElement(final IJaxrsElement element) {
final Term identifierTerm = LuceneDocumentFactory.getIdentifierTerm(element);
indexWriter.deleteDocuments(identifierTerm);
indexWriter.commit();
} catch (Exception e) {
} catch (IOException e) {
Logger.error("Failed to unindex the JAX-RS Element " + element, e);
} finally {
Logger.traceIndexing("Done unindexing {}.", element.getName());
}
}

/**
* Removes the given Endpoint from the index.
* Removes the given {@link IJaxrsEndpoint} from the index.
*
* @param element
*/
// TODO: avoid code duplication with unindexElement(IJaxrsElement) above
public void unindexEndpoint(final JaxrsEndpoint endpoint) {
public void unindexEndpoint(final IJaxrsEndpoint endpoint) {
try {
Logger.debugIndexing("Unindexing {} after removal...", endpoint);
final Term identifierTerm = LuceneDocumentFactory.getIdentifierTerm(endpoint);
indexWriter.deleteDocuments(identifierTerm);
indexWriter.commit();
} catch (Exception e) {
} catch (IOException e) {
Logger.error("Failed to unindex the JAX-RS Element " + endpoint, e);
} finally {
Logger.traceIndexing("Done unindexing {}.", endpoint);
}
}

/**
* Index the given {@link IMarker}
* @param marker the marker to index
*/
public void indexMarker(final IMarker marker) {
try {
Logger.traceIndexing("Indexing {} after addition...", marker);
final Document doc = LuceneDocumentFactory.createDocument(marker);
Logger.debugIndexing("Adding Marker into index with following fields: {}", doc.getFields());
indexWriter.addDocument(doc);
indexWriter.commit();
} catch (IOException e) {
Logger.error("Failed to index the JAX-RS Endpoint " + marker, e);
} finally {
Logger.traceIndexing(" Done indexing {}.", marker);
}


}

/**
* Unindex the markers on the given {@link IResource}, whatever their associated {@link LuceneFields#FIELD_MARKER_TYPE}
* @param the resource on which markers should be removed from the index
*/
public void unindexMarkers(final IResource resource) {
// skip this step for built-in elements (ie: not associated with an IResource)
if(resource == null) {
return;
}
try {
Logger.debugIndexing("Unindexing markers on {} after removal...", resource.getFullPath());
final Term elementTypeTerm = LuceneDocumentFactory.getMarkerTypeTerm();
final Term resourcePathTerm = LuceneDocumentFactory.getResourcePathTerm(resource);
final BooleanQuery deleteResourceMarkersQuery = new BooleanQuery();
deleteResourceMarkersQuery.add(new BooleanClause(new TermQuery(elementTypeTerm), Occur.MUST));
deleteResourceMarkersQuery.add(new BooleanClause(new TermQuery(resourcePathTerm), Occur.MUST));
//Logger.debugIndexing("Removing {} documents from index", searchAll(elementTypeTerm, resourcePathTerm).size());
indexWriter.deleteDocuments(deleteResourceMarkersQuery);
indexWriter.commit();
} catch (IOException e) {
Logger.error("Failed to unindex the Resource " + resource.getFullPath(), e);
} finally {
Logger.traceIndexing("Done unindexing {}.", resource.getFullPath());
}

}

/**
* Performs a {@link BooleanQuery} based on the given {@link TermQuery},
* assuming that each query element is mandatory. This method returns a
Expand Down Expand Up @@ -233,7 +284,7 @@ public String searchSingle(final Term... terms) {
// docIdentifier);
return docIdentifier;
}
} catch (Exception e) {
} catch (IOException e) {
Logger.error("Failed to search for JAX-RS element in index", e);
}
Logger.traceIndexing(" Not document matched the query.");
Expand Down Expand Up @@ -261,12 +312,12 @@ public List<String> searchAll(final Term... terms) {
}
}
Logger.traceIndexing("Searching documents matching {}", query.toString());
final AllResultsCollector collector = new AllResultsCollector(searcher);
searcher.search(query, collector);
final List<String> docIdentifiers = collector.getDocIdentifiers();
final AllResultsCollector docIdsCollector = new AllResultsCollector(searcher);
searcher.search(query, docIdsCollector);
final List<String> docIdentifiers = new ArrayList<String>(docIdsCollector.getDocIdentifiers());
Logger.traceIndexing(" Found {} matching documents", docIdentifiers.size());
return docIdentifiers;
} catch (Exception e) {
} catch (IOException e) {
Logger.error("Failed to search for JAX-RS element in index", e);
}
return Collections.emptyList();
Expand Down Expand Up @@ -294,7 +345,7 @@ public int count(final Term... terms) {
final int totalHits = collector.getTotalHits();
Logger.traceIndexing(" Found {} matching documents", totalHits);
return totalHits;
} catch (Exception e) {
} catch (IOException e) {
Logger.error("Failed to search for JAX-RS element in index", e);
}
return 0;
Expand All @@ -311,11 +362,23 @@ private IndexSearcher getNewIndexSearcherIfNeeded() throws IOException {
return this.indexSearcher;
}

/**
* Document IDs Collector. Collectd the mathcing {@link Document}'s
* {@code LuceneDocumentFactory#FIELD_IDENTIFIER} {@link Field} in a
* {@link Set} to avoid duplicate results.
*
* @author xcoulon
*
*/
static class AllResultsCollector extends Collector {

private IndexReader indexReader;

final List<String> docIdentifiers = new ArrayList<String>();
/**
* Set of doc identifiers matching the query. Using a {@link TreeSet} to
* keep order of returned elements.
*/
final Set<String> docIdentifiers = new TreeSet<String>();

private int docBase;

Expand All @@ -333,7 +396,7 @@ public void collect(int docId) throws IOException {
indexReader.isDeleted(docId));
final Document document = indexReader.document(docId);
final String docIdentifier = document.get(LuceneFields.FIELD_IDENTIFIER);
final String docCategory = document.get(LuceneFields.FIELD_CATEGORY);
final String docCategory = document.get(LuceneFields.FIELD_TYPE);
Logger.traceIndexing(" Retrieved document #{} ({})", docIdentifier, docCategory);
docIdentifiers.add(docIdentifier);
}
Expand All @@ -349,7 +412,7 @@ public boolean acceptsDocsOutOfOrder() {
return true;
}

public List<String> getDocIdentifiers() throws CorruptIndexException, IOException {
public Set<String> getDocIdentifiers() throws CorruptIndexException, IOException {
return docIdentifiers;
}

Expand Down
Expand Up @@ -14,7 +14,6 @@
import static org.jboss.tools.ws.jaxrs.core.internal.metamodel.indexation.LuceneFields.FIELD_ANNOTATION_NAME;
import static org.jboss.tools.ws.jaxrs.core.internal.metamodel.indexation.LuceneFields.FIELD_APPLICATION_PATH;
import static org.jboss.tools.ws.jaxrs.core.internal.metamodel.indexation.LuceneFields.FIELD_BUILT_IN_HTTP_METHOD;
import static org.jboss.tools.ws.jaxrs.core.internal.metamodel.indexation.LuceneFields.FIELD_CATEGORY;
import static org.jboss.tools.ws.jaxrs.core.internal.metamodel.indexation.LuceneFields.FIELD_COMPILATION_UNIT_IDENTIFIER;
import static org.jboss.tools.ws.jaxrs.core.internal.metamodel.indexation.LuceneFields.FIELD_CONSUMED_MEDIA_TYPE;
import static org.jboss.tools.ws.jaxrs.core.internal.metamodel.indexation.LuceneFields.FIELD_HTTP_VERB;
Expand All @@ -25,12 +24,15 @@
import static org.jboss.tools.ws.jaxrs.core.internal.metamodel.indexation.LuceneFields.FIELD_JAVA_ELEMENT;
import static org.jboss.tools.ws.jaxrs.core.internal.metamodel.indexation.LuceneFields.FIELD_JAVA_PROJECT_IDENTIFIER;
import static org.jboss.tools.ws.jaxrs.core.internal.metamodel.indexation.LuceneFields.FIELD_JAXRS_ELEMENT;
import static org.jboss.tools.ws.jaxrs.core.internal.metamodel.indexation.LuceneFields.FIELD_MARKER_IDENTIFIER;
import static org.jboss.tools.ws.jaxrs.core.internal.metamodel.indexation.LuceneFields.FIELD_MARKER_TYPE;
import static org.jboss.tools.ws.jaxrs.core.internal.metamodel.indexation.LuceneFields.FIELD_PACKAGE_FRAGMENT_ROOT_IDENTIFIER;
import static org.jboss.tools.ws.jaxrs.core.internal.metamodel.indexation.LuceneFields.FIELD_PARENT_IDENTIFIER;
import static org.jboss.tools.ws.jaxrs.core.internal.metamodel.indexation.LuceneFields.FIELD_PRODUCED_MEDIA_TYPE;
import static org.jboss.tools.ws.jaxrs.core.internal.metamodel.indexation.LuceneFields.FIELD_PROVIDER_KIND;
import static org.jboss.tools.ws.jaxrs.core.internal.metamodel.indexation.LuceneFields.FIELD_RESOURCE_PATH;
import static org.jboss.tools.ws.jaxrs.core.internal.metamodel.indexation.LuceneFields.FIELD_RETURNED_TYPE_NAME;
import static org.jboss.tools.ws.jaxrs.core.internal.metamodel.indexation.LuceneFields.FIELD_TYPE;
import static org.jboss.tools.ws.jaxrs.core.internal.metamodel.indexation.LuceneFields.FIELD_URI_PATH_TEMPLATE;
import static org.jboss.tools.ws.jaxrs.core.internal.metamodel.indexation.LuceneFields.FIELD_WEBXML_APPLICATION;
import static org.jboss.tools.ws.jaxrs.core.internal.metamodel.indexation.LuceneFields.FIELD_WEBXML_APPLICATION_OVERRIDES_JAVA_APPLICATION;
Expand All @@ -41,6 +43,8 @@
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.Term;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IResource;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IType;
import org.jboss.tools.ws.jaxrs.core.internal.metamodel.domain.JaxrsHttpMethod;
Expand All @@ -51,6 +55,7 @@
import org.jboss.tools.ws.jaxrs.core.internal.metamodel.domain.JaxrsResourceField;
import org.jboss.tools.ws.jaxrs.core.internal.metamodel.domain.JaxrsResourceMethod;
import org.jboss.tools.ws.jaxrs.core.internal.metamodel.domain.JaxrsWebxmlApplication;
import org.jboss.tools.ws.jaxrs.core.internal.metamodel.validation.JaxrsMetamodelValidator;
import org.jboss.tools.ws.jaxrs.core.jdt.Annotation;
import org.jboss.tools.ws.jaxrs.core.metamodel.domain.EnumElementKind;
import org.jboss.tools.ws.jaxrs.core.metamodel.domain.IJaxrsApplication;
Expand All @@ -74,8 +79,34 @@ public static Term getIdentifierTerm(final IJaxrsEndpoint element) {
return new Term(FIELD_IDENTIFIER, element.getIdentifier());
}

public static Term getResourcePathTerm(final IResource resource) {
return new Term(FIELD_IDENTIFIER, resource.getFullPath().toPortableString());
}

public static Term getMarkerTypeTerm() {
return new Term(FIELD_TYPE, IMarker.class.getSimpleName());
}

/**
* Creates a Lucene {@link Document} from the given {@link IMarker}.
*
* @param element
* @return the Lucene document or null if the given element is supposed to
* be indexed.
*/
public static Document createDocument(final IMarker marker) {
final Document document = new Document();
// we use the resource path as an identifier
addFieldToDocument(document, FIELD_IDENTIFIER, marker.getResource().getFullPath().toPortableString());
addFieldToDocument(document, FIELD_MARKER_IDENTIFIER, Long.toString(marker.getId()));
addFieldToDocument(document, FIELD_TYPE, IMarker.class.getSimpleName());
addFieldToDocument(document, FIELD_MARKER_TYPE, marker.getAttribute(JaxrsMetamodelValidator.JAXRS_PROBLEM_TYPE, null));
return document;
}


/**
* Creates a Lucene document from the given JAX-RS element.
* Creates a Lucene {@link Document} from the given {@link IJaxrsElement}.
*
* @param element
* @return the Lucene document or null if the given element is supposed to
Expand Down Expand Up @@ -105,17 +136,16 @@ public static Document createDocument(final IJaxrsElement element) {
return null;
}
/**
* Creates a Lucene document from the given JAX-RS Endpoint.
* Creates a Lucene document from the given {@link IJaxrsEndpoint}.
*
* @param element
* @return the Lucene document or null if the given element is supposed to
* be indexed.
* @param element the JAX-RS endpoint to index.
* @return the Lucene document used to index the given JAX-RS endpoint.
*/
public static Document createDocument(final IJaxrsEndpoint endpoint) {
final Document document = new Document();
addFieldToDocument(document, FIELD_IDENTIFIER, endpoint.getIdentifier());
addFieldToDocument(document, FIELD_JAVA_PROJECT_IDENTIFIER, getHandleIdentifier(endpoint.getJavaProject()));
addFieldToDocument(document, FIELD_CATEGORY, endpoint.getElementCategory().toString());
addFieldToDocument(document, FIELD_TYPE, endpoint.getElementCategory().toString());
addFieldToDocument(document, FIELD_CONSUMED_MEDIA_TYPE, endpoint.getConsumedMediaTypes());
addFieldToDocument(document, FIELD_PRODUCED_MEDIA_TYPE, endpoint.getProducedMediaTypes());
addFieldToDocument(document, FIELD_URI_PATH_TEMPLATE, endpoint.getUriPathTemplate());
Expand Down Expand Up @@ -195,7 +225,7 @@ private static String getHandleIdentifier(final IJavaElement javaElement) {
private static Document createBaseDocument(JaxrsJavaElement<?> element) {
final Document document = new Document();
addFieldToDocument(document, FIELD_JAVA_PROJECT_IDENTIFIER, getHandleIdentifier(element.getMetamodel().getJavaProject()));
addFieldToDocument(document, FIELD_CATEGORY, element.getElementKind().getCategory().toString());
addFieldToDocument(document, FIELD_TYPE, element.getElementKind().getCategory().toString());
addFieldToDocument(document, FIELD_IDENTIFIER, element.getIdentifier());
if (element.getJavaElement() != null) {
addFieldToDocument(document, FIELD_JAVA_ELEMENT, Boolean.TRUE.toString());
Expand Down Expand Up @@ -247,7 +277,7 @@ private static Document createWebxmlApplicationDocument(final JaxrsWebxmlApplica
final Document document = new Document();
addFieldToDocument(document, FIELD_JAVA_PROJECT_IDENTIFIER, webxmlApplication.getMetamodel().getJavaProject()
.getHandleIdentifier());
addFieldToDocument(document, FIELD_CATEGORY, webxmlApplication.getElementKind().getCategory().toString());
addFieldToDocument(document, FIELD_TYPE, webxmlApplication.getElementKind().getCategory().toString());
addFieldToDocument(document, FIELD_IDENTIFIER, webxmlApplication.getIdentifier());
addFieldToDocument(document, FIELD_WEBXML_APPLICATION, Boolean.TRUE.toString());
addFieldToDocument(document, FIELD_WEBXML_APPLICATION_OVERRIDES_JAVA_APPLICATION, Boolean.toString(webxmlApplication.isOverride()));
Expand Down

0 comments on commit 2fa9be0

Please sign in to comment.