blob: 65d87cdc76e0d690dc38e35d21f586fca86b088d [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2004, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - Initial API and implementation
*******************************************************************************/
package org.eclipse.wst.xml.core.internal.search.quickscan;
import java.util.HashMap;
import java.util.Map;
import java.util.Stack;
import org.eclipse.wst.common.core.search.document.ComponentDeclarationEntry;
import org.eclipse.wst.common.core.search.document.ComponentReferenceEntry;
import org.eclipse.wst.common.core.search.document.FileReferenceEntry;
import org.eclipse.wst.common.core.search.document.SearchDocument;
import org.eclipse.wst.common.core.search.pattern.QualifiedName;
import org.eclipse.wst.common.core.search.pattern.SearchPattern;
import org.eclipse.wst.xml.core.internal.search.XMLComponentDeclarationPattern;
import org.eclipse.wst.xml.core.internal.search.XMLComponentReferencePattern;
import org.eclipse.wst.xml.core.internal.search.impl.IXMLSearchConstants;
import org.eclipse.wst.xml.core.internal.search.matching.PatternMatcher;
import org.eclipse.wst.xml.core.internal.search.matching.SAXSearchElement;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
/**
* This class is a SAX content handler, it should be recycled before scanning a file for the new SearchPattern.
*
*/
public class XMLQuickScanContentHandler extends DefaultHandler
{
private Map namespaceMap = new HashMap(); // Map of string prefix keys and namespace
private String targetNamespace = ""; //$NON-NLS-1$
private SearchPattern pattern;
private SearchDocument document; // we'll add useful entries in the search document as we parsing
private SAXSearchElement searchElement = new SAXSearchElement();
private boolean hasMatch = false;
private Stack currentPath = new Stack();
private PatternMatcher matcher;
public static final String XMLSCHEMA_NAMESPACE = "http://www.w3.org/2001/XMLSchema"; //$NON-NLS-1$
public static final String WSDL_NAMESPACE = "http://schemas.xmlsoap.org/wsdl/"; //$NON-NLS-1$
public XMLQuickScanContentHandler(PatternMatcher matcher, SearchPattern pattern) {
super();
this.pattern = pattern;
this.matcher = matcher;
}
public XMLQuickScanContentHandler(SearchDocument document, PatternMatcher matcher, SearchPattern pattern) {
super();
this.pattern = pattern;
this.matcher = matcher;
this.document = document;
}
public XMLQuickScanContentHandler() {
super();
}
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException
{
// Search for targetNamespace if we haven't encountered it yet.
if (targetNamespace.equals("")) //$NON-NLS-1$
{
int nAttributes = attributes.getLength();
for (int i = 0; i < nAttributes; i++)
{
if ("targetNamespace".equals(attributes.getQName(i))) //$NON-NLS-1$
{
targetNamespace = attributes.getValue(i);
break;
}
}
}
// collect link info
// TODO This code should be refactored to delegate the responsibility to
// detect links between files to the search providers/contributors.
// The current code only handles the XSD and WSDL cases.
if("import".equals(localName) && namespaceMatches(uri)){ //$NON-NLS-1$
FileReferenceEntry documentEntry = new FileReferenceEntry();
documentEntry.setCategory(IXMLSearchConstants.REF);
documentEntry.setKey("import"); //$NON-NLS-1$
String namespace = attributes.getValue("namespace"); //$NON-NLS-1$
String location = attributes.getValue(getLocationAttributeName(uri)); //$NON-NLS-1$
documentEntry.setPublicIdentifier(namespace);
documentEntry.setRelativeFilePath(location);
document.putEntry(documentEntry);
}
if(("redefine".equals(localName)|| "include".equals(localName)) && //$NON-NLS-1$ //$NON-NLS-2$
namespaceMatches(uri)){
FileReferenceEntry documentEntry = new FileReferenceEntry();
documentEntry.setCategory(IXMLSearchConstants.REF);
documentEntry.setKey("include"); //$NON-NLS-1$
String location = attributes.getValue(getLocationAttributeName(uri)); //$NON-NLS-1$
documentEntry.setPublicIdentifier(uri);
documentEntry.setRelativeFilePath(location);
document.putEntry(documentEntry);
}
// issue (cs) you may want to try perf measurements to compate reusing the same
// instance of a SAXSearchElement instead of newing one each time
//XMLSearchPattern.SAXSearchElement searchElement = new XMLSearchPattern.SAXSearchElement();
searchElement.setElementName(localName);
searchElement.setElementNamespace(uri);
searchElement.setAttributes(attributes);
searchElement.setNamespaceMap(namespaceMap);
searchElement.setTargetNamespace(targetNamespace);
if (currentPath.size() > 0)
{
String parentName = (String)currentPath.peek();
searchElement.setParentName(parentName);
}
if(matcher != null){
if(matcher.matches(pattern, searchElement)){
hasMatch = true;
if(pattern instanceof XMLComponentReferencePattern){
ComponentReferenceEntry documentEntry = new ComponentReferenceEntry();
documentEntry.setCategory(IXMLSearchConstants.COMPONENT_REF);
QualifiedName name = new QualifiedName(uri, localName);
documentEntry.setKey(name.toString());
documentEntry.setName(name);
document.putEntry(documentEntry);
}
else if(pattern instanceof XMLComponentDeclarationPattern){
ComponentDeclarationEntry documentEntry = new ComponentDeclarationEntry();
documentEntry.setCategory(IXMLSearchConstants.COMPONENT_DECL);
QualifiedName name = new QualifiedName(targetNamespace, attributes.getValue("name")); //$NON-NLS-1$
QualifiedName metaName = new QualifiedName(uri, localName);
documentEntry.setKey(name.toString());
documentEntry.setName(name);
documentEntry.setMetaName(metaName);
document.putEntry(documentEntry);
}
}
}
currentPath.push(localName); //$NON-NLS-1$
}
private String getLocationAttributeName(String uri)
{
if (XMLSCHEMA_NAMESPACE.equals(uri))
{
return "schemaLocation";
}
else if (WSDL_NAMESPACE.equals(uri))
{
return "location";
}
return "";
}
private boolean namespaceMatches(String uri)
{
return XMLSCHEMA_NAMESPACE.equals(uri) ||
WSDL_NAMESPACE.equals(uri);
}
public void endElement(String uri, String localName, String qName)
throws SAXException
{
currentPath.pop();
}
/**
* Callback for SAX parser
*
* @see org.xml.sax.ContentHandler#startPrefixMapping(java.lang.String,
* java.lang.String)
*/
public void startPrefixMapping(String arg0, String arg1)
throws SAXException
{
if (arg0 != null && arg0.length() > 0)
{
this.namespaceMap.put(arg0, arg1);
}
}
public String getTargetNamespace() {
return targetNamespace;
}
public void setTargetNamespace(String targetNamespace) {
this.targetNamespace = targetNamespace;
}
public boolean hasMatch() {
return hasMatch;
}
}