1 /*
2 * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package com.sun.tools.internal.xjc;
27
28 import java.io.BufferedReader;
29 import java.io.File;
30 import java.io.FileInputStream;
31 import java.io.IOException;
32 import java.io.InputStreamReader;
33 import java.io.PrintWriter;
34 import java.io.StringWriter;
35 import java.net.MalformedURLException;
36 import java.net.URL;
37 import java.net.URLClassLoader;
38 import java.security.AccessController;
39 import java.security.PrivilegedAction;
40 import java.text.SimpleDateFormat;
41 import java.util.ArrayList;
42 import java.util.Date;
43 import java.util.Enumeration;
44 import java.util.HashSet;
45 import java.util.List;
46 import java.util.ServiceLoader;
47 import java.util.Set;
48
49 import com.sun.codemodel.internal.CodeWriter;
50 import com.sun.codemodel.internal.JPackage;
51 import com.sun.codemodel.internal.JResourceFile;
52 import com.sun.codemodel.internal.writer.FileCodeWriter;
53 import com.sun.codemodel.internal.writer.PrologCodeWriter;
54 import com.sun.istack.internal.tools.DefaultAuthenticator;
55 import com.sun.org.apache.xml.internal.resolver.CatalogManager;
56 import com.sun.org.apache.xml.internal.resolver.tools.CatalogResolver;
57 import com.sun.tools.internal.xjc.api.ClassNameAllocator;
58 import com.sun.tools.internal.xjc.api.SpecVersion;
59 import com.sun.tools.internal.xjc.generator.bean.field.FieldRendererFactory;
60 import com.sun.tools.internal.xjc.model.Model;
61 import com.sun.tools.internal.xjc.reader.Util;
62 import com.sun.xml.internal.bind.api.impl.NameConverter;
63 import java.net.URI;
64 import java.net.URISyntaxException;
65 import java.nio.charset.Charset;
66 import java.nio.charset.IllegalCharsetNameException;
67 import java.util.Locale;
68 import java.util.logging.Level;
69 import java.util.logging.Logger;
70
71 import org.xml.sax.EntityResolver;
72 import org.xml.sax.InputSource;
73
74 /**
75 * Global options.
76 *
77 * <p>
78 * This class stores invocation configuration for XJC.
79 * The configuration in this class should be abstract enough so that
80 * it could be parsed from both command-line or Ant.
81 */
82 public class Options
83 {
84 /** If "-debug" is specified. */
85 public boolean debugMode;
86
87 /** If the "-verbose" option is specified. */
88 public boolean verbose;
89
90 /** If the "-quiet" option is specified. */
91 public boolean quiet;
92
247 /**
248 * This {@link FieldRendererFactory} determines how the fields are generated.
249 */
250 private FieldRendererFactory fieldRendererFactory = new FieldRendererFactory();
251 /**
252 * Used to detect if two {@link Plugin}s try to overwrite {@link #fieldRendererFactory}.
253 */
254 private Plugin fieldRendererFactoryOwner = null;
255
256 /**
257 * If this is non-null, we use this {@link NameConverter} over the one
258 * given in the schema/binding.
259 */
260 private NameConverter nameConverter = null;
261 /**
262 * Used to detect if two {@link Plugin}s try to overwrite {@link #nameConverter}.
263 */
264 private Plugin nameConverterOwner = null;
265
266 /**
267 * Gets the active {@link FieldRendererFactory} that shall be used to build {@link Model}.
268 *
269 * @return always non-null.
270 */
271 public FieldRendererFactory getFieldRendererFactory() {
272 return fieldRendererFactory;
273 }
274
275 /**
276 * Sets the {@link FieldRendererFactory}.
277 *
278 * <p>
279 * This method is for plugins to call to set a custom {@link FieldRendererFactory}.
280 *
281 * @param frf
282 * The {@link FieldRendererFactory} to be installed. Must not be null.
283 * @param owner
284 * Identifies the plugin that owns this {@link FieldRendererFactory}.
285 * When two {@link Plugin}s try to call this method, this allows XJC
286 * to report it as a user-friendly error message.
447
448 /**
449 * Recursively scan directories and add all ".xjb" files in it.
450 */
451 public void addBindFileRecursive( File dir ) {
452 addRecursive(dir,".xjb",bindFiles);
453 }
454
455 public final List<URL> classpaths = new ArrayList<URL>();
456 /**
457 * Gets a classLoader that can load classes specified via the
458 * -classpath option.
459 */
460 public ClassLoader getUserClassLoader( ClassLoader parent ) {
461 if (classpaths.isEmpty())
462 return parent;
463 return new URLClassLoader(
464 classpaths.toArray(new URL[classpaths.size()]),parent);
465 }
466
467
468 /**
469 * Parses an option {@code args[i]} and return
470 * the number of tokens consumed.
471 *
472 * @return
473 * 0 if the argument is not understood. Returning 0
474 * will let the caller report an error.
475 * @exception BadCommandLineException
476 * If the callee wants to provide a custom message for an error.
477 */
478 public int parseArgument( String[] args, int i ) throws BadCommandLineException {
479 if (args[i].equals("-classpath") || args[i].equals("-cp")) {
480 String a = requireArgument(args[i], args, ++i);
481 for (String p : a.split(File.pathSeparator)) {
482 File file = new File(p);
483 try {
484 classpaths.add(file.toURL());
485 } catch (MalformedURLException e) {
486 throw new BadCommandLineException(
492 if (args[i].equals("-d")) {
493 targetDir = new File(requireArgument("-d",args,++i));
494 if( !targetDir.exists() )
495 throw new BadCommandLineException(
496 Messages.format(Messages.NON_EXISTENT_DIR,targetDir));
497 return 2;
498 }
499 if (args[i].equals("-readOnly")) {
500 readOnly = true;
501 return 1;
502 }
503 if (args[i].equals("-p")) {
504 defaultPackage = requireArgument("-p",args,++i);
505 if(defaultPackage.length()==0) { // user specified default package
506 // there won't be any package to annotate, so disable them
507 // automatically as a usability feature
508 packageLevelAnnotations = false;
509 }
510 return 2;
511 }
512 if (args[i].equals("-debug")) {
513 debugMode = true;
514 verbose = true;
515 return 1;
516 }
517 if (args[i].equals("-nv")) {
518 strictCheck = false;
519 return 1;
520 }
521 if( args[i].equals("-npa")) {
522 packageLevelAnnotations = false;
523 return 1;
524 }
525 if( args[i].equals("-no-header")) {
526 noFileHeader = true;
527 return 1;
528 }
529 if (args[i].equals("-verbose")) {
530 verbose = true;
531 return 1;
607 if (args[i].equals("-httpproxy")) {
608 if (i == args.length - 1 || args[i + 1].startsWith("-")) {
609 throw new BadCommandLineException(
610 Messages.format(Messages.MISSING_PROXY));
611 }
612
613 parseProxy(args[++i]);
614 return 2;
615 }
616 if (args[i].equals("-host")) {
617 proxyHost = requireArgument("-host",args,++i);
618 return 2;
619 }
620 if (args[i].equals("-port")) {
621 proxyPort = requireArgument("-port",args,++i);
622 return 2;
623 }
624 if( args[i].equals("-catalog") ) {
625 // use Sun's "XML Entity and URI Resolvers" by Norman Walsh
626 // to resolve external entities.
627 // http://www.sun.com/xml/developers/resolver/
628
629 File catalogFile = new File(requireArgument("-catalog",args,++i));
630 try {
631 addCatalog(catalogFile);
632 } catch (IOException e) {
633 throw new BadCommandLineException(
634 Messages.format(Messages.FAILED_TO_PARSE,catalogFile,e.getMessage()),e);
635 }
636 return 2;
637 }
638 if( args[i].equals("-Xtest-class-name-allocator") ) {
639 classNameAllocator = new ClassNameAllocator() {
640 public String assignClassName(String packageName, String className) {
641 System.out.printf("assignClassName(%s,%s)\n",packageName,className);
642 return className+"_Type";
643 }
644 };
645 return 1;
646 }
647
718 throw new BadCommandLineException(Messages.format(Messages.ILLEGAL_PROXY,text));
719 }
720 }
721
722 /**
723 * Obtains an operand and reports an error if it's not there.
724 */
725 public String requireArgument(String optionName, String[] args, int i) throws BadCommandLineException {
726 if (i == args.length || args[i].startsWith("-")) {
727 throw new BadCommandLineException(
728 Messages.format(Messages.MISSING_OPERAND,optionName));
729 }
730 return args[i];
731 }
732
733 /**
734 * Parses a token to a file (or a set of files)
735 * and add them as {@link InputSource} to the specified list.
736 *
737 * @param suffix
738 * If the given token is a directory name, we do a recusive search
739 * and find all files that have the given suffix.
740 */
741 private void addFile(String name, List<InputSource> target, String suffix) throws BadCommandLineException {
742 Object src;
743 try {
744 src = Util.getFileOrURL(name);
745 } catch (IOException e) {
746 throw new BadCommandLineException(
747 Messages.format(Messages.NOT_A_FILE_NOR_URL,name));
748 }
749 if(src instanceof URL) {
750 target.add(absolutize(new InputSource(Util.escapeSpace(((URL)src).toExternalForm()))));
751 } else {
752 File fsrc = (File)src;
753 if(fsrc.isDirectory()) {
754 addRecursive(fsrc,suffix,target);
755 } else {
756 target.add(absolutize(fileToInputSource(fsrc)));
757 }
758 }
759 }
760
761 /**
762 * Adds a new catalog file.
763 */
764 public void addCatalog(File catalogFile) throws IOException {
765 if(entityResolver==null) {
766 final CatalogManager staticManager = CatalogManager.getStaticManager();
767 // hack to force initialization so catalog manager system properties take effect
768 staticManager.getVerbosity();
769 staticManager.setIgnoreMissingProperties(true);
770 entityResolver = new CatalogResolver(true);
771 }
772 ((CatalogResolver)entityResolver).getCatalog().parseCatalog(catalogFile.getPath());
773 }
774
775 /**
776 * Parses arguments and fill fields of this object.
777 *
778 * @exception BadCommandLineException
779 * thrown when there's a problem in the command-line arguments
780 */
781 public void parseArguments( String[] args ) throws BadCommandLineException {
782
783 for (int i = 0; i < args.length; i++) {
784 if(args[i].length()==0)
785 throw new BadCommandLineException();
786 if (args[i].charAt(0) == '-') {
787 int j = parseArgument(args,i);
788 if(j==0)
789 throw new BadCommandLineException(
790 Messages.format(Messages.UNRECOGNIZED_PARAMETER, args[i]));
791 i += (j-1);
792 } else {
793 if(args[i].endsWith(".jar"))
794 scanEpisodeFile(new File(args[i]));
|
1 /*
2 * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package com.sun.tools.internal.xjc;
27
28 import com.sun.codemodel.internal.CodeWriter;
29 import com.sun.codemodel.internal.JPackage;
30 import com.sun.codemodel.internal.JResourceFile;
31 import com.sun.codemodel.internal.writer.FileCodeWriter;
32 import com.sun.codemodel.internal.writer.PrologCodeWriter;
33 import com.sun.istack.internal.tools.DefaultAuthenticator;
34 import com.sun.tools.internal.xjc.api.ClassNameAllocator;
35 import com.sun.tools.internal.xjc.api.SpecVersion;
36 import com.sun.tools.internal.xjc.generator.bean.field.FieldRendererFactory;
37 import com.sun.tools.internal.xjc.model.Model;
38 import com.sun.tools.internal.xjc.reader.Util;
39 import com.sun.xml.internal.bind.api.impl.NameConverter;
40 import org.xml.sax.EntityResolver;
41 import org.xml.sax.InputSource;
42
43 import java.io.BufferedReader;
44 import java.io.File;
45 import java.io.FileInputStream;
46 import java.io.IOException;
47 import java.io.InputStreamReader;
48 import java.io.PrintWriter;
49 import java.io.StringWriter;
50 import java.net.MalformedURLException;
51 import java.net.URI;
52 import java.net.URISyntaxException;
53 import java.net.URL;
54 import java.net.URLClassLoader;
55 import java.nio.charset.Charset;
56 import java.nio.charset.IllegalCharsetNameException;
57 import java.security.AccessController;
58 import java.security.PrivilegedAction;
59 import java.text.SimpleDateFormat;
60 import java.util.ArrayList;
61 import java.util.Date;
62 import java.util.Enumeration;
63 import java.util.HashSet;
64 import java.util.List;
65 import java.util.Locale;
66 import java.util.ServiceLoader;
67 import java.util.Set;
68 import java.util.logging.Level;
69 import java.util.logging.Logger;
70
71 import javax.xml.catalog.CatalogFeatures;
72 import javax.xml.catalog.CatalogFeatures.Feature;
73 import javax.xml.catalog.CatalogManager;
74
75 /**
76 * Global options.
77 *
78 * <p>
79 * This class stores invocation configuration for XJC.
80 * The configuration in this class should be abstract enough so that
81 * it could be parsed from both command-line or Ant.
82 */
83 public class Options
84 {
85 /** If "-debug" is specified. */
86 public boolean debugMode;
87
88 /** If the "-verbose" option is specified. */
89 public boolean verbose;
90
91 /** If the "-quiet" option is specified. */
92 public boolean quiet;
93
248 /**
249 * This {@link FieldRendererFactory} determines how the fields are generated.
250 */
251 private FieldRendererFactory fieldRendererFactory = new FieldRendererFactory();
252 /**
253 * Used to detect if two {@link Plugin}s try to overwrite {@link #fieldRendererFactory}.
254 */
255 private Plugin fieldRendererFactoryOwner = null;
256
257 /**
258 * If this is non-null, we use this {@link NameConverter} over the one
259 * given in the schema/binding.
260 */
261 private NameConverter nameConverter = null;
262 /**
263 * Used to detect if two {@link Plugin}s try to overwrite {@link #nameConverter}.
264 */
265 private Plugin nameConverterOwner = null;
266
267 /**
268 * Java module name in {@code module-info.java}.
269 */
270 private String javaModule = null;
271
272 /**
273 * Gets the active {@link FieldRendererFactory} that shall be used to build {@link Model}.
274 *
275 * @return always non-null.
276 */
277 public FieldRendererFactory getFieldRendererFactory() {
278 return fieldRendererFactory;
279 }
280
281 /**
282 * Sets the {@link FieldRendererFactory}.
283 *
284 * <p>
285 * This method is for plugins to call to set a custom {@link FieldRendererFactory}.
286 *
287 * @param frf
288 * The {@link FieldRendererFactory} to be installed. Must not be null.
289 * @param owner
290 * Identifies the plugin that owns this {@link FieldRendererFactory}.
291 * When two {@link Plugin}s try to call this method, this allows XJC
292 * to report it as a user-friendly error message.
453
454 /**
455 * Recursively scan directories and add all ".xjb" files in it.
456 */
457 public void addBindFileRecursive( File dir ) {
458 addRecursive(dir,".xjb",bindFiles);
459 }
460
461 public final List<URL> classpaths = new ArrayList<URL>();
462 /**
463 * Gets a classLoader that can load classes specified via the
464 * -classpath option.
465 */
466 public ClassLoader getUserClassLoader( ClassLoader parent ) {
467 if (classpaths.isEmpty())
468 return parent;
469 return new URLClassLoader(
470 classpaths.toArray(new URL[classpaths.size()]),parent);
471 }
472
473 /**
474 * Gets Java module name option.
475 * @return Java module name option or {@code null} if this option was not set.
476 */
477 public String getModuleName() {
478 return javaModule;
479 }
480
481 /**
482 * Parses an option {@code args[i]} and return
483 * the number of tokens consumed.
484 *
485 * @return
486 * 0 if the argument is not understood. Returning 0
487 * will let the caller report an error.
488 * @exception BadCommandLineException
489 * If the callee wants to provide a custom message for an error.
490 */
491 public int parseArgument( String[] args, int i ) throws BadCommandLineException {
492 if (args[i].equals("-classpath") || args[i].equals("-cp")) {
493 String a = requireArgument(args[i], args, ++i);
494 for (String p : a.split(File.pathSeparator)) {
495 File file = new File(p);
496 try {
497 classpaths.add(file.toURL());
498 } catch (MalformedURLException e) {
499 throw new BadCommandLineException(
505 if (args[i].equals("-d")) {
506 targetDir = new File(requireArgument("-d",args,++i));
507 if( !targetDir.exists() )
508 throw new BadCommandLineException(
509 Messages.format(Messages.NON_EXISTENT_DIR,targetDir));
510 return 2;
511 }
512 if (args[i].equals("-readOnly")) {
513 readOnly = true;
514 return 1;
515 }
516 if (args[i].equals("-p")) {
517 defaultPackage = requireArgument("-p",args,++i);
518 if(defaultPackage.length()==0) { // user specified default package
519 // there won't be any package to annotate, so disable them
520 // automatically as a usability feature
521 packageLevelAnnotations = false;
522 }
523 return 2;
524 }
525 if (args[i].equals("-m")) {
526 javaModule = requireArgument("-m", args, ++i);
527 return 2;
528 }
529 if (args[i].equals("-debug")) {
530 debugMode = true;
531 verbose = true;
532 return 1;
533 }
534 if (args[i].equals("-nv")) {
535 strictCheck = false;
536 return 1;
537 }
538 if( args[i].equals("-npa")) {
539 packageLevelAnnotations = false;
540 return 1;
541 }
542 if( args[i].equals("-no-header")) {
543 noFileHeader = true;
544 return 1;
545 }
546 if (args[i].equals("-verbose")) {
547 verbose = true;
548 return 1;
624 if (args[i].equals("-httpproxy")) {
625 if (i == args.length - 1 || args[i + 1].startsWith("-")) {
626 throw new BadCommandLineException(
627 Messages.format(Messages.MISSING_PROXY));
628 }
629
630 parseProxy(args[++i]);
631 return 2;
632 }
633 if (args[i].equals("-host")) {
634 proxyHost = requireArgument("-host",args,++i);
635 return 2;
636 }
637 if (args[i].equals("-port")) {
638 proxyPort = requireArgument("-port",args,++i);
639 return 2;
640 }
641 if( args[i].equals("-catalog") ) {
642 // use Sun's "XML Entity and URI Resolvers" by Norman Walsh
643 // to resolve external entities.
644 // https://xerces.apache.org/xml-commons/components/resolver/resolver-article.html
645
646 File catalogFile = new File(requireArgument("-catalog",args,++i));
647 try {
648 addCatalog(catalogFile);
649 } catch (IOException e) {
650 throw new BadCommandLineException(
651 Messages.format(Messages.FAILED_TO_PARSE,catalogFile,e.getMessage()),e);
652 }
653 return 2;
654 }
655 if( args[i].equals("-Xtest-class-name-allocator") ) {
656 classNameAllocator = new ClassNameAllocator() {
657 public String assignClassName(String packageName, String className) {
658 System.out.printf("assignClassName(%s,%s)\n",packageName,className);
659 return className+"_Type";
660 }
661 };
662 return 1;
663 }
664
735 throw new BadCommandLineException(Messages.format(Messages.ILLEGAL_PROXY,text));
736 }
737 }
738
739 /**
740 * Obtains an operand and reports an error if it's not there.
741 */
742 public String requireArgument(String optionName, String[] args, int i) throws BadCommandLineException {
743 if (i == args.length || args[i].startsWith("-")) {
744 throw new BadCommandLineException(
745 Messages.format(Messages.MISSING_OPERAND,optionName));
746 }
747 return args[i];
748 }
749
750 /**
751 * Parses a token to a file (or a set of files)
752 * and add them as {@link InputSource} to the specified list.
753 *
754 * @param suffix
755 * If the given token is a directory name, we do a recursive search
756 * and find all files that have the given suffix.
757 */
758 private void addFile(String name, List<InputSource> target, String suffix) throws BadCommandLineException {
759 Object src;
760 try {
761 src = Util.getFileOrURL(name);
762 } catch (IOException e) {
763 throw new BadCommandLineException(
764 Messages.format(Messages.NOT_A_FILE_NOR_URL,name));
765 }
766 if(src instanceof URL) {
767 target.add(absolutize(new InputSource(Util.escapeSpace(((URL)src).toExternalForm()))));
768 } else {
769 File fsrc = (File)src;
770 if(fsrc.isDirectory()) {
771 addRecursive(fsrc,suffix,target);
772 } else {
773 target.add(absolutize(fileToInputSource(fsrc)));
774 }
775 }
776 }
777
778 /**
779 * Adds a new catalog file.
780 */
781 public void addCatalog(File catalogFile) throws IOException {
782 String newUrl = catalogFile.getPath();
783 if (!catalogUrls.contains(newUrl)) {
784 catalogUrls.add(newUrl);
785 }
786 try {
787 entityResolver = CatalogManager.catalogResolver(catalogFeatures,
788 catalogUrls.toArray(new String[0]));
789 } catch (Exception ex) {
790 entityResolver = null;
791 }
792 }
793
794 // Since javax.xml.catalog is unmodifiable we need to track catalog
795 // URLs added and create new catalog each time addCatalog is called
796 private final ArrayList<String> catalogUrls = new ArrayList<String>();
797
798 // Cache CatalogFeatures instance for future usages.
799 // Resolve feature is set to "continue" value for backward compatibility.
800 private static CatalogFeatures catalogFeatures = CatalogFeatures.builder()
801 .with(Feature.RESOLVE, "continue")
802 .build();
803 /**
804 * Parses arguments and fill fields of this object.
805 *
806 * @exception BadCommandLineException
807 * thrown when there's a problem in the command-line arguments
808 */
809 public void parseArguments( String[] args ) throws BadCommandLineException {
810
811 for (int i = 0; i < args.length; i++) {
812 if(args[i].length()==0)
813 throw new BadCommandLineException();
814 if (args[i].charAt(0) == '-') {
815 int j = parseArgument(args,i);
816 if(j==0)
817 throw new BadCommandLineException(
818 Messages.format(Messages.UNRECOGNIZED_PARAMETER, args[i]));
819 i += (j-1);
820 } else {
821 if(args[i].endsWith(".jar"))
822 scanEpisodeFile(new File(args[i]));
|