blob: 913ed4481e1b5d4d8b9d54085884c9d9579914a5 [file] [log] [blame]
package org.eclipse.bpel.validator;
/**
* Java JDK dependencies
*/
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.eclipse.bpel.model.Import;
import org.eclipse.bpel.model.Process;
import org.eclipse.bpel.model.resource.BPELResourceSetImpl;
import org.eclipse.bpel.model.resource.SAXParseDiagnostic;
import org.eclipse.bpel.validator.factory.AdapterFactory;
import org.eclipse.bpel.validator.helpers.ModelQueryImpl;
import org.eclipse.bpel.validator.model.INode;
import org.eclipse.bpel.validator.model.IProblem;
import org.eclipse.bpel.validator.model.Messages;
import org.eclipse.bpel.validator.model.Problem;
import org.eclipse.bpel.validator.model.Runner;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.IResourceVisitor;
import org.eclipse.core.resources.IncrementalProjectBuilder;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdapterManager;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.content.IContentDescription;
import org.eclipse.core.runtime.content.IContentType;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.Resource.Diagnostic;
import org.eclipse.wst.wsdl.WSDLElement;
import org.w3c.dom.Element;
/**
* A builder which is invoked to build (in this case validate), the BPEL files
* in the projects in which the builder is installed.
*
* @author Michal Chmielewski (michal.chmielewski@oracle.com)
* @date Sep 19, 2006
*
*/
@SuppressWarnings("nls")
public class Builder extends IncrementalProjectBuilder {
// https://jira.jboss.org/jira/browse/JBIDE-6006
// Content Type ID for org.eclipse.bpel editor files
public static final String BPEL_CONTENT_TYPE = "org.eclipse.bpel.contenttype"; //$NON-NLS-1$
Date created = new Date();
boolean bDebug = false;
/** Empty problems list */
IProblem[] EMPTY_PROBLEMS = {};
/** The adapter manager for the platform */
IAdapterManager fAdapterManager = Platform.getAdapterManager();
BPELResourceSetImpl fResourceSet = new BPELResourceSetImpl();
BPELReader fReader = new BPELReader();
/**
* Create brand new shiny BPEL Builder.
*/
public Builder() {
p("Created on " + this.created);
}
/** (non-Javadoc)
* @see org.eclipse.core.resources.IncrementalProjectBuilder#setInitializationData(org.eclipse.core.runtime.IConfigurationElement, java.lang.String, java.lang.Object)
*/
@Override
public void setInitializationData(IConfigurationElement config, String propertyName, Object data) throws CoreException {
super.setInitializationData(config, propertyName, data);
}
@Override
protected IProject[] build (int kind, Map args, IProgressMonitor monitor)
throws CoreException {
long started = System.currentTimeMillis();
if (args != null) {
this.bDebug = toBoolean(args.get("debug"),false);
}
AdapterFactory.DEBUG = this.bDebug;
if (this.bDebug) {
p("Clear error messages from the cache ... (will re-load)");
Messages.clear();
}
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=330813
// https://jira.jboss.org/browse/JBIDE-7116
clearCach();
IProject myProject = this.getProject();
IResourceDelta resourceDelta = this.getDelta(myProject);
if (resourceDelta == null) {
// Now find all the BPEL files in the project and validate them
validate ( myProject, monitor );
} else {
processDeltas(resourceDelta.getAffectedChildren( IResourceDelta.CHANGED ), monitor );
}
long ended = System.currentTimeMillis();
p(" Validation Ended " + (ended-started) + "ms");
return new IProject[] { myProject };
}
void processDeltas ( IResourceDelta [] deltas , IProgressMonitor monitor ) throws CoreException {
for(IResourceDelta delta : deltas) {
processDeltas( delta.getAffectedChildren(IResourceDelta.CHANGED, IResource.FILE), monitor );
IResource resource = delta.getResource();
if (resource.getType () != IResource.FILE) {
continue;
}
// * @see IResourceDelta#CONTENT
// * @see IResourceDelta#DESCRIPTION
// * @see IResourceDelta#ENCODING
// * @see IResourceDelta#OPEN
// * @see IResourceDelta#MOVED_TO
// * @see IResourceDelta#MOVED_FROM
// * @see IResourceDelta#TYPE
// * @see IResourceDelta#SYNC
// * @see IResourceDelta#MARKERS
// * @see IResourceDelta#REPLACED
if ((delta.getFlags() & IResourceDelta.CONTENT) != IResourceDelta.CONTENT ) {
continue;
}
this.fResourceSet.resourceChanged((IFile)resource);
validate ( resource, monitor );
}
}
/**
* @see org.eclipse.core.resources.IncrementalProjectBuilder#clean(org.eclipse.core.runtime.IProgressMonitor)
*/
@Override
protected void clean (IProgressMonitor monitor) throws CoreException {
removeProblemsAndTasksFor(getProject());
}
public static void removeProblemsAndTasksFor(IResource resource) {
try {
if (resource != null && resource.exists()) {
resource.deleteMarkers(IBPELMarker.ID, false, IResource.DEPTH_INFINITE);
}
} catch (CoreException e) {
// assume there were no problems
}
}
/**
* Validate the resource using the monitor passed.
*
* @param resource (File or Folder)
* @param monitor the monitor to use.
* @throws CoreException
*/
public void validate (IResource resource, IProgressMonitor monitor) throws CoreException {
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=330813
// https://jira.jboss.org/browse/JBIDE-7116
// enable element location tracking for error reporting
// TODO: move this to somewhere more appropriate when fixing JBIDE-6839
Map<Object, Object> loadOptions = this.fResourceSet.getLoadOptions();
loadOptions.put("TRACK_LOCATION", Boolean.TRUE);
this.fResourceSet.setLoadOptions(loadOptions);
switch (resource.getType()) {
case IResource.FOLDER :
IFolder folder = (IFolder) resource;
for(IResource next : folder.members() ) {
validate (next,monitor);
}
break;
case IResource.FILE :
IFile file = (IFile) resource;
p("File Resource : " + file.getName() );
// https://jira.jboss.org/jira/browse/JBIDE-6006
// use content type to check for BPEL files
if ( isBPELFile(file) || "wsdl".equalsIgnoreCase(file.getFileExtension()) ) {
IProject project = file.getProject();
validate(project, monitor);
// file.deleteMarkers(IBPELMarker.ID, true, IResource.DEPTH_INFINITE);
// deleteMarkersInReferencialResources(file);
// makeMarkers ( validate ( file, monitor ) );
}
break;
case IResource.PROJECT:
for(IFile bpelFile : getBPELFilesByProject((IProject)resource)){
p("File Resource : " + bpelFile.getName() );
bpelFile.deleteMarkers(IBPELMarker.ID, true, IResource.DEPTH_INFINITE);
deleteMarkersInReferencialResources(bpelFile);
makeMarkers ( validate ( bpelFile, monitor ) );
}
}
}
private List<IFile> getBPELFilesByProject(IProject project){
final List<IFile> bpelFolders = new ArrayList<IFile>();
IResourceVisitor bpelFolderFinder = new IResourceVisitor() {
@Override
public boolean visit(IResource resource) throws CoreException {
if( resource.getType() == IResource.FILE){
// https://jira.jboss.org/jira/browse/JBIDE-6006
if(isBPELFile(resource)){
bpelFolders.add((IFile)resource);
return false;
}
}
return true;
}
};
try {
project.accept(bpelFolderFinder);
} catch (CoreException e) {
e.printStackTrace();
}
return bpelFolders;
}
private void deleteMarkersInReferencialResources(IFile bpelFile) throws CoreException{
this.fResourceSet.resourceChanged(bpelFile);
this.fReader.read( bpelFile, this.fResourceSet );
Process process = this.fReader.getProcess();
p("Delete markers");
// https://jira.jboss.org/browse/JBIDE-6825
// in case of XML parse errors, the Process will be null!
if (process == null) {
p ("Cannot read BPEL Process !!!");
return;
}
IContainer container = bpelFile.getParent();
for(Import impt : process.getImports()){
String fileLocation = impt.getLocation();
IFile importedFile = container.getFile(new Path(fileLocation));
if(importedFile != null && importedFile.exists()){
importedFile.deleteMarkers(IBPELMarker.ID, false, IResource.DEPTH_ZERO);
}
}
}
public void clearCach(){
this.fResourceSet.getResources().clear();
}
/**
* @param file
* @param monitor
* @return return the list of problems found
*/
public IProblem[] validate (IFile file, IProgressMonitor monitor ) {
p("Validating BPEL Resource : " + file.getName() );
// Step 1. Read the BPEL process using the Model API.
this.fResourceSet.resourceChanged(file);
this.fReader.read( file, this.fResourceSet );
Process process = this.fReader.getProcess();
if (process == null) {
// https://jira.jboss.org/browse/JBIDE-6825
// if the resource failed to parse because of malformed XML, the Process
// will be null. Fetch the SAXParseDiagnostics from the resource and build
// problem markers for this resource.
Resource resource = this.fReader.getProcessResource();
if ( resource!=null && !resource.getErrors().isEmpty() )
{
ArrayList<IProblem> problems = new ArrayList<IProblem>(resource.getErrors().size());
for ( Diagnostic d : resource.getErrors())
{
IProblem problem = new Problem();
problem.setAttribute(IProblem.ERESOURCE,resource);
if (d instanceof SAXParseDiagnostic &&
((SAXParseDiagnostic)d).getSeverity() == SAXParseDiagnostic.WARNING)
{
problem.setAttribute(IProblem.SEVERITY, IProblem.SEVERITY_WARNING);
}
else
problem.setAttribute(IProblem.SEVERITY, IProblem.SEVERITY_ERROR);
problem.setAttribute(IProblem.LINE_NUMBER, d.getLine());
problem.setAttribute(IProblem.COLUMN_NUMBER, d.getColumn());
problem.setAttribute(IProblem.MESSAGE, d.getMessage());
problems.add(problem);
}
return problems.toArray( new Problem[problems.size()] );
}
p ("Cannot read BPEL Process !!!");
return this.EMPTY_PROBLEMS ;
}
p("Read in BPEL Model OK" );
// Step 2. Preparation for the validator.
linkModels ( process );
p("Models Linked" );
// Process as INode
INode node = (INode) this.fAdapterManager.getAdapter( process.getElement(), INode.class );
// Debug: Dump the dom from the reader, just to see what we have
// p( org.eclipse.bpel.model.util.BPELUtils.elementToString(process.getElement()));
// Step 4. Run the validator.
IProblem[] problemList = new Runner (ModelQueryImpl.getModelQuery(), node ).run();
p("Validator Executed" );
return problemList;
}
/**
* @param problemList
*/
public void makeMarkers ( IProblem [] problemList ) {
if (problemList.length < 1) {
return ;
}
// Step 5. Adapt problems to markers.
for(IProblem problem : problemList) {
this.fAdapterManager.getAdapter(problem, IMarker.class);
}
p( "Markers Created " );
p( " ------ Done" );
// done.
}
void linkModels ( EObject process ) {
//
// Each extensible element points to the DOM element that
// comprises it. This is done in the BPEL reader as well as
// the WSDL readers. Here we add a pointer to the
// emf objects from the DOM objects.
Iterator<?> emfIterator = process.eAllContents();
while (emfIterator.hasNext()) {
Object obj = emfIterator.next();
// This is because only WSDLElement has a reference to
// a DOM element.
if (obj instanceof WSDLElement) {
WSDLElement wsdle = (WSDLElement) obj;
Element el = wsdle.getElement();
if (el != null) {
// System.out.println(el.getOwnerDocument().getDocumentURI() + " " + el.getLocalName() + "----" + obj);
el.setUserData("emf.model", obj, null); //$NON-NLS-1$
}
}
}
}
@SuppressWarnings("boxing")
boolean toBoolean ( Object obj , boolean def) {
if (obj instanceof String) {
return Boolean.valueOf((String)obj);
}
return def;
}
void p (String msg ) {
if (this.bDebug) {
System.out.printf( "[%1$s]>> %2$s\n", getClass().getName(), msg);
System.out.flush();
}
}
// https://jira.jboss.org/jira/browse/JBIDE-6006
public static boolean isBPELFile(IResource res)
{
try
{
if (res.getType() == IResource.FILE) {
IContentDescription desc = ((IFile) res).getContentDescription();
if (desc != null) {
IContentType type = desc.getContentType();
if (type.getId().equals(BPEL_CONTENT_TYPE))
return true;
}
}
}
catch(Exception ex)
{
}
return false;
}
}