/*******************************************************************************
* Copyright (c) 2007 Red Hat, Inc.
* Distributed under license by Red Hat, Inc. All rights reserved.
* This program is 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:
* Red Hat, Inc. - initial API and implementation
******************************************************************************/
package org.jboss.tools.seam.internal.core.validation;
import java.io.IOException;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.jobs.ISchedulingRule;
import org.eclipse.ui.editors.text.TextFileDocumentProvider;
import org.eclipse.wst.common.componentcore.ComponentCore;
import org.eclipse.wst.common.componentcore.resources.IVirtualComponent;
import org.eclipse.wst.common.componentcore.resources.IVirtualFolder;
import org.eclipse.wst.common.componentcore.resources.IVirtualReference;
import org.eclipse.wst.sse.core.StructuredModelManager;
import org.eclipse.wst.sse.core.internal.provisional.IModelManager;
import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionList;
import org.eclipse.wst.validation.internal.core.ValidationException;
import org.eclipse.wst.validation.internal.operations.WorkbenchContext;
import org.eclipse.wst.validation.internal.operations.WorkbenchReporter;
import org.eclipse.wst.validation.internal.provisional.core.IMessage;
import org.eclipse.wst.validation.internal.provisional.core.IReporter;
import org.eclipse.wst.validation.internal.provisional.core.IValidationContext;
import org.eclipse.wst.validation.internal.provisional.core.IValidatorJob;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocument;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
import org.jboss.tools.common.validation.ValidationErrorManager;
import org.jboss.tools.seam.core.ISeamProject;
import org.jboss.tools.seam.core.SeamCorePlugin;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
* This validator is workaround for bug of WTP 2.0.2
* See http://jira.jboss.com/jira/browse/JBIDE-2117
* @author Alexey Kazakov
*/
public class SeamEarProjectValidator implements IValidatorJob {
/* (non-Javadoc)
* @see org.eclipse.wst.validation.internal.provisional.core.IValidatorJob#getSchedulingRule(org.eclipse.wst.validation.internal.provisional.core.IValidationContext)
*/
public ISchedulingRule getSchedulingRule(IValidationContext helper) {
return null;
}
/* (non-Javadoc)
* @see org.eclipse.wst.validation.internal.provisional.core.IValidatorJob#validateInJob(org.eclipse.wst.validation.internal.provisional.core.IValidationContext, org.eclipse.wst.validation.internal.provisional.core.IReporter)
*/
public IStatus validateInJob(IValidationContext helper, IReporter reporter) throws ValidationException {
IProject project = ((WorkbenchContext)helper).getProject();
if(!project.isAccessible()) {
return OK_STATUS;
}
WorkbenchReporter.removeAllMessages(project, new String[]{this.getClass().getName()}, null);
IVirtualComponent component = ComponentCore.createComponent(project);
IVirtualReference[] rs = component.getReferences();
for (int i = 0; i < rs.length; i++) {
IVirtualComponent c = rs[i].getReferencedComponent();
if(c == null) {
continue;
}
IVirtualFolder folder = c.getRootFolder();
if(folder==null) {
continue;
}
ISeamProject seamProject = SeamCorePlugin.getSeamProject(folder.getProject(), false);
if(seamProject!=null) {
IVirtualFolder earRootFolder = component.getRootFolder().getFolder(new Path("/")); //$NON-NLS-1$
if(earRootFolder!=null) {
IFolder f = (IFolder)earRootFolder.getUnderlyingFolder();
if(f!=null ) {
validateApplicationXml(f.findMember(new Path("META-INF/application.xml")));
}
}
break;
}
}
return OK_STATUS;
}
private static final String MODULE_NODE_NAME = "module";
private static final String JAVA_NODE_NAME = "java";
private static final String SEAM_JAR_NAME = "jboss-seam.jar";
private static final String[] JARS = new String[]{
"el-ri",
"jbpm",
"drools-core",
"drools-compiler",
"janino",
"antlr",
"commons-jci-core",
"commons-jci-janino",
"stringtemplate",
"jboss-el",
"jbpm-jpdl",
"mvel14",
"richfaces-api"};
private void validateApplicationXml(IResource applicationXml) {
if(applicationXml==null || !(applicationXml instanceof IFile) || !applicationXml.exists()) {
return;
}
IModelManager manager = StructuredModelManager.getModelManager();
if(manager == null) {
return;
}
IStructuredModel model = null;
try {
model = manager.getModelForRead((IFile)applicationXml);
if (model instanceof IDOMModel) {
IDOMModel domModel = (IDOMModel) model;
IDOMDocument document = domModel.getDocument();
Element root = document.getDocumentElement();
if(root==null) {
return;
}
NodeList children = root.getChildNodes();
for(int i=0; i<children.getLength(); i++) {
Node curentValidatedNode = children.item(i);
if(Node.ELEMENT_NODE == curentValidatedNode.getNodeType() && MODULE_NODE_NAME.equals(curentValidatedNode.getNodeName())) {
NodeList moduleChildren = curentValidatedNode.getChildNodes();
for(int j=0; j<moduleChildren.getLength(); j++) {
Node child = moduleChildren.item(j);
if(Node.ELEMENT_NODE == child.getNodeType() && JAVA_NODE_NAME.equals(child.getNodeName())) {
validateJavaModule(applicationXml, child);
}
}
}
}
}
} catch (CoreException e) {
SeamCorePlugin.getDefault().logError(e);
} catch (IOException e) {
SeamCorePlugin.getDefault().logError(e);
} finally {
if (model != null) {
model.releaseFromRead();
}
}
}
private void validateJavaModule(IResource file, Node node) {
NodeList children = node.getChildNodes();
for(int i=0; i<children.getLength(); i++) {
Node child = children.item(i);
if(Node.TEXT_NODE == child.getNodeType()) {
IStructuredDocumentRegion strRegion = ((IDOMNode)child).getFirstStructuredDocumentRegion();
ITextRegionList regions = strRegion.getRegions();
for(int j=0; j<regions.size(); j++) {
ITextRegion region = regions.get(j);
if(region.getType() == DOMRegionContext.XML_CONTENT) {
String text = strRegion.getFullText(region);
int offset = strRegion.getStartOffset() + region.getStart();
validateJarName(file, text, offset);
}
}
}
}
}
private void validateJarName(IResource file, String text, int offset) {
String jarName = text.trim();
TextFileDocumentProvider documentProvider = new TextFileDocumentProvider();
for(int jarIndex=0; jarIndex<JARS.length; jarIndex++) {
int position = offset + text.indexOf(jarName);
int length = jarName.length();
if(SEAM_JAR_NAME.equals(jarName)) {
ValidationErrorManager.addError(SeamValidationMessages.INVALID_JAR_MODULE_IN_APPLICATION_XML, IMessage.HIGH_SEVERITY, new String[]{jarName}, 0, length, position, file, documentProvider, SeamValidationErrorManager.MARKED_SEAM_PROJECT_MESSAGE_GROUP, this.getClass(), 0, null);
break;
}
if(jarName.startsWith(JARS[jarIndex])) {
ValidationErrorManager.addError(SeamValidationMessages.INVALID_JAR_MODULE_IN_APPLICATION_XML, IMessage.NORMAL_SEVERITY, new String[]{jarName}, 0, length, position, file, documentProvider, SeamValidationErrorManager.MARKED_SEAM_PROJECT_MESSAGE_GROUP, this.getClass(), 0, null);
break;
}
}
}
/* (non-Javadoc)
* @see org.eclipse.wst.validation.internal.provisional.core.IValidator#cleanup(org.eclipse.wst.validation.internal.provisional.core.IReporter)
*/
public void cleanup(IReporter reporter) {
}
/* (non-Javadoc)
* @see org.eclipse.wst.validation.internal.provisional.core.IValidator#validate(org.eclipse.wst.validation.internal.provisional.core.IValidationContext, org.eclipse.wst.validation.internal.provisional.core.IReporter)
*/
public void validate(IValidationContext helper, IReporter reporter) throws ValidationException {
validateInJob(helper, reporter);
}
}