View Javadoc
1   /*
2    * Copyright (c) 1997, 2011, 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.util;
27  
28  import com.sun.codemodel.internal.ClassType;
29  import com.sun.codemodel.internal.JClassAlreadyExistsException;
30  import com.sun.codemodel.internal.JClassContainer;
31  import com.sun.codemodel.internal.JDefinedClass;
32  import com.sun.codemodel.internal.JJavaName;
33  import com.sun.codemodel.internal.JMod;
34  import com.sun.tools.internal.xjc.ErrorReceiver;
35  
36  import org.xml.sax.Locator;
37  import org.xml.sax.SAXParseException;
38  
39  /**
40   * Create new {@link JDefinedClass} and report class collision errors,
41   * if necessary.
42   *
43   * This is just a helper class that simplifies the class name collision
44   * detection. This object maintains no state, so it is OK to use
45   * multiple instances of this.
46   *
47   * @author
48   *     Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
49   */
50  public final class CodeModelClassFactory {
51  
52      /** errors are reported to this object. */
53      private ErrorReceiver errorReceiver;
54  
55      /** unique id generator. */
56      private int ticketMaster = 0;
57  
58  
59      public CodeModelClassFactory( ErrorReceiver _errorReceiver ) {
60          this.errorReceiver = _errorReceiver;
61      }
62  
63      public JDefinedClass createClass( JClassContainer parent, String name, Locator source ) {
64          return createClass( parent, JMod.PUBLIC, name, source );
65      }
66      public JDefinedClass createClass( JClassContainer parent, int mod, String name, Locator source ) {
67          return createClass(parent,mod,name,source,ClassType.CLASS);
68      }
69  
70      public JDefinedClass createInterface( JClassContainer parent, String name, Locator source ) {
71          return createInterface( parent, JMod.PUBLIC, name, source );
72      }
73      public JDefinedClass createInterface( JClassContainer parent, int mod, String name, Locator source ) {
74          return createClass(parent,mod,name,source,ClassType.INTERFACE);
75      }
76      public JDefinedClass createClass(
77          JClassContainer parent, String name, Locator source, ClassType kind ) {
78          return createClass(parent,JMod.PUBLIC,name,source,kind);
79      }
80      public JDefinedClass createClass(
81          JClassContainer parent, int mod, String name, Locator source, ClassType kind ) {
82  
83          if(!JJavaName.isJavaIdentifier(name)) {
84              // report the error
85              errorReceiver.error( new SAXParseException(
86                  Messages.format( Messages.ERR_INVALID_CLASSNAME, name ), source ));
87              return createDummyClass(parent);
88          }
89  
90  
91          try {
92              if(parent.isClass() && kind==ClassType.CLASS)
93                  mod |= JMod.STATIC;
94  
95              JDefinedClass r = parent._class(mod,name,kind);
96              // use the metadata field to store the source location,
97              // so that we can report class name collision errors.
98              r.metadata = source;
99  
100             return r;
101         } catch( JClassAlreadyExistsException e ) {
102             // class collision.
103             JDefinedClass cls = e.getExistingClass();
104 
105             // report the error
106             errorReceiver.error( new SAXParseException(
107                 Messages.format( Messages.ERR_CLASSNAME_COLLISION, cls.fullName() ),
108                 (Locator)cls.metadata ));
109             errorReceiver.error( new SAXParseException(
110                 Messages.format( Messages.ERR_CLASSNAME_COLLISION_SOURCE, name ),
111                 source ));
112 
113             if( !name.equals(cls.name()) ) {
114                 // on Windows, FooBar and Foobar causes name collision
115                 errorReceiver.error( new SAXParseException(
116                     Messages.format( Messages.ERR_CASE_SENSITIVITY_COLLISION,
117                         name, cls.name() ), null ) );
118             }
119 
120             if(Util.equals((Locator)cls.metadata,source)) {
121                 errorReceiver.error( new SAXParseException(
122                     Messages.format( Messages.ERR_CHAMELEON_SCHEMA_GONE_WILD ),
123                     source ));
124             }
125 
126             return createDummyClass(parent);
127         }
128     }
129 
130     /**
131      * Create a dummy class to recover from an error.
132      *
133      * We won't generate the code, so the client will never see this class
134      * getting generated.
135      */
136     private JDefinedClass createDummyClass(JClassContainer parent) {
137         try {
138             return parent._class("$$$garbage$$$"+(ticketMaster++));
139         } catch( JClassAlreadyExistsException ee ) {
140             return ee.getExistingClass();
141         }
142     }
143 }