1 package org.tigris.scarab.util.xmlissues; 2 3 48 49 import java.beans.BeanDescriptor ; 50 import java.io.BufferedInputStream ; 51 import java.io.File ; 52 import java.io.FileInputStream ; 53 import java.io.IOException ; 54 import java.io.InputStream ; 55 import java.io.Writer ; 56 import java.util.Collection ; 57 import java.util.Iterator ; 58 import java.util.Locale ; 59 60 import javax.xml.parsers.ParserConfigurationException ; 61 62 import org.apache.commons.betwixt.XMLIntrospector; 63 import org.apache.commons.betwixt.io.BeanReader; 64 import org.apache.commons.betwixt.io.BeanWriter; 65 import org.apache.commons.betwixt.strategy.HyphenatedNameMapper; 66 import org.apache.commons.betwixt.strategy.NameMapper; 67 import org.apache.commons.digester.Digester; 68 import org.apache.commons.digester.Rule; 69 import org.apache.commons.fileupload.FileItem; 70 import org.apache.commons.logging.Log; 71 import org.apache.commons.logging.LogFactory; 72 import org.apache.fulcrum.localization.Localization; 73 import org.tigris.scarab.om.Module; 74 import org.tigris.scarab.util.ScarabConstants; 75 import org.tigris.scarab.util.TurbineInitialization; 76 import org.tigris.scarab.workflow.WorkflowFactory; 77 import org.xml.sax.Attributes ; 78 import org.xml.sax.ErrorHandler ; 79 import org.xml.sax.InputSource ; 80 import org.xml.sax.SAXException ; 81 import org.xml.sax.SAXParseException ; 82 83 84 103 public class ImportIssues 104 implements ErrorHandler 105 { 106 private static final Log LOG = LogFactory.getLog(ImportIssues.class); 107 108 114 public static final String SYSTEM_DTD_URI = 115 "http://scarab.tigris.org/dtd/scarab-0.16.29.dtd"; 116 117 121 private static final String INTERNAL_DTD_URI = 122 "http://scarab.tigris.org/unbranded-source/browse/scarab/src/dtd/scarab.dtd?rev=1.49&content-type=text/plain"; 123 124 127 private static final String DTD_RESOURCE = "/org/tigris/scarab/scarab.dtd"; 128 129 132 private String trProps = "/WEB-INF/conf/TurbineResourcesTest.properties"; 133 134 137 private String configProps = "/WEB-INF/conf/xmlimport.properties"; 138 139 private File configDir = null; 140 private boolean sendEmail = false; 141 private File xmlFile = null; 142 143 153 private boolean allowFileAttachments; 154 155 158 private boolean validationMode; 159 160 164 private ImportErrors importErrors; 165 166 public ImportIssues() 167 { 168 this(false); 169 } 170 171 public ImportIssues(boolean allowFileAttachments) 172 { 173 this.allowFileAttachments = allowFileAttachments; 174 this.importErrors = new ImportErrors(); 175 } 176 177 183 private ScarabIssues si = null; 184 185 186 public boolean getSendEmail() 187 { 188 return this.sendEmail; 189 } 190 191 public void setSendEmail(boolean state) 192 { 193 this.sendEmail = state; 194 } 195 196 public File getXmlFile() 197 { 198 return this.xmlFile; 199 } 200 201 public void setXmlFile(File xmlFile) 202 { 203 this.xmlFile = xmlFile; 204 } 205 206 public File getConfigDir() 207 { 208 return this.configDir; 209 } 210 211 public void setConfigDir(File configDir) 212 { 213 this.configDir = configDir; 214 } 215 216 public String getConfigFile() 217 { 218 return this.configProps; 219 } 220 221 public void setConfigFile(String configProps) 222 { 223 this.configProps = configProps; 224 } 225 226 public String getTurbineResources() 227 { 228 return this.trProps; 229 } 230 231 public void setTurbineResources(String trProps) 232 { 233 this.trProps = trProps; 234 } 235 236 public void init() 237 throws Exception 238 { 239 TurbineInitialization.setTurbineResources(getTurbineResources()); 240 TurbineInitialization.setUp(getConfigDir().getAbsolutePath(), 241 getConfigFile()); 242 } 243 244 248 public void execute() 249 throws Exception 250 { 251 runImport(getXmlFile()); 252 } 253 254 265 public Collection runImport(File importFile) 266 throws Exception 267 { 268 return runImport(importFile, (Module) null); 269 } 270 271 284 public Collection runImport(File importFile, Module currentModule) 285 throws Exception 286 { 287 return runImport(importFile.getAbsolutePath(), importFile, 288 currentModule); 289 } 290 291 307 public Collection runImport(FileItem importFile) 308 throws Exception 309 { 310 return runImport(importFile, (Module) null); 311 } 312 313 331 public Collection runImport(FileItem importFile, Module currentModule) 332 throws Exception 333 { 334 return runImport(importFile.getName(), importFile, currentModule); 335 } 336 337 340 protected Collection runImport(String filePath, Object input, 341 Module currentModule) 342 throws Exception 343 { 344 String msg = "Importing issues from XML '" + filePath + '\''; 345 LOG.debug(msg); 346 try 347 { 348 WorkflowFactory.setForceUseDefault(true); 350 BeanReader reader = createScarabIssuesBeanReader(); 351 validate(filePath, inputStreamFor(input), reader, currentModule); 352 353 if (importErrors == null || importErrors.isEmpty()) 354 { 355 this.si = insert(filePath, inputStreamFor(input), reader); 357 } 358 } 359 catch (Exception e) 360 { 361 LOG.error(msg, e); 362 throw e; } 364 finally 365 { 366 WorkflowFactory.setForceUseDefault(false); 368 } 369 370 return importErrors; 371 } 372 373 382 private InputStream inputStreamFor(Object input) 383 throws IOException 384 { 385 if (input instanceof FileItem) 386 { 387 return ((FileItem) input).getInputStream(); 388 } 389 else if (input instanceof File ) 390 { 391 return new BufferedInputStream (new FileInputStream ((File ) input)); 392 } 393 else 394 { 395 throw new IllegalArgumentException (); } 397 } 398 399 415 protected void validate(String name, InputStream is, 416 BeanReader reader, Module currentModule) 417 throws Exception 418 { 419 setValidationMode(reader, true); 422 ScarabIssues si = null; 423 try 424 { 425 si = (ScarabIssues) reader.parse(is); 426 } 427 catch (SAXParseException e) 428 { 429 importErrors.add("XML parse error at line " + e.getLineNumber() + 433 " column " + e.getColumnNumber() + ": " + 434 e.getMessage()); 435 } 436 437 if (si != null) 439 { 440 validateContent(si, currentModule); 442 443 if (importErrors != null) 445 { 446 int nbrErrors = importErrors.size(); 447 LOG.error("Found " + nbrErrors + " error" + 448 (nbrErrors == 1 ? "" : "s") + " importing '" + 449 name + "':"); 450 for (Iterator itr = importErrors.iterator(); itr.hasNext(); ) 451 { 452 LOG.error(itr.next()); 453 } 454 } 455 } 456 } 457 458 463 private void validateContent(ScarabIssues si, Module currentModule) 464 throws Exception 465 { 466 if (currentModule != null) 467 { 468 XmlModule xmlModule = si.getModule(); 473 474 476 String xmlModuleName = xmlModule.getName(); 477 String curModuleName = currentModule.getRealName(); 478 if (!curModuleName.equals(xmlModuleName)) 479 { 480 Object [] args = { xmlModuleName, curModuleName }; 481 String error = Localization.format 482 (ScarabConstants.DEFAULT_BUNDLE_NAME, getLocale(), 483 "XMLAndCurrentModuleMismatch", args); 484 importErrors.add(error); 485 } 486 487 String xmlCode = xmlModule.getCode(); 488 if (xmlCode == null || 489 !currentModule.getCode().equals(xmlCode)) 490 { 491 Object [] args = { xmlCode, currentModule.getCode() }; 492 String error = Localization.format 493 (ScarabConstants.DEFAULT_BUNDLE_NAME, getLocale(), 494 "XMLAndCurrentCodeMismatch", args); 495 importErrors.add(error); 496 } 497 } 498 499 si.doValidateDependencies(); 500 si.doValidateUsers(); 501 } 502 503 516 protected ScarabIssues insert(String name, InputStream is, 517 BeanReader reader) 518 throws Exception 519 { 520 setValidationMode(reader, false); 521 ScarabIssues si = (ScarabIssues)reader.parse(is); 522 si.doHandleDependencies(); 523 LOG.debug("Successfully imported " + name + '!'); 524 return si; 525 } 526 527 536 private void setValidationMode(Digester reader, boolean state) 537 throws ParserConfigurationException , SAXException 538 { 539 this.validationMode = state; 540 541 543 reader.setValidating(state); 546 reader.setFeature("http://xml.org/sax/features/validation", state); 547 548 reader.setFeature("http://apache.org/xml/features/validation/dynamic", 551 state); 552 } 553 554 564 public ScarabIssues getScarabIssuesBeanReader() 565 { 566 return this.si; 567 } 568 569 574 protected BeanReader createScarabIssuesBeanReader() 575 throws Exception 576 { 577 BeanReader reader = new BeanReader() 578 { 579 public InputSource resolveEntity(String publicId, 580 String systemId) 581 throws SAXException 582 { 583 InputSource input = null; 584 if (publicId == null && systemId != null) 585 { 586 if (SYSTEM_DTD_URI.equalsIgnoreCase(systemId) || 588 INTERNAL_DTD_URI.equalsIgnoreCase(systemId)) 589 { 590 input = resolveDTDResource(); 592 593 if (input == null) 594 { 595 input = super.resolveEntity(publicId, 597 systemId); 598 } 599 } 600 } 601 return input; 602 } 603 604 610 private InputSource resolveDTDResource() 611 { 612 InputStream stream = 613 getClass().getResourceAsStream(DTD_RESOURCE); 614 if (stream != null) 615 { 616 LOG.debug("Located DTD in classpath using " + 617 "resource path '" + DTD_RESOURCE + '\''); 618 return new InputSource (stream); 619 } 620 else 621 { 622 LOG.debug("DTD resource '" + DTD_RESOURCE + "' not " + 623 "found in classpath"); 624 return null; 625 } 626 } 627 }; 628 629 reader.register(SYSTEM_DTD_URI, INTERNAL_DTD_URI); 632 reader.setFeature("http://apache.org/xml/features/allow-java-encodings", 634 true); 635 reader.setXMLIntrospector(createXMLIntrospector()); 636 reader.registerBeanClass(ScarabIssues.class); 637 NameMapper nm = reader.getXMLIntrospector().getNameMapper(); 638 reader.addRule(nm.mapTypeToElementName 639 (new BeanDescriptor (ScarabIssues.class).getName()), 640 new ScarabIssuesSetupRule()); 641 reader.setErrorHandler(this); 642 return reader; 643 } 644 645 protected XMLIntrospector createXMLIntrospector() 646 { 647 XMLIntrospector introspector = new XMLIntrospector(); 648 649 introspector.setAttributesForPrimitives(false); 651 652 655 introspector.setElementNameMapper(new HyphenatedNameMapper()); 657 658 return introspector; 659 } 660 661 664 class ScarabIssuesSetupRule extends Rule 665 { 666 public void begin(String namespace, String name, Attributes attributes) 667 { 668 ScarabIssues si = (ScarabIssues) getDigester().peek(); 669 si.allowFileAttachments(allowFileAttachments); 670 si.inValidationMode(validationMode); 671 si.importErrors = importErrors; 672 } 673 } 674 675 680 protected void write(Object bean, Writer out) 681 throws Exception 682 { 683 BeanWriter writer = new BeanWriter(out); 684 writer.setXMLIntrospector(createXMLIntrospector()); 685 writer.enablePrettyPrint(); 686 writer.setWriteIDs(false); 687 writer.write(bean); 688 } 689 690 private Locale getLocale() 691 { 692 return ScarabConstants.DEFAULT_LOCALE; 693 } 694 695 696 698 699 public void error(SAXParseException e) 700 throws SAXParseException 701 { 702 LOG.error("Parse Error at line " + e.getLineNumber() + 703 " column " + e.getColumnNumber() + ": " + e.getMessage(), e); 704 throw e; } 706 707 708 public void fatalError(SAXParseException e) 709 throws SAXParseException 710 { 711 LOG.error("Parse Fatal Error at line " + e.getLineNumber() + 712 " column " + e.getColumnNumber() + ": " + e.getMessage(), e); 713 throw e; } 715 716 717 public void warning(SAXParseException e) 718 { 719 LOG.debug("Parse Warning at line " + e.getLineNumber() + 722 " column " + e.getColumnNumber() + ": " + e.getMessage()); 723 } 724 } 725 | Popular Tags |