1 17 package org.apache.ws.jaxme.generator; 18 19 import java.io.File ; 20 import java.io.IOException ; 21 import java.net.URL ; 22 import java.util.ArrayList ; 23 import java.util.Enumeration ; 24 import java.util.HashSet ; 25 import java.util.Iterator ; 26 import java.util.List ; 27 import java.util.Set ; 28 29 import org.apache.ws.jaxme.generator.impl.GeneratorImpl; 30 import org.apache.ws.jaxme.generator.sg.SGFactoryChain; 31 import org.apache.ws.jaxme.generator.sg.SchemaSG; 32 import org.apache.ws.jaxme.generator.sg.impl.JAXBSchemaReader; 33 import org.apache.ws.jaxme.generator.sg.impl.JaxMeSchemaReader; 34 import org.apache.ws.jaxme.js.JavaSource; 35 import org.apache.ws.jaxme.js.JavaSourceFactory; 36 import org.apache.ws.jaxme.js.TextFile; 37 import org.apache.ws.jaxme.logging.AntProjectLoggerFactory; 38 import org.apache.ws.jaxme.logging.LoggerAccess; 39 import org.apache.ws.jaxme.logging.LoggerFactory; 40 import org.apache.ws.jaxme.util.ClassLoader; 41 import org.apache.ws.jaxme.xs.parser.impl.LocSAXException; 42 import org.apache.tools.ant.BuildException; 43 import org.apache.tools.ant.DirectoryScanner; 44 import org.apache.tools.ant.Project; 45 import org.apache.tools.ant.Task; 46 import org.apache.tools.ant.types.Commandline; 47 import org.apache.tools.ant.types.FileSet; 48 import org.apache.tools.ant.types.Path; 49 import org.xml.sax.SAXParseException ; 50 51 52 254 public class XJCTask extends Task { 255 257 public static class Dtd { 258 private String targetNamespace; 259 261 public void setTargetNamespace(String pTargetNamespace) { 262 targetNamespace = pTargetNamespace; 263 } 264 266 public String getTargetNamespace() { 267 return targetNamespace; 268 } 269 } 270 271 public static class Property { 272 private String name; 273 private String value; 274 public void setName(String pName) { name = pName; } 275 public void setValue(String pValue) { value = pValue; } 276 public String getName() { return name; } 277 public String getValue() { return value; } 278 public void finish() { 279 if (name == null) { 280 throw new NullPointerException ("Missing attribute: 'name'"); 281 } 282 if (value == null) { 283 throw new NullPointerException ("Missing attribute: 'value'"); 284 } 285 } 286 } 287 288 public static class ClassType { 289 private String className; 290 public void setClassName(String pClassName) { 291 className = pClassName; 292 } 293 public String getClassName() { 294 return className; 295 } 296 public Object getInstance(Class pInstanceClass) { 297 if (className == null) { 298 throw new NullPointerException ("Missing attribute: 'class'"); 299 } 300 Class cl; 301 try { 302 cl = ClassLoader.getClass(className, pInstanceClass); 303 } catch (ClassNotFoundException e) { 304 throw new BuildException("Could not load class " + className, e); 305 } catch (IllegalArgumentException e) { 306 throw new BuildException(e); 307 } 308 309 try { 310 return cl.newInstance(); 311 } catch (Exception e) { 312 throw new BuildException("The class " + className + 313 " could not be instantiated: " + 314 e.getMessage(), e); 315 } 316 } 317 } 318 319 private File binding, schema, target; 320 private String packageName; 321 private boolean readOnly, extension, removeOldOutput, force, isValidating; 322 private boolean isSettingLoggerFactory = true; 323 private String stackSize; 324 private List bindings = new ArrayList (), schemas = new ArrayList (); 325 private List depends = new ArrayList (), produces = new ArrayList (); 326 private List sgFactoryChains = new ArrayList (); 327 private ClassType schemaReader; 328 private List properties = new ArrayList (); 329 private Dtd dtd; 330 331 337 public Property createProperty() { 338 Property property = new Property(); 339 properties.add(property); 340 return property; 341 } 342 343 349 public Property[] getProperties() { 350 return (Property[]) properties.toArray(new Property[properties.size()]); 351 } 352 353 359 public ClassType createSchemaReader() { 360 if (schemaReader != null) { 361 throw new BuildException("Only one SchemaReader may be configured"); 362 } 363 schemaReader = new ClassType(); 364 return schemaReader; 365 } 366 367 373 public SchemaReader getSchemaReader() { 374 if (schemaReader == null) { 375 if (isExtension()) { 376 return new JaxMeSchemaReader(); 377 } else { 378 return new JAXBSchemaReader(); 379 } 380 } else { 381 return (SchemaReader) schemaReader.getInstance(SchemaReader.class); 382 } 383 } 384 385 393 public ClassType createSGFactoryChain() { 394 ClassType result = new ClassType(); 395 sgFactoryChains.add(result); 396 return result; 397 } 398 399 404 public ClassType[] getSGFactoryChains() { 405 return (ClassType[]) sgFactoryChains.toArray(new ClassType[sgFactoryChains.size()]); 406 } 407 408 410 public String getDescription() { 411 return "A JaxMe generator task converting XML schemata into Java source files."; 412 } 413 414 416 public void setValidating(boolean pValidating) { 417 isValidating = pValidating; 418 } 419 420 422 public boolean isValidating() { 423 return isValidating; 424 } 425 426 427 432 public boolean isForce() { 433 return force; 434 } 435 436 441 public void setForce(boolean pForce) { 442 force = pForce; 443 } 444 445 449 public boolean isSettingLoggerFactory() { 450 return isSettingLoggerFactory; 451 } 452 453 457 public void setSettingLoggerFactory(boolean pIsSettingLoggerFactory) { 458 isSettingLoggerFactory = pIsSettingLoggerFactory; 459 } 460 461 463 public File getBinding() { 464 return binding; 465 } 466 467 469 public void setBinding(File pBinding) { 470 binding = pBinding; 471 } 472 473 476 public boolean isExtension() { 477 return extension; 478 } 479 480 483 public void setExtension(boolean pExtension) { 484 extension = pExtension; 485 } 486 487 490 public String getPackage() { 491 return packageName; 492 } 493 494 497 public void setPackage(String pPackageName) { 498 packageName = pPackageName; 499 } 500 501 503 public void setPackageName(String pPackageName) { 504 log("Warning: The 'packageName' attribute is updated to 'package', for compatibility reasons. Please update your build script.", Project.MSG_WARN); 505 setPackage(pPackageName); 506 } 507 508 510 public boolean isReadOnly() { 511 return readOnly; 512 } 513 514 516 public void setReadOnly(boolean pReadOnly) { 517 readOnly = pReadOnly; 518 } 519 520 526 public boolean isRemoveOldOutput() { 527 return removeOldOutput; 528 } 529 530 536 public void setRemoveOldOutput(boolean pRemoveOldOutput) { 537 removeOldOutput = pRemoveOldOutput; 538 } 539 540 542 public File getSchema() { 543 return schema; 544 } 545 546 548 public void setSchema(File pSchema) { 549 schema = pSchema; 550 } 551 552 560 public String getStackSize() { 561 return stackSize; 562 } 563 564 572 public void setStackSize(String pStackSize) { 573 stackSize = pStackSize; 574 log("The 'stackSize' attribute is ignored by the JaxMe ant task.", Project.MSG_WARN); 575 } 576 577 581 public File getTarget() { 582 return target; 583 } 584 585 589 public void setTarget(File pTarget) { 590 target = pTarget; 591 } 592 593 598 public void addSchema(FileSet pSchemas) { 599 if (getSchema() != null) { 600 throw new BuildException("The 'schema' attribute and the nested 'schema' element are mutually exclusive."); 601 } 602 schemas.add(pSchemas); 603 } 604 605 610 public FileSet[] getSchemas() { 611 return (FileSet[]) schemas.toArray(new FileSet[schemas.size()]); 612 } 613 614 618 public void addBinding(FileSet pBindings) { 619 if (getBinding() != null) { 620 throw new BuildException("The 'binding' attribute and the nested 'binding' element are mutually exclusive."); 621 } 622 bindings.add(pBindings); 623 } 624 625 629 public FileSet[] getBindings() { 630 return (FileSet[]) bindings.toArray(new FileSet[bindings.size()]); 631 } 632 633 637 public void addClasspath(Path pClasspath) { 638 log("The 'classpath' attribute is ignored by the JaxMe ant task.", Project.MSG_WARN); 639 } 640 641 657 public void addArg(Commandline.Argument pArg) { 658 log("The 'arg' attribute is ignored by the JaxMe ant task.", Project.MSG_WARN); 659 } 660 661 668 public void addDepends(FileSet pDepends) { 669 depends.add(pDepends); 670 } 671 672 679 public FileSet[] getDepends() { 680 return (FileSet[]) depends.toArray(new FileSet[depends.size()]); 681 } 682 683 687 public FileSet createProduces() { 688 FileSet result = new FileSet(); 689 produces.add(result); 690 return result; 691 } 692 693 697 public FileSet[] getProduces() { 698 return (FileSet[]) produces.toArray(new FileSet[produces.size()]); 699 } 700 701 703 public Dtd createDtd() { 704 if (dtd == null) { 705 dtd = new Dtd(); 706 return dtd; 707 } else { 708 throw new BuildException("Multiple nested 'dtd' elements are forbidden.", 709 getLocation()); 710 } 711 } 712 713 715 public Dtd getDtd() { 716 return dtd; 717 } 718 719 public void finish() { 720 if (getSchema() == null && getSchemas().length == 0) { 721 throw new BuildException("Either of the 'schema' attribute or the nested 'schema' elements must be given.", 722 getLocation()); 723 } 724 } 725 726 private File [] getFiles(FileSet[] pFileSets) { 727 List list = new ArrayList (); 728 for (int i = 0; i < pFileSets.length; i++) { 729 FileSet fileSet = pFileSets[i]; 730 DirectoryScanner scanner = fileSet.getDirectoryScanner(getProject()); 731 scanner.scan(); 732 String [] files = scanner.getIncludedFiles(); 733 for (int j = 0; j < files.length; j++) { 734 list.add(new File (fileSet.getDir(getProject()), files[j])); 735 } 736 } 737 return (File []) list.toArray(new File [list.size()]); 738 } 739 740 private File [] getSchemaFiles() { 741 if (getSchema() != null) { 742 return new File []{getSchema()}; 743 } else { 744 return getFiles(getSchemas()); 745 } 746 } 747 748 private File [] getBindingFiles() { 749 if (getBinding() != null) { 750 return new File []{getBinding()}; 751 } else { 752 return getFiles(getBindings()); 753 } 754 } 755 756 private File [] getDependsFiles() { 757 return getFiles(getDepends()); 758 } 759 760 public boolean isUpToDate(File [] pSchemaFiles, File [] pBindingFiles, File [] pDependsFiles, List pProducesList) { 761 FileSet[] myProduces = getProduces(); 762 if (myProduces.length == 0) { 763 log("No nested 'produces' elements, up-to-date check returns false", Project.MSG_VERBOSE); 764 return false; 765 } 766 767 boolean result = true; 768 long firstTarget = 0; 769 File firstTargetFile = null; 770 for (int i = 0; i < myProduces.length; i++) { 771 File dir = myProduces[i].getDir(getProject()); 772 if (dir == null) { 773 dir = getTarget(); 774 if (dir == null) { 775 dir = getProject().getBaseDir(); 776 } 777 myProduces[i].setDir(dir); 778 } 779 if (!dir.exists()) { 780 log("The directory specified by the nested 'produces' element #" + i + " does not exist, up-to-date check returns false", 781 Project.MSG_VERBOSE); 782 result = false; 783 continue; 784 } 785 DirectoryScanner scanner = myProduces[i].getDirectoryScanner(getProject()); 786 scanner.scan(); 787 String [] files = scanner.getIncludedFiles(); 788 if (files.length == 0) { 789 log("The fileset specified by the nested 'produces' element #" + i + " is empty, up-to-date check returns false", 790 Project.MSG_VERBOSE); 791 result = false; 792 } 793 for (int j = 0; j < files.length; j++) { 794 File f = new File (dir, files[j]).getAbsoluteFile(); 795 if (pProducesList != null) { 796 pProducesList.add(f); 797 } 798 long l = f.lastModified(); 799 if (l == -1) { 800 log("Unable to determine timestamp of target file " + f + ", up-to-date check returns false.", Project.MSG_VERBOSE); 801 result = false; 802 } 803 if (firstTargetFile == null || firstTarget > l) { 804 firstTargetFile = f; 805 firstTarget = l; 806 } 807 } 808 } 809 810 if (isForce()) { 811 log("Force option is set, up-to-date check returns false", Project.MSG_VERBOSE); 812 result = false; 813 } 814 815 if (!result) { 816 return false; 817 } 818 819 List sourceFiles = new ArrayList (); 820 for (int i = 0; i < pSchemaFiles.length; i++) { 821 sourceFiles.add(pSchemaFiles[i]); 822 } 823 for (int i = 0; i < pBindingFiles.length; i++) { 824 sourceFiles.add(pBindingFiles[i]); 825 } 826 for (int i = 0; i < pDependsFiles.length; i++) { 827 sourceFiles.add(pDependsFiles[i]); 828 } 829 830 long lastSource = 0; 831 File lastSourceFile = null; 832 for (Iterator iter = sourceFiles.iterator(); iter.hasNext(); ) { 833 File f = (File ) iter.next(); 834 long l = f.lastModified(); 835 if (l == -1) { 836 log("Unable to determine timestamp of source file " + f + ", up-to-date check returns false.", Project.MSG_VERBOSE); 837 result = false; 838 } 839 if (lastSourceFile == null || lastSource < l) { 840 lastSource = l; 841 lastSourceFile = f; 842 } 843 } 844 845 if (lastSourceFile == null) { 846 log("No source files found, up-to-date check returns false.", Project.MSG_VERBOSE); 847 return false; 848 } 849 850 if (!result) { 851 return false; 852 } 853 854 try { 855 URL url = Generator.class.getClassLoader().getResource(Generator.class.getName().replace('.', '/') + ".class"); 856 if (url != null) { 857 long l = url.openConnection().getLastModified(); 858 if (l != 0 && lastSource < l) { 859 log("Generator class is newer than any schema files, using Generator classes timestamp as schema timestamp.", Project.MSG_DEBUG); 860 lastSource = l; 861 } 862 } 863 } catch (IOException e) { 864 } 865 866 if (lastSource >= firstTarget) { 867 log("Source file " + lastSourceFile + " is more recent than target file " + firstTargetFile + ", up-to-date check returns false", Project.MSG_VERBOSE); 868 return false; 869 } 870 871 log("All target files are up-to-date.", Project.MSG_VERBOSE); 872 return true; 873 } 874 875 public class MyClassLoader extends java.lang.ClassLoader { 876 private java.lang.ClassLoader parent; 877 public java.lang.ClassLoader getMyParent() { 878 return parent; 879 } 880 public MyClassLoader(java.lang.ClassLoader pParent) { 881 super(XJCTask.this.getClass().getClassLoader()); 882 parent = pParent; 883 } 884 public Class findClass(String name) throws ClassNotFoundException { 885 return parent.loadClass(name); 886 } 887 public URL findResource(String resource) { 888 return parent.getResource(resource); 889 } 890 public Enumeration findResources(String resource) throws IOException { 891 return parent.getResources(resource); 892 } 893 } 894 895 public void stopLogging(LoggerFactory pFactory) { 896 if (pFactory != null) { 897 LoggerAccess.setLoggerFactory(pFactory); 898 } 899 } 900 901 public LoggerFactory initLogging() { 902 if (!isSettingLoggerFactory()) { 903 return null; 904 } 905 LoggerFactory loggerFactory = LoggerAccess.getLoggerFactory(); 906 if (!(loggerFactory instanceof AntProjectLoggerFactory)) { 907 loggerFactory = new AntProjectLoggerFactory(this); 908 LoggerAccess.setLoggerFactory(loggerFactory); 909 return loggerFactory; 910 } 911 return null; 912 } 913 914 public void execute() { 915 java.lang.ClassLoader parent = Thread.currentThread().getContextClassLoader(); 916 MyClassLoader cl = new MyClassLoader(parent == null ? getClass().getClassLoader() : parent); 917 LoggerFactory loggerFactory = initLogging(); 918 try { 919 Thread.currentThread().setContextClassLoader(cl); 920 921 File [] schemaFiles = getSchemaFiles(); 922 if (schemaFiles.length == 0) { 923 log("No schema files specified", Project.MSG_WARN); 924 return; 925 } 926 927 File [] bindingFiles = getBindingFiles(); 928 if (bindingFiles.length > 0) { 929 throw new BuildException("External schema bindings are still unsupported by JaxMe.", getLocation()); 930 } 931 932 File [] dependFiles = getDependsFiles(); 933 List producesFiles = isRemoveOldOutput() ? new ArrayList () : null; 934 if (isUpToDate(schemaFiles, bindingFiles, dependFiles, producesFiles)) { 935 return; 936 } 937 938 Set producesFilesSet = null; 939 if (producesFiles != null) { 940 producesFilesSet = new HashSet (); 941 for (Iterator iter = producesFiles.iterator(); iter.hasNext(); ) { 942 File f = ((File ) iter.next()); 943 producesFilesSet.add(f); 944 } 945 } 946 947 948 Generator generator = new GeneratorImpl(); 949 generator.setForcingOverwrite(isForce()); 950 generator.setSettingReadOnly(isReadOnly()); 951 generator.setValidating(isValidating()); 952 if (getPackage() != null) { 953 generator.setProperty("jaxme.package.name", getPackage()); 954 } 955 Dtd myDtd = getDtd(); 956 if (myDtd != null) { 957 generator.setProperty("jaxme.dtd.input", "true"); 958 if (myDtd.getTargetNamespace() != null) { 959 generator.setProperty("jaxme.dtd.targetNamespace", myDtd.getTargetNamespace()); 960 } 961 } 962 Property[] myProperties = getProperties(); 963 for (int i = 0; i < myProperties.length; i++) { 964 Property ot = myProperties[i]; 965 log("Option " + ot.getName() + "=" + ot.getValue(), Project.MSG_VERBOSE); 966 generator.setProperty(ot.getName(), ot.getValue()); 967 } 968 969 SchemaReader reader = getSchemaReader(); 970 if (reader instanceof JAXBSchemaReader) { 971 ((JAXBSchemaReader) reader).setSupportingExtensions(isExtension()); 972 } 973 generator.setSchemaReader(reader); 974 reader.setGenerator(generator); 975 generator.setTargetDirectory(getTarget()); 976 977 ClassType[] mySgFactoryChains = getSGFactoryChains(); 978 if (mySgFactoryChains.length > 0) { 979 if (!(reader instanceof JAXBSchemaReader)) { 980 throw new BuildException("The nested child element 'sgFactoryChain' is valid only, if the schema reader is an instance of " 981 + JAXBSchemaReader.class.getName(), getLocation()); 982 } 983 for (int i = 0; i < mySgFactoryChains.length; i++) { 984 ClassType ct = mySgFactoryChains[i]; 985 Class c; 986 try { 987 c = cl.loadClass(ct.getClassName()); 988 } catch (ClassNotFoundException e) { 989 throw new BuildException("Failed to load SGFactoryChain implementation class " + ct.getClassName(), 990 getLocation()); 991 } 992 if (!SGFactoryChain.class.isAssignableFrom(c)) { 993 throw new BuildException("The SGFactoryChain class " + c.getName() + 994 " is not implementing " + SGFactoryChain.class.getName(), 995 getLocation()); 996 } 997 reader.addSGFactoryChain(c); 998 } 999 } 1000 1001 for (int i = 0; i < schemaFiles.length; i++) { 1002 log("Reading schema file " + schemaFiles[i], Project.MSG_VERBOSE); 1003 try { 1004 SchemaSG schemaSG = generator.generate(schemaFiles[i]); 1005 if (producesFilesSet != null) { 1006 JavaSourceFactory jsf = schemaSG.getJavaSourceFactory(); 1007 File targetDirectory = getTarget(); 1008 for (Iterator iter = jsf.getJavaSources(); iter.hasNext(); ) { 1009 JavaSource js = (JavaSource) iter.next(); 1010 File f = jsf.getLocation(targetDirectory, js).getAbsoluteFile(); 1011 producesFilesSet.remove(f); 1012 } 1013 for (Iterator iter = jsf.getTextFiles(); iter.hasNext(); ) { 1014 TextFile tf = (TextFile) iter.next(); 1015 File f = jsf.getLocation(targetDirectory, tf).getAbsoluteFile(); 1016 producesFilesSet.remove(f); 1017 } 1018 } 1019 } catch (SAXParseException e) { 1020 String msg = LocSAXException.formatMsg(e.getMessage() == null ? e.getClass().getName() : e.getMessage(), 1021 e.getPublicId(), 1022 e.getSystemId(), 1023 e.getLineNumber(), 1024 e.getColumnNumber()); 1025 throw new BuildException(msg, e, getLocation()); 1026 } catch (Exception e) { 1027 String msg = e.getMessage(); 1028 if (msg == null) { 1029 msg = e.getClass().getName(); 1030 } 1031 throw new BuildException(schemaFiles[i] + ": " + msg, e, getLocation()); 1032 } 1033 } 1034 1035 if (producesFilesSet != null) { 1036 for (Iterator iter = producesFilesSet.iterator(); iter.hasNext(); ) { 1037 File f = (File ) iter.next(); 1038 log("Removing orphan file " + f, Project.MSG_VERBOSE); 1039 if (!f.delete()) { 1040 throw new BuildException("Unable to delete file " + f); 1041 } 1042 } 1043 } 1044 } finally { 1045 Thread.currentThread().setContextClassLoader(parent); 1046 stopLogging(loggerFactory); 1047 } 1048 } 1049} 1050 | Popular Tags |