1 11 package org.eclipse.pde.internal.builders; 12 13 import java.io.File ; 14 import java.util.ArrayList ; 15 import java.util.HashSet ; 16 import java.util.StringTokenizer ; 17 18 import org.eclipse.core.resources.IFile; 19 import org.eclipse.core.runtime.IPath; 20 import org.eclipse.core.runtime.IProgressMonitor; 21 import org.eclipse.core.runtime.Path; 22 import org.eclipse.jdt.core.IJavaProject; 23 import org.eclipse.jdt.core.IType; 24 import org.eclipse.jdt.core.JavaCore; 25 import org.eclipse.jdt.core.JavaModelException; 26 import org.eclipse.osgi.util.NLS; 27 import org.eclipse.pde.core.plugin.IPluginExtensionPoint; 28 import org.eclipse.pde.core.plugin.IPluginModelBase; 29 import org.eclipse.pde.internal.PDEMessages; 30 import org.eclipse.pde.internal.core.AbstractModel; 31 import org.eclipse.pde.internal.core.NLResourceHelper; 32 import org.eclipse.pde.internal.core.PDECore; 33 import org.eclipse.pde.internal.core.TargetPlatform; 34 import org.eclipse.pde.internal.core.ischema.IMetaAttribute; 35 import org.eclipse.pde.internal.core.ischema.ISchema; 36 import org.eclipse.pde.internal.core.ischema.ISchemaAttribute; 37 import org.eclipse.pde.internal.core.ischema.ISchemaComplexType; 38 import org.eclipse.pde.internal.core.ischema.ISchemaCompositor; 39 import org.eclipse.pde.internal.core.ischema.ISchemaElement; 40 import org.eclipse.pde.internal.core.ischema.ISchemaEnumeration; 41 import org.eclipse.pde.internal.core.ischema.ISchemaObject; 42 import org.eclipse.pde.internal.core.ischema.ISchemaObjectReference; 43 import org.eclipse.pde.internal.core.ischema.ISchemaRestriction; 44 import org.eclipse.pde.internal.core.ischema.ISchemaSimpleType; 45 import org.eclipse.pde.internal.core.ischema.ISchemaType; 46 import org.eclipse.pde.internal.core.schema.SchemaRegistry; 47 import org.eclipse.pde.internal.core.util.CoreUtility; 48 import org.eclipse.pde.internal.core.util.IdUtil; 49 import org.w3c.dom.Attr ; 50 import org.w3c.dom.Element ; 51 import org.w3c.dom.NamedNodeMap ; 52 import org.w3c.dom.Node ; 53 import org.w3c.dom.NodeList ; 54 import org.xml.sax.SAXException ; 55 56 public class ExtensionsErrorReporter extends ManifestErrorReporter { 57 58 IPluginModelBase fModel; 59 60 public ExtensionsErrorReporter(IFile file) { 61 super(file); 62 fModel = PDECore.getDefault().getModelManager().findModel(file.getProject()); 63 } 64 65 68 public void characters(char[] characters, int start, int length) 69 throws SAXException { 70 } 71 72 public void validateContent(IProgressMonitor monitor) { 73 Element element = getDocumentRoot(); 74 if (element == null) 75 return; 76 String elementName = element.getNodeName(); 77 if (!"plugin".equals(elementName) && !"fragment".equals(elementName)) { reportIllegalElement(element, CompilerFlags.ERROR); 79 } else { 80 int severity = CompilerFlags.getFlag(fProject, CompilerFlags.P_DEPRECATED); 81 if (severity != CompilerFlags.IGNORE) { 82 NamedNodeMap attrs = element.getAttributes(); 83 for (int i = 0; i < attrs.getLength(); i++) { 84 reportUnusedAttribute(element, attrs.item(i).getNodeName(), severity); 85 } 86 } 87 88 NodeList children = element.getChildNodes(); 89 for (int i = 0; i < children.getLength(); i++) { 90 if (monitor.isCanceled()) 91 break; 92 Element child = (Element)children.item(i); 93 String name = child.getNodeName(); 94 if (name.equals("extension")) { validateExtension(child); 96 } else if (name.equals("extension-point")) { validateExtensionPoint(child); 98 } else { 99 if (!name.equals("runtime") && !name.equals("requires")) { severity = CompilerFlags.getFlag(fProject, CompilerFlags.P_UNKNOWN_ELEMENT); 101 if (severity != CompilerFlags.IGNORE) 102 reportIllegalElement(child, severity); 103 } else { 104 severity = CompilerFlags.getFlag(fProject, CompilerFlags.P_DEPRECATED); 105 if (severity != CompilerFlags.IGNORE) 106 reportUnusedElement(child, severity); 107 } 108 } 109 } 110 } 111 } 112 113 protected void validateExtension(Element element) { 114 if (!assertAttributeDefined(element, "point", CompilerFlags.ERROR)) return; 116 String pointID = element.getAttribute("point"); IPluginExtensionPoint point = PDECore.getDefault().findExtensionPoint(pointID); 118 if (point == null) { 119 int severity = CompilerFlags.getFlag(fProject, CompilerFlags.P_UNRESOLVED_EX_POINTS); 120 if (severity != CompilerFlags.IGNORE) { 121 report(NLS.bind(PDEMessages.Builders_Manifest_ex_point, pointID), getLine(element, "point"), severity); } 124 } else { 125 SchemaRegistry registry = PDECore.getDefault().getSchemaRegistry(); 126 ISchema schema = registry.getSchema(pointID); 127 if (schema != null) { 128 validateElement(element, schema); 129 } 130 } 131 } 132 133 protected void validateElement(Element element, ISchema schema) { 134 String elementName = element.getNodeName(); 135 ISchemaElement schemaElement = schema.findElement(elementName); 136 137 ISchemaElement parentSchema = null; 138 if (!"extension".equals(elementName)) { Node parent = element.getParentNode(); 140 parentSchema = schema.findElement(parent.getNodeName()); 141 } 142 143 if (parentSchema != null) { 144 int severity = CompilerFlags.getFlag(fProject, CompilerFlags.P_UNKNOWN_ELEMENT); 145 if (severity != CompilerFlags.IGNORE) { 146 HashSet allowedElements = new HashSet (); 147 computeAllowedElements(parentSchema.getType(), allowedElements); 148 if (!allowedElements.contains(elementName)) { 149 reportIllegalElement(element, severity); 150 return; 151 } 152 } 153 154 } 155 if (schemaElement == null && parentSchema != null) { 156 ISchemaAttribute attr = parentSchema.getAttribute(elementName); 157 if (attr != null && attr.getKind() == IMetaAttribute.JAVA) { 158 if (attr.isDeprecated()) 159 reportDeprecatedAttribute(element, element.getAttributeNode("class")); validateJavaAttribute(element, element.getAttributeNode("class")); } 162 } else { 163 if (schemaElement != null) { 164 validateRequiredExtensionAttributes(element, schemaElement); 165 validateExistingExtensionAttributes(element, element.getAttributes(), schemaElement); 166 if (schemaElement.isDeprecated()) 167 reportDeprecatedElement(element); 168 if (schemaElement.hasTranslatableContent()) 169 validateTranslatableElementContent(element); 170 } 171 NodeList children = element.getChildNodes(); 172 for (int i = 0; i < children.getLength(); i++) { 173 validateElement((Element)children.item(i), schema); 174 } 175 } 176 } 177 178 private void computeAllowedElements(ISchemaType type, HashSet elementSet) { 179 if (type instanceof ISchemaComplexType) { 180 ISchemaComplexType complexType = (ISchemaComplexType) type; 181 ISchemaCompositor compositor = complexType.getCompositor(); 182 if (compositor != null) 183 computeAllowedElements(compositor, elementSet); 184 185 ISchemaAttribute[] attrs = complexType.getAttributes(); 186 for (int i = 0; i < attrs.length; i++) { 187 if (attrs[i].getKind() == IMetaAttribute.JAVA) 188 elementSet.add(attrs[i].getName()); 189 } 190 } 191 } 192 193 private void computeAllowedElements(ISchemaCompositor compositor, 194 HashSet elementSet) { 195 ISchemaObject[] children = compositor.getChildren(); 196 for (int i = 0; i < children.length; i++) { 197 ISchemaObject child = children[i]; 198 if (child instanceof ISchemaObjectReference) { 199 ISchemaObjectReference ref = (ISchemaObjectReference) child; 200 ISchemaElement refElement = (ISchemaElement) ref 201 .getReferencedObject(); 202 if (refElement != null) 203 elementSet.add(refElement.getName()); 204 } else if (child instanceof ISchemaCompositor) { 205 computeAllowedElements((ISchemaCompositor) child, elementSet); 206 } 207 } 208 } 209 210 211 212 private void validateRequiredExtensionAttributes(Element element, ISchemaElement schemaElement) { 213 int severity = CompilerFlags.getFlag(fProject, CompilerFlags.P_NO_REQUIRED_ATT); 214 if (severity == CompilerFlags.IGNORE) 215 return; 216 217 ISchemaAttribute[] attInfos = schemaElement.getAttributes(); 218 for (int i = 0; i < attInfos.length; i++) { 219 ISchemaAttribute attInfo = attInfos[i]; 220 if (attInfo.getUse() == ISchemaAttribute.REQUIRED) { 221 boolean found = element.getAttributeNode(attInfo.getName()) != null; 222 if (!found && attInfo.getKind() == IMetaAttribute.JAVA) { 223 NodeList children = element.getChildNodes(); 224 for (int j = 0; j < children.getLength(); j++) { 225 if (attInfo.getName().equals(children.item(j).getNodeName())) { 226 found = true; 227 break; 228 } 229 } 230 } 231 if (!found) { 232 reportMissingRequiredAttribute(element, attInfo.getName(), severity); 233 } 234 } 235 } 236 } 237 238 private void validateExistingExtensionAttributes(Element element, NamedNodeMap attrs, 239 ISchemaElement schemaElement) { 240 for (int i = 0; i < attrs.getLength(); i++) { 241 Attr attr = (Attr )attrs.item(i); 242 ISchemaAttribute attInfo = schemaElement.getAttribute(attr.getName()); 243 if (attInfo == null) { 244 HashSet allowedElements = new HashSet (); 245 computeAllowedElements(schemaElement.getType(), allowedElements); 246 if (allowedElements.contains(attr.getName())) { 247 validateJavaAttribute(element, attr); 248 } else { 249 int flag = CompilerFlags.getFlag(fProject, CompilerFlags.P_UNKNOWN_ATTRIBUTE); 250 if (flag != CompilerFlags.IGNORE) 251 reportUnknownAttribute(element, attr.getName(), flag); 252 } 253 } else { 254 validateExtensionAttribute(element, attr, attInfo); 255 } 256 } 257 } 258 259 private void validateExtensionAttribute(Element element, Attr attr, ISchemaAttribute attInfo) { 260 ISchemaSimpleType type = attInfo.getType(); 261 ISchemaRestriction restriction = type.getRestriction(); 262 if (restriction != null) { 263 validateRestrictionAttribute(element, attr, restriction); 264 } 265 266 int kind = attInfo.getKind(); 267 if (kind == IMetaAttribute.JAVA) { 268 validateJavaAttribute(element, attr); 269 } else if (kind == IMetaAttribute.RESOURCE) { 270 validateResourceAttribute(element, attr); 271 } else if (type.getName().equals("boolean")) { validateBoolean(element, attr); 273 } 274 275 validateTranslatableString(element, attr, attInfo.isTranslatable()); 276 277 if (attInfo.isDeprecated()) { 278 reportDeprecatedAttribute(element, attr); 279 } 280 } 281 282 protected void validateExtensionPoint(Element element) { 283 if (assertAttributeDefined(element, "id", CompilerFlags.ERROR)) { Attr idAttr = element.getAttributeNode("id"); if (!IdUtil.isValidExtensionPointId(idAttr.getValue())) { 286 String message = NLS.bind(PDEMessages.Builders_Manifest_extensionPointId_value, idAttr.getValue()); 287 report(message, getLine(element, idAttr.getName()), CompilerFlags.WARNING); 288 } 289 } 290 291 assertAttributeDefined(element, "name", CompilerFlags.ERROR); 293 int severity = CompilerFlags.getFlag(fProject, CompilerFlags.P_UNKNOWN_ATTRIBUTE); 294 NamedNodeMap attrs = element.getAttributes(); 295 for (int i = 0; i < attrs.getLength(); i++) { 296 Attr attr = (Attr )attrs.item(i); 297 String name = attr.getName(); 298 if ("name".equals(name)) { validateTranslatableString(element, attr, true); 300 } else if (!"id".equals(name) && !"schema".equals(name) && severity != CompilerFlags.IGNORE) { reportUnknownAttribute(element, name, severity); 302 } 303 } 304 305 severity = CompilerFlags.getFlag(fProject, CompilerFlags.P_UNKNOWN_ELEMENT); 306 if (severity != CompilerFlags.IGNORE) { 307 NodeList children = element.getChildNodes(); 308 for (int i = 0; i < children.getLength(); i++) 309 reportIllegalElement((Element)children.item(i), severity); 310 } 311 } 312 313 protected void validateTranslatableString(Element element, Attr attr, boolean shouldTranslate) { 314 int severity = CompilerFlags.getFlag(fProject, CompilerFlags.P_NOT_EXTERNALIZED); 315 if (severity == CompilerFlags.IGNORE) 316 return; 317 String value = attr.getValue(); 318 if (shouldTranslate) { 319 if (!value.startsWith("%")) { report(NLS.bind(PDEMessages.Builders_Manifest_non_ext_attribute, attr.getName()), getLine(element, attr.getName()), severity); } else if (fModel != null && fModel instanceof AbstractModel) { 322 NLResourceHelper helper = ((AbstractModel)fModel).getNLResourceHelper(); 323 if (helper == null || !helper.resourceExists(value)) { 324 report(NLS.bind(PDEMessages.Builders_Manifest_key_not_found, value.substring(1)), getLine(element, attr.getName()), severity); } 326 } 327 } 328 } 329 330 protected void validateTranslatableElementContent(Element element) { 331 int severity = CompilerFlags.getFlag(fProject, CompilerFlags.P_NOT_EXTERNALIZED); 332 if (severity == CompilerFlags.IGNORE) 333 return; 334 String value = getTextContent(element); 335 if (value == null) 336 return; 337 if (!value.startsWith("%")) { report(NLS.bind(PDEMessages.Builders_Manifest_non_ext_element, element.getNodeName()), getLine(element), severity); } else if (fModel != null && fModel instanceof AbstractModel) { 340 NLResourceHelper helper = ((AbstractModel)fModel).getNLResourceHelper(); 341 if (helper == null || !helper.resourceExists(value)) { 342 report(NLS.bind(PDEMessages.Builders_Manifest_key_not_found, value.substring(1)), getLine(element), severity); } 344 } 345 } 346 347 protected void validateResourceAttribute(Element element, Attr attr) { 348 int severity = CompilerFlags.getFlag(fProject, CompilerFlags.P_UNKNOWN_RESOURCE); 349 if (severity != CompilerFlags.IGNORE && !resourceExists(attr.getValue())) { 350 report(NLS.bind(PDEMessages.Builders_Manifest_resource, (new String [] { attr.getValue(), attr.getName() })), getLine(element, 352 attr.getName()), 353 severity); 354 } 355 } 356 357 private boolean resourceExists(String location) { 358 String bundleJar=null; 359 IPath path = new Path(location); 360 if ("platform:".equals(path.getDevice()) && path.segmentCount() > 2) { if ("plugin".equals(path.segment(0))) { String id = path.segment(1); 363 IPluginModelBase model = PDECore.getDefault().getModelManager().findModel(id); 364 if (model != null && model.isEnabled()) { 365 path = path.setDevice(null).removeFirstSegments(2); 366 String bundleLocation = model.getInstallLocation(); 367 if(bundleLocation.endsWith(".jar")){ bundleJar=bundleLocation; 369 } else { 370 path = new Path(model.getInstallLocation()).append(path); 371 } 372 location = path.toString(); 373 } 374 } 375 } else if (path.getDevice()==null && path.segmentCount() > 3 && "platform:".equals(path.segment(0))){ if ("plugin".equals(path.segment(1))) { String id = path.segment(2); 378 IPluginModelBase model = PDECore.getDefault().getModelManager().findModel(id); 379 if (model != null && model.isEnabled()) { 380 path = path.removeFirstSegments(3); 381 String bundleLocation = model.getInstallLocation(); 382 if(bundleLocation.endsWith(".jar")){ bundleJar=bundleLocation; 384 } else { 385 path = new Path(model.getInstallLocation()).append(path); 386 } 387 location = path.toString(); 388 } 389 } 390 } 391 392 ArrayList paths = new ArrayList (); 393 if (location.indexOf("$nl$") != -1) { StringTokenizer tokenizer = new StringTokenizer (TargetPlatform.getNL(), "_"); String language = tokenizer.hasMoreTokens() ? tokenizer.nextToken() : null; 396 String country = tokenizer.hasMoreTokens() ? tokenizer.nextToken() : null; 397 if (language != null && country != null) 398 paths.add(location 399 .replaceAll( 400 "\\$nl\\$", "nl" + IPath.SEPARATOR + language + IPath.SEPARATOR + country)); if (language != null) 402 paths.add(location.replaceAll( 403 "\\$nl\\$", "nl" + IPath.SEPARATOR + language)); paths.add(location.replaceAll("\\$nl\\$", "")); } else { 406 paths.add(location); 407 } 408 409 for (int i = 0; i < paths.size(); i++) { 410 if (bundleJar == null) { 411 IPath currPath = new Path(paths.get(i).toString()); 412 if (currPath.isAbsolute() && currPath.toFile().exists()) 413 return true; 414 if (fFile.getProject().findMember(currPath) != null) 415 return true; 416 } else { 417 if (CoreUtility.jarContainsResource(new File (bundleJar), paths.get(i).toString(), false)) 418 return true; 419 } 420 } 421 422 return false; 423 } 424 425 protected void validateJavaAttribute(Element element, Attr attr) { 426 int severity = CompilerFlags.getFlag(fProject, CompilerFlags.P_UNKNOWN_CLASS); 427 if (severity == CompilerFlags.IGNORE) 428 return; 429 430 String value = attr.getValue(); 431 IJavaProject javaProject = JavaCore.create(fFile.getProject()); 432 try { 433 int index = value.indexOf(":"); if (index != -1) 437 value = value.substring(0, index); 438 439 IType javaType = javaProject.findType(value); 440 if (javaType == null && value.indexOf('$') != -1) 441 javaType = javaProject.findType(value.replace('$', '.')); 442 443 if (javaType == null) { 444 report(NLS.bind(PDEMessages.Builders_Manifest_class, (new String [] { value, attr.getName() })), getLine( 445 element, attr.getName()), severity); 446 } 447 } catch (JavaModelException e) { 448 } 449 } 450 451 protected void validateRestrictionAttribute(Element element, Attr attr, ISchemaRestriction restriction) { 452 Object [] children = restriction.getChildren(); 453 String value = attr.getValue(); 454 for (int i = 0; i < children.length; i++) { 455 Object child = children[i]; 456 if (child instanceof ISchemaEnumeration) { 457 ISchemaEnumeration enumeration = (ISchemaEnumeration) child; 458 if (enumeration.getName().equals(value)) { 459 return; 460 } 461 } 462 } 463 reportIllegalAttributeValue(element, attr); 464 } 465 466 protected void reportUnusedAttribute(Element element, String attName, int severity) { 467 String message = NLS.bind(PDEMessages.Builders_Manifest_unused_attribute, attName); 468 report(message, getLine(element, attName), severity); 469 } 470 471 protected void reportUnusedElement(Element element, int severity) { 472 Node parent = element.getParentNode(); 473 report(NLS.bind(PDEMessages.Builders_Manifest_unused_element, (new String [] { element.getNodeName(), parent.getNodeName() })), 475 getLine(element), severity); 476 } 477 478 protected void reportDeprecatedElement(Element element) { 479 int severity = CompilerFlags.getFlag(fProject, CompilerFlags.P_DEPRECATED); 480 if (severity != CompilerFlags.IGNORE) { 481 report(NLS.bind(PDEMessages.Builders_Manifest_deprecated_element, element.getNodeName()), getLine(element), severity); 482 } 483 } 484 485 } 486 | Popular Tags |