feat(jdk8): move files to new folder to avoid resources compiled.

This commit is contained in:
2025-09-07 15:25:52 +08:00
parent 3f0047bf6f
commit 8c35cfb1c0
17415 changed files with 217 additions and 213 deletions

View File

@@ -0,0 +1,210 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader;
import java.util.Set;
import java.util.HashSet;
import com.sun.tools.internal.xjc.util.SubtreeCutter;
import com.sun.tools.internal.xjc.Options;
import com.sun.tools.internal.xjc.Plugin;
import com.sun.xml.internal.bind.v2.util.EditDistance;
import org.xml.sax.helpers.NamespaceSupport;
import org.xml.sax.Locator;
import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXParseException;
import org.xml.sax.SAXException;
import com.sun.xml.internal.bind.v2.WellKnownNamespace;
/**
* Common code between {@code DTDExtensionBindingChecker} and {@link ExtensionBindingChecker}.
*
* @author Kohsuke Kawaguchi
*/
public abstract class AbstractExtensionBindingChecker extends SubtreeCutter {
/** Remembers in-scope namespace bindings. */
protected final NamespaceSupport nsSupport = new NamespaceSupport();
/**
* Set of namespace URIs that designates enabled extensions.
*/
protected final Set<String> enabledExtensions = new HashSet<String>();
private final Set<String> recognizableExtensions = new HashSet<String>();
private Locator locator;
/**
* Namespace URI of the target schema language. Elements in this
* namespace are always allowed.
*/
protected final String schemaLanguage;
/**
* If false, any use of extensions is reported as an error.
*/
protected final boolean allowExtensions;
private final Options options;
/**
* @param handler
* This error handler will receive detected errors.
*/
public AbstractExtensionBindingChecker( String schemaLanguage, Options options, ErrorHandler handler ) {
this.schemaLanguage = schemaLanguage;
this.allowExtensions = options.compatibilityMode!=Options.STRICT;
this.options = options;
setErrorHandler(handler);
for (Plugin plugin : options.getAllPlugins())
recognizableExtensions.addAll(plugin.getCustomizationURIs());
recognizableExtensions.add(Const.XJC_EXTENSION_URI);
}
/**
* Verify that the given URI is indeed a valid extension namespace URI,
* and if so enable it.
* <p>
* This method does all the error handling.
*/
protected final void checkAndEnable(String uri) throws SAXException {
if( !isRecognizableExtension(uri) ) {
String nearest = EditDistance.findNearest(uri, recognizableExtensions);
// not the namespace URI we know of
error( Messages.ERR_UNSUPPORTED_EXTENSION.format(uri,nearest) );
} else
if( !isSupportedExtension(uri) ) {
// recognizable but not not supported, meaning
// the plug-in isn't enabled
// look for plug-in that handles this URI
Plugin owner = null;
for( Plugin p : options.getAllPlugins() ) {
if(p.getCustomizationURIs().contains(uri)) {
owner = p;
break;
}
}
if(owner!=null)
// we know the plug-in that supports this namespace, but it's not enabled
error( Messages.ERR_PLUGIN_NOT_ENABLED.format(owner.getOptionName(),uri));
else {
// this shouldn't happen, but be defensive...
error( Messages.ERR_UNSUPPORTED_EXTENSION.format(uri) );
}
}
// as an error recovery enable this namespace URI anyway.
enabledExtensions.add(uri);
}
/**
* If the tag name belongs to a plugin namespace-wise, check its local name
* to make sure it's correct.
*/
protected final void verifyTagName(String namespaceURI, String localName, String qName) throws SAXException {
if(options.pluginURIs.contains(namespaceURI)) {
// make sure that this is a valid tag name
boolean correct = false;
for( Plugin p : options.activePlugins ) {
if(p.isCustomizationTagName(namespaceURI,localName)) {
correct = true;
break;
}
}
if(!correct) {
error( Messages.ERR_ILLEGAL_CUSTOMIZATION_TAGNAME.format(qName) );
startCutting();
}
}
}
/**
* Checks if the given namespace URI is supported as the extension
* bindings.
*/
protected final boolean isSupportedExtension( String namespaceUri ) {
return namespaceUri.equals(Const.XJC_EXTENSION_URI) || options.pluginURIs.contains(namespaceUri);
}
/**
* Checks if the given namespace URI can be potentially recognized
* by this XJC.
*/
protected final boolean isRecognizableExtension( String namespaceUri ) {
return recognizableExtensions.contains(namespaceUri);
}
@Override
public void setDocumentLocator(Locator locator) {
super.setDocumentLocator(locator);
this.locator = locator;
}
@Override
public void startDocument() throws SAXException {
super.startDocument();
nsSupport.reset();
enabledExtensions.clear();
}
@Override
public void startPrefixMapping(String prefix, String uri) throws SAXException {
if (WellKnownNamespace.XML_NAMESPACE_URI.equals(uri)) return;
super.startPrefixMapping(prefix, uri); //xml prefix shall not be declared based on jdk api javado
nsSupport.pushContext();
nsSupport.declarePrefix(prefix,uri);
}
@Override
public void endPrefixMapping(String prefix) throws SAXException {
if ("xml".equals(prefix)) return; //xml prefix shall not be declared based on jdk api javadoc
super.endPrefixMapping(prefix);
nsSupport.popContext();
}
/**
* Reports an error and returns the created SAXParseException
*/
protected final SAXParseException error( String msg ) throws SAXException {
SAXParseException spe = new SAXParseException( msg, locator );
getErrorHandler().error(spe);
return spe;
}
/**
* Reports a warning.
*/
protected final void warning( String msg ) throws SAXException {
SAXParseException spe = new SAXParseException( msg, locator );
getErrorHandler().warning(spe);
}
}

View File

@@ -0,0 +1,65 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader;
import com.sun.xml.internal.bind.v2.WellKnownNamespace;
/**
* Useful constant values.
*
* @author
* Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
*/
public class Const {
/** XML namespace URI. */
public final static String XMLNS_URI =
"http://www.w3.org/2000/xmlns/";
/** JAXB customization URI. */
public final static String JAXB_NSURI =
"http://java.sun.com/xml/ns/jaxb";
/** XJC vendor extension namespace URI. */
public final static String XJC_EXTENSION_URI =
"http://java.sun.com/xml/ns/jaxb/xjc";
/** RELAX NG namespace URI. */
public static final String RELAXNG_URI =
"http://relaxng.org/ns/structure/1.0";
/** URI to represent DTD. */
public static final String DTD = "DTD";
/**
* Attribute name of the expected media type.
*
* @see WellKnownNamespace#XML_MIME_URI
* @see http://www.w3.org/TR/xml-media-types/
*/
public static final String EXPECTED_CONTENT_TYPES = "expectedContentTypes";
}

View File

@@ -0,0 +1,137 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader;
import java.util.StringTokenizer;
import com.sun.tools.internal.xjc.Options;
import org.xml.sax.Attributes;
import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXException;
/**
* This filter checks jaxb:extensionBindingPrefix and
* pass/filter extension bindings.
*
* <p>
* This filter also remembers enabled extension namespaces
* and filters out any extension namespaces that doesn't belong
* to those. The net effect is that disabled customizations
* will never pass through this filter.
*
* <p>
* Note that we can't just filter out all foreign namespaces,
* as we need to use user-defined tags in documentations to generate javadoc.
*
* <p>
* The class needs to know the list of extension binding namespaces
* that the RI recognizes.
* To add new URI, modify the isSupportedExtension method.
*
* @author
* Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
*/
public final class ExtensionBindingChecker extends AbstractExtensionBindingChecker {
/**
* Number of the elements encountered. Used to detect the root element.
*/
private int count=0;
public ExtensionBindingChecker(String schemaLanguage, Options options, ErrorHandler handler) {
super(schemaLanguage, options, handler);
}
/**
* Returns true if the elements with the given namespace URI
* should be blocked by this filter.
*/
private boolean needsToBePruned( String uri ) {
if( uri.equals(schemaLanguage) )
return false;
if( uri.equals(Const.JAXB_NSURI) )
return false;
if( enabledExtensions.contains(uri) )
return false;
// we don't need to prune something unless
// the rest of the processor recognizes it as something special.
// this allows us to send the documentation and other harmless
// foreign XML fragments, which may be picked up as documents.
return isRecognizableExtension(uri);
}
@Override
public void startDocument() throws SAXException {
super.startDocument();
count=0;
}
@Override
public void startElement(String namespaceURI, String localName, String qName, Attributes atts)
throws SAXException {
if(!isCutting()) {
String v = atts.getValue(Const.JAXB_NSURI,"extensionBindingPrefixes");
if(v!=null) {
if(count!=0)
// the binding attribute is allowed only at the root level.
error( Messages.ERR_UNEXPECTED_EXTENSION_BINDING_PREFIXES.format() );
if(!allowExtensions)
error( Messages.ERR_VENDOR_EXTENSION_DISALLOWED_IN_STRICT_MODE.format() );
// then remember the associated namespace URIs.
StringTokenizer tokens = new StringTokenizer(v);
while(tokens.hasMoreTokens()) {
String prefix = tokens.nextToken();
String uri = nsSupport.getURI(prefix);
if( uri==null )
// undeclared prefix
error( Messages.ERR_UNDECLARED_PREFIX.format(prefix) );
else
checkAndEnable(uri);
}
}
if( needsToBePruned(namespaceURI) ) {
// start pruning the tree. Call the super class method directly.
if( isRecognizableExtension(namespaceURI) ) {
// but this is a supported customization.
// isn't the user forgetting @jaxb:extensionBindingPrefixes?
warning( Messages.ERR_SUPPORTED_EXTENSION_IGNORED.format(namespaceURI) );
}
startCutting();
} else
verifyTagName(namespaceURI, localName, qName);
}
count++;
super.startElement(namespaceURI, localName, qName, atts);
}
}

View File

@@ -0,0 +1,59 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader;
import java.text.MessageFormat;
import java.util.ResourceBundle;
/**
* Formats error messages.
*/
public enum Messages {
DUPLICATE_PROPERTY, // 1 arg
DUPLICATE_ELEMENT, // 1 arg
ERR_UNDECLARED_PREFIX,
ERR_UNEXPECTED_EXTENSION_BINDING_PREFIXES,
ERR_UNSUPPORTED_EXTENSION,
ERR_SUPPORTED_EXTENSION_IGNORED,
ERR_RELEVANT_LOCATION,
ERR_CLASS_NOT_FOUND,
PROPERTY_CLASS_IS_RESERVED,
ERR_VENDOR_EXTENSION_DISALLOWED_IN_STRICT_MODE,
ERR_ILLEGAL_CUSTOMIZATION_TAGNAME, // 1 arg
ERR_PLUGIN_NOT_ENABLED, // 2 args
;
private static final ResourceBundle rb = ResourceBundle.getBundle(Messages.class.getPackage().getName() +".MessageBundle");
public String toString() {
return format();
}
public String format( Object... args ) {
return MessageFormat.format( rb.getString(name()), args );
}
}

View File

@@ -0,0 +1,101 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader;
import java.util.List;
import java.util.Map;
import java.util.HashMap;
import javax.xml.namespace.QName;
import com.sun.tools.internal.xjc.ErrorReceiver;
import com.sun.tools.internal.xjc.model.CClassInfo;
import com.sun.tools.internal.xjc.model.CPropertyInfo;
import com.sun.tools.internal.xjc.model.Model;
/**
* Checks errors on model classes.
*
* <p>
* This should be used as a {@link Ring} component.
*
* @author Kohsuke Kawaguchi
*/
public final class ModelChecker {
private final Model model = Ring.get(Model.class);
private final ErrorReceiver errorReceiver = Ring.get(ErrorReceiver.class);
public ModelChecker() {
}
public void check() {
for( CClassInfo ci : model.beans().values() )
check(ci);
}
private void check( CClassInfo ci ) {
List<CPropertyInfo> props = ci.getProperties();
Map<QName,CPropertyInfo> collisionTable = new HashMap<QName,CPropertyInfo>();
OUTER:
for( int i=0; i<props.size(); i++ ) {
CPropertyInfo p1 = props.get(i);
if(p1.getName(true).equals("Class")) {
errorReceiver.error(p1.locator,Messages.PROPERTY_CLASS_IS_RESERVED.format());
continue;
}
QName n = p1.collectElementNames(collisionTable);
if(n!=null) {
CPropertyInfo p2 = collisionTable.get(n);
if (p2.getName(true).equals(n.toString()) || p2.getName(false).equals(n.toString())) {
errorReceiver.error(p1.locator, Messages.DUPLICATE_ELEMENT.format(n));
errorReceiver.error(p2.locator, Messages.ERR_RELEVANT_LOCATION.format());
}
}
for( int j=i+1; j<props.size(); j++ ) {
if(checkPropertyCollision(p1,props.get(j)))
continue OUTER;
}
for( CClassInfo c=ci.getBaseClass(); c!=null; c=c.getBaseClass() ) {
for( CPropertyInfo p2 : c.getProperties() )
if(checkPropertyCollision(p1,p2))
continue OUTER;
}
}
}
private boolean checkPropertyCollision(CPropertyInfo p1, CPropertyInfo p2) {
if(!p1.getName(true).equals(p2.getName(true)))
return false;
errorReceiver.error(p1.locator,Messages.DUPLICATE_PROPERTY.format(p1.getName(true)));
errorReceiver.error(p2.locator,Messages.ERR_RELEVANT_LOCATION.format());
return true;
}
}

View File

@@ -0,0 +1,227 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.activation.MimeType;
import com.sun.tools.internal.xjc.model.CElementPropertyInfo;
import static com.sun.tools.internal.xjc.model.CElementPropertyInfo.CollectionMode.*;
import com.sun.tools.internal.xjc.model.CReferencePropertyInfo;
import com.sun.tools.internal.xjc.model.CTypeRef;
import com.sun.tools.internal.xjc.model.Multiplicity;
import com.sun.tools.internal.xjc.model.nav.NType;
import com.sun.xml.internal.bind.v2.model.core.Element;
import com.sun.xml.internal.bind.v2.model.core.ID;
import java.math.BigInteger;
/**
* Set of {@link Ref}.
*
* @author Kohsuke Kawaguchi
*/
public final class RawTypeSet {
public final Set<Ref> refs;
/**
* True if this type set can form references to types.
*/
public final Mode canBeTypeRefs;
/**
* The occurence of the whole references.
*/
public final Multiplicity mul;
// computed inside canBeTypeRefs()
private CElementPropertyInfo.CollectionMode collectionMode;
/**
* Should be called from one of the raw type set builders.
*/
public RawTypeSet( Set<Ref> refs, Multiplicity m ) {
this.refs = refs;
mul = m;
canBeTypeRefs = canBeTypeRefs();
}
public CElementPropertyInfo.CollectionMode getCollectionMode() {
return collectionMode;
}
public boolean isRequired() {
return mul.min.compareTo(BigInteger.ZERO) == 1;
}
/**
* Represents the possible binding option for this {@link RawTypeSet}.
*/
public enum Mode {
/**
* This {@link RawTypeSet} can be either an reference property or
* an element property, and XJC recommends element property.
*/
SHOULD_BE_TYPEREF(0),
/**
* This {@link RawTypeSet} can be either an reference property or
* an element property, and XJC recommends reference property.
*/
CAN_BE_TYPEREF(1),
/**
* This {@link RawTypeSet} can be only bound to a reference property.
*/
MUST_BE_REFERENCE(2);
private final int rank;
Mode(int rank) {
this.rank = rank;
}
Mode or(Mode that) {
switch(Math.max(this.rank,that.rank)) {
case 0: return SHOULD_BE_TYPEREF;
case 1: return CAN_BE_TYPEREF;
case 2: return MUST_BE_REFERENCE;
}
throw new AssertionError();
}
}
/**
* Returns true if {@link #refs} can form refs of types.
*
* If there are multiple {@link Ref}s with the same type,
* we cannot make them into type refs. Or if any of the {@link Ref}
* says they cannot be in type refs, we cannot do that either.
*
* TODO: just checking if the refs are the same is not suffice.
* If two refs derive from each other, they cannot form a list of refs
* (because of a possible ambiguity).
*/
private Mode canBeTypeRefs() {
Set<NType> types = new HashSet<NType>();
collectionMode = mul.isAtMostOnce()?NOT_REPEATED:REPEATED_ELEMENT;
// the way we compute this is that we start from the most optimistic value,
// and then gradually degrade as we find something problematic.
Mode mode = Mode.SHOULD_BE_TYPEREF;
for( Ref r : refs ) {
mode = mode.or(r.canBeType(this));
if(mode== Mode.MUST_BE_REFERENCE)
return mode; // no need to continue the processing
if(!types.add(r.toTypeRef(null).getTarget().getType()))
return Mode.MUST_BE_REFERENCE; // collision
if(r.isListOfValues()) {
if(refs.size()>1 || !mul.isAtMostOnce())
return Mode.MUST_BE_REFERENCE; // restriction on @XmlList
collectionMode = REPEATED_VALUE;
}
}
return mode;
}
public void addTo(CElementPropertyInfo prop) {
assert canBeTypeRefs!= Mode.MUST_BE_REFERENCE;
if(mul.isZero())
return; // the property can't have any value
List<CTypeRef> dst = prop.getTypes();
for( Ref t : refs )
dst.add(t.toTypeRef(prop));
}
public void addTo(CReferencePropertyInfo prop) {
if(mul.isZero())
return; // the property can't have any value
for( Ref t : refs )
t.toElementRef(prop);
}
public ID id() {
for( Ref t : refs ) {
ID id = t.id();
if(id!=ID.NONE) return id;
}
return ID.NONE;
}
public MimeType getExpectedMimeType() {
for( Ref t : refs ) {
MimeType mt = t.getExpectedMimeType();
if(mt!=null) return mt;
}
return null;
}
/**
* A reference to something.
*
* <p>
* A {@link Ref} can be either turned into {@link CTypeRef} to form
* an element property, or {@link Element} to form a reference property.
*/
public static abstract class Ref {
/**
* @param ep
* the property to which the returned {@link CTypeRef} will be
* added to.
*/
protected abstract CTypeRef toTypeRef(CElementPropertyInfo ep);
protected abstract void toElementRef(CReferencePropertyInfo prop);
/**
* Can this {@link Ref} be a type ref?
* @return false to veto.
* @param parent
*/
protected abstract Mode canBeType(RawTypeSet parent);
protected abstract boolean isListOfValues();
/**
* When this {@link RawTypeSet} binds to a {@link CElementPropertyInfo},
* this method is used to determine if the property is ID or not.
*/
protected abstract ID id();
/**
* When this {@link RawTypeSet} binds to a {@link CElementPropertyInfo},
* this method is used to determine if the property has an associated expected MIME type or not.
*/
protected MimeType getExpectedMimeType() { return null; }
}
}

View File

@@ -0,0 +1,134 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;
import com.sun.tools.internal.xjc.ErrorReceiver;
import com.sun.tools.internal.xjc.model.Model;
/**
* Holds all the binding related singleton components in a "ring",
* and let you access those components, creating them as necessary.
*
* <p>
* A {@link Ring} is local to a thread,
* and only one instanceof {@link Ring} can be active at any given time.
*
* Use {@link #begin()} and {@link #end(Ring)} to start/end a ring scope.
* Inside a scope, use {@link #get()} to obtain the instance.
*
* <p>
* When a {@link Model} is built by the reader, an active {@link Ring} scope
* is assumed.
*
*
* <h2>Components in Ring</h2>
* <p>
* Depending on the schema language we are dealing with, different
* components are in the model. But at least the following components
* are in the ring.
*
* <ul>
* <li>{@link ErrorReceiver}
* </ul>
*
* @author Kohsuke Kawaguchi
*/
public final class Ring {
private final Map<Class,Object> components = new HashMap<Class,Object>();
private static final ThreadLocal<Ring> instances = new ThreadLocal<Ring>();
private Ring() {}
public static <T> void add( Class<T> clazz, T instance ) {
assert !get().components.containsKey(clazz);
get().components.put(clazz,instance);
}
public static <T> void add( T o ) {
add((Class<T>)o.getClass(),o);
}
public static <T> T get( Class<T> key ) {
T t = (T)get().components.get(key);
if(t==null) {
try {
Constructor<T> c = key.getDeclaredConstructor();
c.setAccessible(true);
t = c.newInstance();
if(!get().components.containsKey(key))
// many components register themselves.
add(key,t);
} catch (InstantiationException e) {
throw new Error(e);
} catch (IllegalAccessException e) {
throw new Error(e);
} catch (NoSuchMethodException e) {
throw new Error(e);
} catch (InvocationTargetException e) {
throw new Error(e);
}
}
assert t!=null;
return t;
}
/**
* A {@link Ring} instance is associated with a thread.
*/
public static Ring get() {
return instances.get();
}
/**
* Starts a new scope.
*/
public static Ring begin() {
Ring r = null;
synchronized (instances) {
r = instances.get();
instances.set(new Ring());
}
return r;
}
/**
* Ends a scope.
*/
public static void end(Ring old) {
synchronized (instances) {
instances.remove();
instances.set(old);
}
}
}

View File

@@ -0,0 +1,266 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import com.sun.codemodel.internal.JClass;
import com.sun.codemodel.internal.JCodeModel;
import com.sun.codemodel.internal.JDefinedClass;
import com.sun.codemodel.internal.JType;
import com.sun.tools.internal.xjc.ErrorReceiver;
import org.xml.sax.Locator;
import org.xml.sax.SAXParseException;
/**
* Type-related utility methods.
*
* @author
* <a href="mailto:kohsuke.kawaguchi@sun.com">Kohsuke KAWAGUCHI</a>
*/
public class TypeUtil {
/**
* Computes the common base type of two types.
*
* @param types
* set of {@link JType} objects.
*/
public static JType getCommonBaseType( JCodeModel codeModel, Collection<? extends JType> types ) {
return getCommonBaseType( codeModel, types.toArray(new JType[types.size()]) );
}
/**
* Computes the common base type of types.
*
* TODO: this is a very interesting problem. Since one type has possibly
* multiple base types, it's not an easy problem.
* The current implementation is very naive.
*
* To make the result deterministic across differente JVMs, we have to
* use a Set whose ordering is deterministic.
*/
public static JType getCommonBaseType(JCodeModel codeModel, JType... t) {
// first, eliminate duplicates.
Set<JType> uniqueTypes = new TreeSet<JType>(typeComparator);
for (JType type : t)
uniqueTypes.add(type);
// if this yields only one type. return now.
// this is the only case where we can return a primitive type
// from this method
if (uniqueTypes.size() == 1)
return uniqueTypes.iterator().next();
// assertion failed. nullType can be used only under a very special circumstance
assert !uniqueTypes.isEmpty();
// the null type doesn't need to be taken into account.
uniqueTypes.remove(codeModel.NULL);
// box all the types and compute the intersection of all types
Set<JClass> s = null;
for (JType type : uniqueTypes) {
JClass cls = type.boxify();
if (s == null)
s = getAssignableTypes(cls);
else
s.retainAll(getAssignableTypes(cls));
}
// any JClass can be casted to Object, so make sure it's always there
s.add( codeModel.ref(Object.class));
// refine 's' by removing "lower" types.
// for example, if we have both java.lang.Object and
// java.io.InputStream, then we don't want to use java.lang.Object.
JClass[] raw = s.toArray(new JClass[s.size()]);
s.clear();
for (int i = 0; i < raw.length; i++) { // for each raw[i]
int j;
for (j = 0; j < raw.length; j++) { // see if raw[j] "includes" raw[i]
if (i == j)
continue;
if (raw[i].isAssignableFrom(raw[j]))
break; // raw[j] is derived from raw[i], hence j includes i.
}
if (j == raw.length)
// no other type inclueds raw[i]. remember this value.
s.add(raw[i]);
}
assert !s.isEmpty(); // since at least java.lang.Object has to be there
// we now pick the candidate for the return type
JClass result = pickOne(s);
// finally, sometimes this method is used to compute the base type of types like
// JAXBElement<A>, JAXBElement<B>, and JAXBElement<C>.
// for those inputs, at this point result=JAXBElement.
//
// here, we'll try to figure out the parameterization
// so that we can return JAXBElement<? extends D> instead of just "JAXBElement".
if(result.isParameterized())
return result;
// for each uniqueType we store the list of base type parameterization
List<List<JClass>> parameters = new ArrayList<List<JClass>>(uniqueTypes.size());
int paramLen = -1;
for (JType type : uniqueTypes) {
JClass cls = type.boxify();
JClass bp = cls.getBaseClass(result);
// if there's no parameterization in the base type,
// we won't do any better than <?>. Thus no point in trying to figure out the parameterization.
// just return the base type.
if(bp.equals(result))
return result;
assert bp.isParameterized();
List<JClass> tp = bp.getTypeParameters();
parameters.add(tp);
assert paramLen==-1 || paramLen==tp.size();
// since 'bp' always is a parameterized version of 'result', it should always
// have the same number of parameters.
paramLen = tp.size();
}
List<JClass> paramResult = new ArrayList<JClass>();
List<JClass> argList = new ArrayList<JClass>(parameters.size());
// for each type parameter compute the common base type
for( int i=0; i<paramLen; i++ ) {
argList.clear();
for (List<JClass> list : parameters)
argList.add(list.get(i));
// compute the lower bound.
JClass bound = (JClass)getCommonBaseType(codeModel,argList);
boolean allSame = true;
for (JClass a : argList)
allSame &= a.equals(bound);
if(!allSame)
bound = bound.wildcard();
paramResult.add(bound);
}
return result.narrow(paramResult);
}
private static JClass pickOne(Set<JClass> s) {
// we may have more than one candidates at this point.
// any user-defined generated types should have
// precedence over system-defined existing types.
//
// so try to return such a type if any.
for (JClass c : s)
if (c instanceof JDefinedClass)
return c;
// we can do more if we like. for example,
// we can avoid types in the RI runtime.
// but for now, just return the first one.
return s.iterator().next();
}
private static Set<JClass> getAssignableTypes( JClass t ) {
Set<JClass> r = new TreeSet<JClass>(typeComparator);
getAssignableTypes(t,r);
return r;
}
/**
* Returns the set of all classes/interfaces that a given type
* implements/extends, including itself.
*
* For example, if you pass java.io.FilterInputStream, then the returned
* set will contain java.lang.Object, java.lang.InputStream, and
* java.lang.FilterInputStream.
*/
private static void getAssignableTypes( JClass t, Set<JClass> s ) {
if(!s.add(t))
return;
// add its raw type
s.add(t.erasure());
// if this type is added for the first time,
// recursively process the super class.
JClass _super = t._extends();
if(_super!=null)
getAssignableTypes(_super,s);
// recursively process all implemented interfaces
Iterator<JClass> itr = t._implements();
while(itr.hasNext())
getAssignableTypes(itr.next(),s);
}
/**
* Obtains a {@link JType} object for the string representation
* of a type.
*/
public static JType getType( JCodeModel codeModel,
String typeName, ErrorReceiver errorHandler, Locator errorSource ) {
try {
return codeModel.parseType(typeName);
} catch( ClassNotFoundException ee ) {
// make it a warning
errorHandler.warning( new SAXParseException(
Messages.ERR_CLASS_NOT_FOUND.format(typeName)
,errorSource));
// recover by assuming that it's a class that derives from Object
return codeModel.directClass(typeName);
}
}
/**
* Compares {@link JType} objects by their names.
*/
private static final Comparator<JType> typeComparator = new Comparator<JType>() {
public int compare(JType t1, JType t2) {
return t1.fullName().compareTo(t2.fullName());
}
};
}

View File

@@ -0,0 +1,80 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import org.xml.sax.InputSource;
public class Util
{
/**
* Parses the specified string either as an {@link URL} or as a {@link File}.
*
* @throws IOException
* if the parameter is neither.
*/
public static Object getFileOrURL(String fileOrURL) throws IOException {
try {
return new URL(fileOrURL);
} catch (MalformedURLException e) {
return new File(fileOrURL).getCanonicalFile();
}
}
/**
* Gets an InputSource from a string, which contains either
* a file name or an URL.
*/
public static InputSource getInputSource(String fileOrURL) {
try {
Object o = getFileOrURL(fileOrURL);
if(o instanceof URL) {
return new InputSource(escapeSpace(((URL)o).toExternalForm()));
} else {
String url = ((File)o).toURL().toExternalForm();
return new InputSource(escapeSpace(url));
}
} catch (IOException e) {
return new InputSource(fileOrURL);
}
}
public static String escapeSpace( String url ) {
// URLEncoder didn't work.
StringBuffer buf = new StringBuffer();
for (int i = 0; i < url.length(); i++) {
// TODO: not sure if this is the only character that needs to be escaped.
if (url.charAt(i) == ' ')
buf.append("%20");
else
buf.append(url.charAt(i));
}
return buf.toString();
}
}

View File

@@ -0,0 +1,50 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.dtd;
import java.util.LinkedHashSet;
import java.util.Set;
/**
* @author Kohsuke Kawaguchi
*/
final class Block {
final boolean isOptional;
final boolean isRepeated;
/**
* {@link Element}s that belong to this block.
* <p>
* We want to preserve the order they are added, but we don't want
* dupliates.
*/
final Set<Element> elements = new LinkedHashSet<Element>();
Block(boolean optional, boolean repeated) {
isOptional = optional;
isRepeated = repeated;
}
}

View File

@@ -0,0 +1,314 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.dtd;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.xml.namespace.QName;
import com.sun.tools.internal.xjc.model.CBuiltinLeafInfo;
import com.sun.tools.internal.xjc.model.CClassInfo;
import com.sun.tools.internal.xjc.model.CElementPropertyInfo;
import static com.sun.tools.internal.xjc.model.CElementPropertyInfo.CollectionMode.*;
import com.sun.tools.internal.xjc.model.CPropertyInfo;
import com.sun.tools.internal.xjc.model.CReferencePropertyInfo;
import com.sun.tools.internal.xjc.model.CTypeRef;
import com.sun.tools.internal.xjc.model.CValuePropertyInfo;
import com.sun.tools.internal.xjc.model.TypeUse;
import com.sun.tools.internal.xjc.reader.dtd.bindinfo.BIConversion;
import com.sun.tools.internal.xjc.reader.dtd.bindinfo.BIElement;
import com.sun.xml.internal.bind.v2.model.core.ID;
import com.sun.xml.internal.bind.v2.model.core.WildcardMode;
import com.sun.xml.internal.dtdparser.DTDEventListener;
import org.xml.sax.Locator;
/**
* DTD Element.
*
* <p>
* This class extends {@link Term} to participate in the content model tree.
*
* <p>
* This class is repsonsible for binding the element.
*
* @author Kohsuke Kawaguchi
*/
final class Element extends Term implements Comparable<Element> {
/**
* Name of the element.
*/
final String name;
private final TDTDReader owner;
/**
* @see DTDEventListener#endContentModel(String, short)
*/
private short contentModelType;
private Term contentModel;
/**
* True if this element is referenced from another element.
*/
boolean isReferenced;
/**
* If this element maps to a class, that class representation.
* Otherwise null.
*/
private CClassInfo classInfo;
/**
* True if {@link #classInfo} field is computed.
*/
private boolean classInfoComputed;
/**
* List of attribute properties on this element
*/
final List<CPropertyInfo> attributes = new ArrayList<CPropertyInfo>();
/**
* Normalized blocks of the content model.
*/
private final List<Block> normalizedBlocks = new ArrayList<Block>();
/**
* True if this element needs to be a class.
*
* Currently, if an element is referenced from a construct like (A|B|C),
* we require those A,B, and C to be a class.
*/
private boolean mustBeClass;
/**
* The source location where this element is defined.
*/
private Locator locator;
public Element(TDTDReader owner,String name) {
this.owner = owner;
this.name = name;
}
void normalize(List<Block> r, boolean optional) {
Block o = new Block(optional,false);
o.elements.add(this);
r.add(o);
}
void addAllElements(Block b) {
b.elements.add(this);
}
boolean isOptional() {
return false;
}
boolean isRepeated() {
return false;
}
/**
* Define its content model.
*/
void define(short contentModelType, Term contentModel, Locator locator) {
assert this.contentModel==null; // may not be called twice
this.contentModelType = contentModelType;
this.contentModel = contentModel;
this.locator = locator;
contentModel.normalize(normalizedBlocks,false);
for( Block b : normalizedBlocks ) {
if(b.isRepeated || b.elements.size()>1) {
for( Element e : b.elements ) {
owner.getOrCreateElement(e.name).mustBeClass = true;
}
}
}
}
/**
* When this element is an PCDATA-only content model,
* returns the conversion for it. Otherwise the behavior is undefined.
*/
private TypeUse getConversion() {
assert contentModel == Term.EMPTY; // this is PCDATA-only element
BIElement e = owner.bindInfo.element(name);
if(e!=null) {
BIConversion conv = e.getConversion();
if(conv!=null)
return conv.getTransducer();
}
return CBuiltinLeafInfo.STRING;
}
/**
* Return null if this class is not bound to a class.
*/
CClassInfo getClassInfo() {
if(!classInfoComputed) {
classInfoComputed = true;
classInfo = calcClass();
}
return classInfo;
}
private CClassInfo calcClass() {
BIElement e = owner.bindInfo.element(name);
if(e==null) {
if(contentModelType!=DTDEventListener.CONTENT_MODEL_MIXED
|| !attributes.isEmpty()
|| mustBeClass)
return createDefaultClass();
if(contentModel!=Term.EMPTY) {
throw new UnsupportedOperationException("mixed content model not supported");
} else {
// just #PCDATA
if(isReferenced)
return null;
else
// if no one else is referencing, assumed to be the root.
return createDefaultClass();
}
} else {
return e.clazz;
}
}
private CClassInfo createDefaultClass() {
String className = owner.model.getNameConverter().toClassName(name);
QName tagName = new QName("",name);
return new CClassInfo(owner.model,owner.getTargetPackage(),className,locator,null,tagName,null,null/*TODO*/);
}
void bind() {
CClassInfo ci = getClassInfo();
assert ci!=null || attributes.isEmpty();
for( CPropertyInfo p : attributes )
ci.addProperty(p);
switch(contentModelType) {
case DTDEventListener.CONTENT_MODEL_ANY:
CReferencePropertyInfo rp = new CReferencePropertyInfo("Content",true,false,true,null,null/*TODO*/,locator, false, false, false);
rp.setWildcard(WildcardMode.SKIP);
ci.addProperty(rp);
return;
case DTDEventListener.CONTENT_MODEL_CHILDREN:
break; // handling follows
case DTDEventListener.CONTENT_MODEL_MIXED:
if(contentModel!=Term.EMPTY)
throw new UnsupportedOperationException("mixed content model unsupported yet");
if(ci!=null) {
// if this element is mapped to a class, just put one property
CValuePropertyInfo p = new CValuePropertyInfo("value", null,null/*TODO*/,locator,getConversion(),null);
ci.addProperty(p);
}
return;
case DTDEventListener.CONTENT_MODEL_EMPTY:
// no content model
assert ci!=null;
return;
}
// normalize
List<Block> n = new ArrayList<Block>();
contentModel.normalize(n,false);
{// check collision among Blocks
Set<String> names = new HashSet<String>();
boolean collision = false;
OUTER:
for( Block b : n )
for( Element e : b.elements )
if(!names.add(e.name)) {
collision = true;
break OUTER;
}
if(collision) {
// collapse all blocks into one
Block all = new Block(true,true);
for( Block b : n )
all.elements.addAll(b.elements);
n.clear();
n.add(all);
}
}
for( Block b : n ) {
CElementPropertyInfo p;
if(b.isRepeated || b.elements.size()>1) {
// collection
StringBuilder name = new StringBuilder();
for( Element e : b.elements ) {
if(name.length()>0)
name.append("Or");
name.append(owner.model.getNameConverter().toPropertyName(e.name));
}
p = new CElementPropertyInfo(name.toString(), REPEATED_ELEMENT, ID.NONE, null, null,null/*TODO*/, locator, !b.isOptional );
for( Element e : b.elements ) {
CClassInfo child = owner.getOrCreateElement(e.name).getClassInfo();
assert child!=null; // we are requiring them to be classes.
p.getTypes().add(new CTypeRef(child,new QName("",e.name),null,false,null));
}
} else {
// single property
String name = b.elements.iterator().next().name;
String propName = owner.model.getNameConverter().toPropertyName(name);
TypeUse refType;
Element ref = owner.getOrCreateElement(name);
if(ref.getClassInfo()!=null)
refType = ref.getClassInfo();
else {
refType = ref.getConversion().getInfo();
}
p = new CElementPropertyInfo(propName,
refType.isCollection()?REPEATED_VALUE:NOT_REPEATED, ID.NONE, null, null,null/*TODO*/, locator, !b.isOptional );
p.getTypes().add(new CTypeRef(refType.getInfo(),new QName("",name),null,false,null));
}
ci.addProperty(p);
}
}
public int compareTo(Element that) {
return this.name.compareTo(that.name);
}
}

View File

@@ -0,0 +1,64 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.dtd;
import java.text.MessageFormat;
import java.util.ResourceBundle;
/**
* Formats error messages.
*/
class Messages
{
/** Loads a string resource and formats it with specified arguments. */
static String format( String property, Object... args ) {
String text = ResourceBundle.getBundle(Messages.class.getPackage().getName() + ".MessageBundle").getString(property);
return MessageFormat.format(text,args);
}
public static final String ERR_NO_ROOT_ELEMENT = // arg:0
"TDTDReader.NoRootElement";
public static final String ERR_UNDEFINED_ELEMENT_IN_BINDINFO = // arg:1
"TDTDReader.UndefinedElementInBindInfo";
public static final String ERR_CONVERSION_FOR_NON_VALUE_ELEMENT = // arg:1
"TDTDReader.ConversionForNonValueElement";
public static final String ERR_CONTENT_PROPERTY_PARTICLE_MISMATCH = // arg:1
"TDTDReader.ContentProperty.ParticleMismatch";
public static final String ERR_CONTENT_PROPERTY_DECLARATION_TOO_SHORT = // arg:1
"TDTDReader.ContentProperty.DeclarationTooShort";
public static final String ERR_BINDINFO_NON_EXISTENT_ELEMENT_DECLARATION = // arg:1
"TDTDReader.BindInfo.NonExistentElementDeclaration";
public static final String ERR_BINDINFO_NON_EXISTENT_INTERFACE_MEMBER = // arg:1
"TDTDReader.BindInfo.NonExistentInterfaceMember";
}

View File

@@ -0,0 +1,138 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.dtd;
import java.util.ArrayList;
import java.util.List;
import com.sun.xml.internal.dtdparser.DTDEventListener;
/**
* @author Kohsuke Kawaguchi
*/
final class ModelGroup extends Term {
enum Kind {
CHOICE, SEQUENCE
}
Kind kind;
private final List<Term> terms = new ArrayList<Term>();
void normalize(List<Block> r, boolean optional) {
switch(kind) {
case SEQUENCE:
for( Term t : terms )
t.normalize(r,optional);
return;
case CHOICE:
Block b = new Block(isOptional()||optional,isRepeated());
addAllElements(b);
r.add(b);
return;
}
}
void addAllElements(Block b) {
for( Term t : terms )
t.addAllElements(b);
}
boolean isOptional() {
switch(kind) {
case SEQUENCE:
for( Term t : terms )
if(!t.isOptional())
return false;
return true;
case CHOICE:
for( Term t : terms )
if(t.isOptional())
return true;
return false;
default:
throw new IllegalArgumentException();
}
}
boolean isRepeated() {
switch(kind) {
case SEQUENCE:
return true;
case CHOICE:
for( Term t : terms )
if(t.isRepeated())
return true;
return false;
default:
throw new IllegalArgumentException();
}
}
void setKind(short connectorType) {
Kind k;
switch(connectorType) {
case DTDEventListener.SEQUENCE:
k = Kind.SEQUENCE;
break;
case DTDEventListener.CHOICE:
k = Kind.CHOICE;
break;
default:
throw new IllegalArgumentException();
}
assert kind==null || k==kind;
kind = k;
}
void addTerm(Term t) {
if (t instanceof ModelGroup) {
ModelGroup mg = (ModelGroup) t;
if(mg.kind==this.kind) {
terms.addAll(mg.terms);
return;
}
}
terms.add(t);
}
Term wrapUp() {
switch(terms.size()) {
case 0:
return EMPTY;
case 1:
assert kind==null;
return terms.get(0);
default:
assert kind!=null;
return this;
}
}
}

View File

@@ -0,0 +1,83 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.dtd;
import java.util.List;
import com.sun.xml.internal.dtdparser.DTDEventListener;
/**
* @author Kohsuke Kawaguchi
*/
final class Occurence extends Term {
final Term term;
final boolean isOptional;
final boolean isRepeated;
Occurence(Term term, boolean optional, boolean repeated) {
this.term = term;
isOptional = optional;
isRepeated = repeated;
}
static Term wrap( Term t, int occurence ) {
switch(occurence) {
case DTDEventListener.OCCURENCE_ONCE:
return t;
case DTDEventListener.OCCURENCE_ONE_OR_MORE:
return new Occurence(t,false,true);
case DTDEventListener.OCCURENCE_ZERO_OR_MORE:
return new Occurence(t,true,true);
case DTDEventListener.OCCURENCE_ZERO_OR_ONE:
return new Occurence(t,true,false);
default:
throw new IllegalArgumentException();
}
}
void normalize(List<Block> r, boolean optional) {
if(isRepeated) {
Block b = new Block(isOptional||optional,true);
addAllElements(b);
r.add(b);
} else {
term.normalize(r,optional||isOptional);
}
}
void addAllElements(Block b) {
term.addAllElements(b);
}
boolean isOptional() {
return isOptional||term.isOptional();
}
boolean isRepeated() {
return isRepeated||term.isRepeated();
}
}

View File

@@ -0,0 +1,463 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.dtd;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Stack;
import javax.xml.namespace.QName;
import com.sun.codemodel.internal.JClass;
import com.sun.codemodel.internal.JCodeModel;
import com.sun.codemodel.internal.JDefinedClass;
import com.sun.codemodel.internal.JPackage;
import com.sun.tools.internal.xjc.AbortException;
import com.sun.tools.internal.xjc.ErrorReceiver;
import com.sun.tools.internal.xjc.Options;
import com.sun.tools.internal.xjc.model.CAttributePropertyInfo;
import com.sun.tools.internal.xjc.model.CBuiltinLeafInfo;
import com.sun.tools.internal.xjc.model.CClassInfo;
import com.sun.tools.internal.xjc.model.CPropertyInfo;
import com.sun.tools.internal.xjc.model.Model;
import com.sun.tools.internal.xjc.model.TypeUse;
import com.sun.tools.internal.xjc.model.TypeUseFactory;
import com.sun.tools.internal.xjc.model.CDefaultValue;
import com.sun.tools.internal.xjc.reader.ModelChecker;
import com.sun.tools.internal.xjc.reader.Ring;
import com.sun.tools.internal.xjc.reader.dtd.bindinfo.BIAttribute;
import com.sun.tools.internal.xjc.reader.dtd.bindinfo.BIElement;
import com.sun.tools.internal.xjc.reader.dtd.bindinfo.BIInterface;
import com.sun.tools.internal.xjc.reader.dtd.bindinfo.BindInfo;
import com.sun.tools.internal.xjc.util.CodeModelClassFactory;
import com.sun.tools.internal.xjc.util.ErrorReceiverFilter;
import com.sun.xml.internal.bind.api.impl.NameConverter;
import com.sun.xml.internal.dtdparser.DTDHandlerBase;
import com.sun.xml.internal.dtdparser.DTDParser;
import com.sun.xml.internal.dtdparser.InputEntity;
import com.sun.xml.internal.xsom.XmlString;
import com.sun.istack.internal.SAXParseException2;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.helpers.LocatorImpl;
/**
* Parses DTD grammar along with binding information into BGM.
*
* @author
* <a href="mailto:kohsuke.kawaguchi@sun.com">Kohsuke KAWAGUCHI</a>
*/
public class TDTDReader extends DTDHandlerBase
{
/**
* Parses DTD grammar and a binding information into BGM.
*
* <p>
* This method is just a utility method that covers 80% of the use
* cases.
*
* @param bindingInfo
* binding information file, if any. Can be null.
*/
public static Model parse(
InputSource dtd,
InputSource bindingInfo,
ErrorReceiver errorReceiver,
Options opts) {
try {
// set up a ring
final Ring old = Ring.begin();
try {
ErrorReceiverFilter ef = new ErrorReceiverFilter(errorReceiver);
JCodeModel cm = new JCodeModel();
Model model = new Model(opts,cm,NameConverter.standard,opts.classNameAllocator,null);
Ring.add(cm);
Ring.add(model);
Ring.add(ErrorReceiver.class,ef);
TDTDReader reader = new TDTDReader( ef, opts, bindingInfo);
DTDParser parser = new DTDParser();
parser.setDtdHandler(reader);
if( opts.entityResolver!=null )
parser.setEntityResolver(opts.entityResolver);
try {
parser.parse(dtd);
} catch (SAXParseException e) {
return null; // this error was already handled by GrammarReaderController
}
Ring.get(ModelChecker.class).check();
if(ef.hadError()) return null;
else return model;
} finally {
Ring.end(old);
}
} catch (IOException e) {
errorReceiver.error(new SAXParseException2(e.getMessage(),null,e));
return null;
} catch (SAXException e) {
errorReceiver.error(new SAXParseException2(e.getMessage(),null,e));
return null;
} catch (AbortException e) {
// parsing was aborted but the error was already reported
return null;
}
}
protected TDTDReader(ErrorReceiver errorReceiver, Options opts, InputSource _bindInfo)
throws AbortException {
this.entityResolver = opts.entityResolver;
this.errorReceiver = new ErrorReceiverFilter(errorReceiver);
bindInfo = new BindInfo(model,_bindInfo, this.errorReceiver);
classFactory = new CodeModelClassFactory(errorReceiver);
}
private final EntityResolver entityResolver;
/**
* binding information.
*
* <p>
* This is always non-null even if no binding information was specified.
* (In that case, a dummy object will be provided.)
*/
final BindInfo bindInfo;
final Model model = Ring.get(Model.class);
private final CodeModelClassFactory classFactory;
private final ErrorReceiverFilter errorReceiver;
/**
* Element name to its content model definition.
*/
private final Map<String,Element> elements = new HashMap<String,Element>();
public void startDTD(InputEntity entity) throws SAXException {
}
public void endDTD() throws SAXException {
// bind them all.
// we need to know how elements are referencing each other before we do this,
// so this can be only done at the endDTD method
for( Element e : elements.values() )
e.bind();
// if there was an error by now, just abort.
if (errorReceiver.hadError())
return;
processInterfaceDeclarations();
// check XJC extensions and realize them
model.serialVersionUID = bindInfo.getSerialVersionUID();
if(model.serialVersionUID!=null)
model.serializable=true;
model.rootClass = bindInfo.getSuperClass();
model.rootInterface = bindInfo.getSuperInterface();
// TODO: do we need to reimplement them?
// // performs annotation
// Annotator.annotate(model, this);
// FieldCollisionChecker.check( model, this );
processConstructorDeclarations();
}
/** Processes interface declarations. */
private void processInterfaceDeclarations() {
Map<String,InterfaceAcceptor> fromName = new HashMap<String,InterfaceAcceptor>();
// first, create empty InterfaceItem declaration for all interfaces
Map<BIInterface,JClass> decls = new HashMap<BIInterface,JClass>();
for( BIInterface decl : bindInfo.interfaces() ) {
final JDefinedClass intf = classFactory.createInterface(
bindInfo.getTargetPackage(), decl.name(), copyLocator() );
decls.put(decl,intf);
fromName.put(decl.name(),new InterfaceAcceptor() {
public void implement(JClass c) {
intf._implements(c);
}
});
}
for( final CClassInfo ci : model.beans().values() ) {
fromName.put(ci.getName(),new InterfaceAcceptor() {
public void implement(JClass c) {
ci._implements(c);
}
});
}
// traverse the interface declarations again
// and populate its expression according to the members attribute.
for( Map.Entry<BIInterface,JClass> e : decls.entrySet() ) {
BIInterface decl = e.getKey();
JClass c = e.getValue();
for (String member : decl.members()) {
InterfaceAcceptor acc = fromName.get(member);
if (acc == null) {
// there is no such class/interface
// TODO: error location
error(decl.getSourceLocation(),
Messages.ERR_BINDINFO_NON_EXISTENT_INTERFACE_MEMBER,
member);
continue;
}
acc.implement(c);
}
}
// TODO: check the cyclic interface definition
}
private static interface InterfaceAcceptor {
void implement( JClass c );
}
JPackage getTargetPackage() {
return bindInfo.getTargetPackage();
}
/**
* Creates constructor declarations as specified in the
* binding information.
*
* <p>
* Also checks that the binding file does not contain
* declarations for non-existent elements.
*/
private void processConstructorDeclarations() {
for( BIElement decl: bindInfo.elements() ) {
Element e = elements.get(decl.name());
if(e==null) {
error(decl.getSourceLocation(),
Messages.ERR_BINDINFO_NON_EXISTENT_ELEMENT_DECLARATION,decl.name());
continue; // continue to process next declaration
}
if(!decl.isClass())
// only element-class declaration has constructor definitions
continue;
decl.declareConstructors(e.getClassInfo());
}
}
public void attributeDecl(String elementName, String attributeName, String attributeType, String[] enumeration, short attributeUse, String defaultValue) throws SAXException {
getOrCreateElement(elementName).attributes.add(
createAttribute(elementName, attributeName, attributeType, enumeration, attributeUse, defaultValue)
);
}
protected CPropertyInfo createAttribute(
String elementName, String attributeName, String attributeType,
String[] enums, short attributeUse, String defaultValue )
throws SAXException {
boolean required = attributeUse==USE_REQUIRED;
// get the attribute-property declaration
BIElement edecl = bindInfo.element(elementName);
BIAttribute decl=null;
if(edecl!=null) decl=edecl.attribute(attributeName);
String propName;
if(decl==null) propName = model.getNameConverter().toPropertyName(attributeName);
else propName = decl.getPropertyName();
QName qname = new QName("",attributeName);
// if no declaration is specified, just wrap it by
// a FieldItem and let the normalizer handle its content.
TypeUse use;
if(decl!=null && decl.getConversion()!=null)
use = decl.getConversion().getTransducer();
else
use = builtinConversions.get(attributeType);
CPropertyInfo r = new CAttributePropertyInfo(
propName, null,null/*TODO*/, copyLocator(), qname, use, null, required );
if(defaultValue!=null)
r.defaultValue = CDefaultValue.create( use, new XmlString(defaultValue) );
return r;
}
Element getOrCreateElement( String elementName ) {
Element r = elements.get(elementName);
if(r==null) {
r = new Element(this,elementName);
elements.put(elementName,r);
}
return r;
}
public void startContentModel(String elementName, short contentModelType) throws SAXException {
assert modelGroups.isEmpty();
modelGroups.push(new ModelGroup());
}
public void endContentModel(String elementName, short contentModelType) throws SAXException {
assert modelGroups.size()==1;
Term term = modelGroups.pop().wrapUp();
Element e = getOrCreateElement(elementName);
e.define( contentModelType, term, copyLocator() );
}
private final Stack<ModelGroup> modelGroups = new Stack<ModelGroup>();
public void startModelGroup() throws SAXException {
modelGroups.push(new ModelGroup());
}
public void endModelGroup(short occurence) throws SAXException {
Term t = Occurence.wrap( modelGroups.pop().wrapUp(), occurence );
modelGroups.peek().addTerm(t);
}
public void connector(short connectorType) throws SAXException {
modelGroups.peek().setKind(connectorType);
}
// TODO: for now, we just ignore all the content model specification
// and treat it as (A,B,C,....)
public void childElement(String elementName, short occurence) throws SAXException {
Element child = getOrCreateElement(elementName);
modelGroups.peek().addTerm( Occurence.wrap( child, occurence ) );
child.isReferenced = true;
}
/**
* Mutable {@link Locator} instance that points to
* the current source line.
* <p>
* Use {@link #copyLocator()} to get a immutable clone.
*/
private Locator locator;
public void setDocumentLocator(Locator loc) {
this.locator = loc;
}
/**
* Creates a snapshot of the current {@link #locator} values.
*/
private Locator copyLocator(){
return new LocatorImpl(locator);
}
//
//
// builtin datatype handling
//
//
/** Transducers for the built-in types. Read-only. */
private static final Map<String,TypeUse> builtinConversions;
static {
// list of datatypes which have built-in conversions.
// note that although xs:token and xs:normalizedString are not
// specified in the spec, they need to be here because they
// have different whitespace normalization semantics.
Map<String,TypeUse> m = new HashMap<String,TypeUse>();
m.put("CDATA", CBuiltinLeafInfo.NORMALIZED_STRING);
m.put("ENTITY", CBuiltinLeafInfo.TOKEN);
m.put("ENTITIES", CBuiltinLeafInfo.STRING.makeCollection());
m.put("NMTOKEN", CBuiltinLeafInfo.TOKEN);
m.put("NMTOKENS", CBuiltinLeafInfo.STRING.makeCollection());
m.put("ID", CBuiltinLeafInfo.ID);
m.put("IDREF", CBuiltinLeafInfo.IDREF);
m.put("IDREFS", TypeUseFactory.makeCollection(CBuiltinLeafInfo.IDREF));
m.put("ENUMERATION",CBuiltinLeafInfo.TOKEN);
builtinConversions = Collections.unmodifiableMap(m);
}
//
//
// error related utility methods
//
//
public void error(SAXParseException e) throws SAXException {
errorReceiver.error(e);
}
public void fatalError(SAXParseException e) throws SAXException {
errorReceiver.fatalError(e);
}
public void warning(SAXParseException e) throws SAXException {
errorReceiver.warning(e);
}
protected final void error( Locator loc, String prop, Object... args ) {
errorReceiver.error(loc,Messages.format(prop,args));
}
}

View File

@@ -0,0 +1,62 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.dtd;
import java.util.List;
/**
* @author Kohsuke Kawaguchi
*/
abstract class Term {
abstract void normalize( List<Block> r, boolean optional );
abstract void addAllElements(Block b);
abstract boolean isOptional();
abstract boolean isRepeated();
/**
* Represents empty term.
* <p>
* This special term is only used to represent #PCDATA-only content model.
*/
static final Term EMPTY = new Term() {
void normalize(List<Block> r, boolean optional) {
}
void addAllElements(Block b) {
}
boolean isOptional() {
return false;
}
boolean isRepeated() {
return false;
}
};
}

View File

@@ -0,0 +1,107 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.dtd.bindinfo;
import java.util.ArrayList;
import com.sun.tools.internal.xjc.generator.bean.field.FieldRenderer;
import com.sun.tools.internal.xjc.generator.bean.field.FieldRendererFactory;
import org.w3c.dom.Attr;
import org.w3c.dom.Element;
/** &lt;attribute> declaration in the binding file. */
public class BIAttribute
{
/**
* Wraps a given &lt;attribute> element.
* <p>
* Should be created only from {@link BIElement}.
*/
BIAttribute( BIElement _parent, Element _e ) {
this.parent = _parent;
this.element = _e;
}
private final BIElement parent;
private final Element element;
/** Gets the name of this attribute-property declaration. */
public final String name() {
return element.getAttribute("name");
}
/**
* Gets the conversion method for this attribute, if any.
*
* @return
* If the convert attribute is not specified, this
* method returns null.
*/
public BIConversion getConversion() {
if (element.getAttributeNode("convert") == null)
return null;
String cnv = element.getAttribute("convert");
return parent.conversion(cnv);
}
/**
* Gets the realization of this particle, if any.
*
* @return
* null if the "collection" attribute was not specified.
*/
public final FieldRenderer getRealization() {
Attr a = element.getAttributeNode("collection");
if(a==null) return null;
String v = element.getAttribute("collection").trim();
FieldRendererFactory frf = parent.parent.model.options.getFieldRendererFactory();
if(v.equals("array")) return frf.getArray();
if(v.equals("list"))
return frf.getList(
parent.parent.codeModel.ref(ArrayList.class));
// the correctness of the attribute value must be
// checked by the validator.
throw new InternalError("unexpected collection value: "+v);
}
/**
* Gets the property name for this attribute.
*
* @return
* always a non-null, valid string.
*/
public final String getPropertyName() {
String r = DOMUtil.getAttribute(element,"property");
if(r!=null) return r;
else return name();
}
}

View File

@@ -0,0 +1,90 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.dtd.bindinfo;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
import com.sun.tools.internal.xjc.model.CClassInfo;
import org.w3c.dom.Element;
import org.xml.sax.Locator;
/**
* &lt;constructor> declaration in the binding file.
*
* <p>
* Since JAXB will generate both interfaces and implementations,
* A constructor declaration will create:
*
* <ul>
* <li> a method declaration in the factory interface
* <li> a method implementation in the factory implementation class
* <li> a constructor implementation in the actual implementation class
* </ul>
*/
public class BIConstructor
{
BIConstructor( Element _node ) {
this.dom = _node;
StringTokenizer tokens = new StringTokenizer(
DOMUtil.getAttribute(_node,"properties"));
List<String> vec = new ArrayList<String>();
while(tokens.hasMoreTokens())
vec.add(tokens.nextToken());
properties = vec.toArray(new String[0]);
if( properties.length==0 )
throw new AssertionError("this error should be catched by the validator");
}
/** &lt;constructor> element in the source binding file. */
private final Element dom;
/** properties specified by @properties. */
private final String[] properties;
/**
* Creates a constructor declaration into the ClassItem.
*
* @param cls
* ClassItem object that corresponds to the
* element declaration that contains this declaration.
*/
public void createDeclaration( CClassInfo cls ) {
cls.addConstructor(properties);
}
/** Gets the location where this declaration is declared. */
public Locator getSourceLocation() {
return DOMLocator.getLocationInfo(dom);
}
}

View File

@@ -0,0 +1,138 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.dtd.bindinfo;
import java.util.ArrayList;
import com.sun.codemodel.internal.JClass;
import com.sun.tools.internal.xjc.Options;
import com.sun.tools.internal.xjc.generator.bean.field.FieldRenderer;
import org.w3c.dom.Element;
/**
* Particles in the &lt;content> declaration in the binding file.
*
*/
public class BIContent
{
/**
* Wraps a given particle.
*
* <p>
* This object should be created through
* the {@link #create(Element, BIElement)} method.
*/
private BIContent( Element e, BIElement _parent ) {
this.element = e;
this.parent = _parent;
this.opts = parent.parent.model.options;
}
/** The particle element which this object is wrapping. */
protected final Element element;
/** The parent object.*/
protected final BIElement parent;
private final Options opts;
/**
* Gets the realization of this particle, if any.
*
* @return
* null if the "collection" attribute was not specified.
*/
public final FieldRenderer getRealization() {
String v = DOMUtil.getAttribute(element,"collection");
if(v==null) return null;
v = v.trim();
if(v.equals("array")) return opts.getFieldRendererFactory().getArray();
if(v.equals("list"))
return opts.getFieldRendererFactory().getList(
parent.parent.codeModel.ref(ArrayList.class));
// the correctness of the attribute value must be
// checked by the validator.
throw new InternalError("unexpected collection value: "+v);
}
/**
* Gets the property name of this particle.
*
* @return
* always a non-null, valid string.
*/
public final String getPropertyName() {
String r = DOMUtil.getAttribute(element,"property");
// in case of <element-ref>, @property is optional and
// defaults to @name.
// in all other cases, @property is mandatory.
if(r!=null) return r;
return DOMUtil.getAttribute(element,"name");
}
/**
* Gets the type of this property, if any.
* <p>
* &lt;element-ref> particle doesn't have the type.
*
* @return
* null if none is specified.
*/
public final JClass getType() {
try {
String type = DOMUtil.getAttribute(element,"supertype");
if(type==null) return null;
// TODO: does this attribute defaults to the current package?
int idx = type.lastIndexOf('.');
if(idx<0) return parent.parent.codeModel.ref(type);
else return parent.parent.getTargetPackage().ref(type);
} catch( ClassNotFoundException e ) {
// TODO: better error handling
throw new NoClassDefFoundError(e.getMessage());
}
}
/**
* Creates an appropriate subclass of BIContent
* by sniffing the tag name.
* <p>
* This method should be only called by the BIElement class.
*/
static BIContent create( Element e, BIElement _parent ) {
return new BIContent(e,_parent);
}
}

View File

@@ -0,0 +1,40 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.dtd.bindinfo;
import com.sun.tools.internal.xjc.model.TypeUse;
/**
* conversion declaration (&lt;conversion> and &lt;enumeration>).
*/
public interface BIConversion
{
/** Gets the conversion name. */
String name();
/** Gets a transducer for this conversion. */
TypeUse getTransducer();
}

View File

@@ -0,0 +1,273 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.dtd.bindinfo;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.xml.namespace.QName;
import com.sun.tools.internal.xjc.model.CClassInfo;
import com.sun.xml.internal.bind.api.impl.NameConverter;
import org.w3c.dom.Element;
import org.xml.sax.Locator;
/**
* &lt;element> declaration in the binding file.
*/
public final class BIElement
{
/**
* Wraps a given &lt;element> element in the binding file.
*
* <p>
* Should be created only from {@link BindInfo}.
*/
BIElement( BindInfo bi, Element _e ) {
this.parent = bi;
this.e = _e;
{
Element c = DOMUtil.getElement(e,"content");
if(c!=null) {
if(DOMUtil.getAttribute(c,"property")!=null) {
// if @property is there, this is a general declaration
this.rest = BIContent.create(c,this);
} else {
// this must be a model-based declaration
for( Element p : DOMUtil.getChildElements(c) ) {
if(p.getLocalName().equals("rest"))
this.rest = BIContent.create(p,this);
else
this.contents.add(BIContent.create(p,this));
}
}
}
}
// parse <attribute>s
for( Element atr : DOMUtil.getChildElements(e,"attribute") ) {
BIAttribute a = new BIAttribute( this, atr );
attributes.put(a.name(),a);
}
if(isClass()) {
// if this is a class-declaration, create JClass object now
String className = DOMUtil.getAttribute(e,"class");
if(className==null)
// none was specified. infer the name.
className = NameConverter.standard.toClassName(name());
this.className = className;
} else {
// this is not an element-class declaration
className = null;
}
// process conversion declarations
for( Element conv : DOMUtil.getChildElements(e,"conversion") ) {
BIConversion c = new BIUserConversion(bi,conv);
conversions.put(c.name(),c);
}
for( Element en : DOMUtil.getChildElements(e,"enumeration") ) {
BIConversion c = BIEnumeration.create(en,this);
conversions.put(c.name(),c);
}
// parse <constructor>s
for( Element c : DOMUtil.getChildElements(e,"constructor") ) {
constructors.add( new BIConstructor(c) );
}
String name = name();
QName tagName = new QName("",name);
this.clazz = new CClassInfo(parent.model,parent.getTargetPackage(),className,getLocation(),null,tagName,null,null/*TODO*/);
}
/**
* Gets the source location where this element is declared.
*/
public Locator getLocation() {
return DOMLocator.getLocationInfo(e);
}
/** The parent {@link BindInfo} object to which this object belongs. */
final BindInfo parent;
/** &lt;element> element which this object is wrapping. */
private final Element e;
/**
* The bean representation for this element.
*/
public final CClassInfo clazz;
/**
* Content-property declarations.
* <p>
* This vector will be empty if no content-property declaration is made.
*/
private final List<BIContent> contents = new ArrayList<BIContent>();
/** Conversion declarations. */
private final Map<String,BIConversion> conversions = new HashMap<String,BIConversion>();
/**
* The "rest" content-property declaration.
* <p>
* This field is null when there was no "rest" declaration.
*/
private BIContent rest;
/** Attribute-property declarations. */
private final Map<String,BIAttribute> attributes = new HashMap<String,BIAttribute>();
/** Constructor declarations. */
private final List<BIConstructor> constructors = new ArrayList<BIConstructor>();
/**
* the class which is generated by this declaration.
* This field will be null if this declaration is an element-property
* declaration.
*/
private final String className;
/** Gets the element name. */
public String name() { return DOMUtil.getAttribute(e,"name"); }
/**
* Checks if the element type is "class".
* If false, that means this element will be a value.
*/
public boolean isClass() {
return "class".equals(e.getAttribute("type"));
}
/**
* Checks if this element is designated as a root element.
*/
public boolean isRoot() {
return "true".equals(e.getAttribute("root"));
}
/**
* Gets the JClass object that represents this declaration.
*
* <p>
* This method returns null if this declaration
* is an element-property declaration.
*/
public String getClassName() {
return className;
}
/**
* Creates constructor declarations for this element.
*
* <p>
* This method should only be called by DTDReader <b>after</b>
* the normalization has completed.
*
* @param src
* The ClassItem object that corresponds to this declaration
*/
public void declareConstructors( CClassInfo src ) {
for( BIConstructor c : constructors )
c.createDeclaration(src);
}
/**
* Gets the conversion method for this element.
*
* <p>
* This method can be called only when this element
* declaration is designated as element-value.
*
* @return
* If the convert attribute is not specified, this
* method returns null.
*/
public BIConversion getConversion() {
String cnv = DOMUtil.getAttribute(e,"convert");
if(cnv==null) return null;
return conversion(cnv);
}
/**
* Resolves the conversion name to the conversion declaration.
*
* <p>
* Element-local declarations are checked first.
*
* @return
* A non-null valid BIConversion object.
*/
public BIConversion conversion( String name ) {
BIConversion r = conversions.get(name);
if(r!=null) return r;
// check the global conversion declarations
return parent.conversion(name);
}
/**
* Iterates all content-property declarations (except 'rest').
*/
public List<BIContent> getContents() {
return contents;
}
/**
* Gets the attribute-property declaration, if any.
*
* @return
* null if attribute declaration was not given by that name.
*/
public BIAttribute attribute( String name ) {
return attributes.get(name);
}
/**
* Gets the 'rest' content-property declaration, if any.
* @return
* if there is no 'rest' declaration, return null.
*/
public BIContent getRest() { return this.rest; }
/** Gets the location where this declaration is declared. */
public Locator getSourceLocation() {
return DOMLocator.getLocationInfo(e);
}
}

View File

@@ -0,0 +1,112 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.dtd.bindinfo;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
import com.sun.tools.internal.xjc.model.CBuiltinLeafInfo;
import com.sun.tools.internal.xjc.model.CClassInfoParent;
import com.sun.tools.internal.xjc.model.CEnumConstant;
import com.sun.tools.internal.xjc.model.CEnumLeafInfo;
import com.sun.tools.internal.xjc.model.Model;
import com.sun.tools.internal.xjc.model.TypeUse;
import org.w3c.dom.Element;
/**
* &lt;enumeration> declaration in the binding file.
*/
public final class BIEnumeration implements BIConversion
{
/** Creates an object from &lt;enumeration> declaration. */
private BIEnumeration( Element _e, TypeUse _xducer ) {
this.e = _e;
this.xducer = _xducer;
}
/** &lt;enumeration> element in DOM. */
private final Element e;
private final TypeUse xducer;
public String name() { return DOMUtil.getAttribute(e,"name"); }
/** Returns a transducer for this enumeration declaration. */
public TypeUse getTransducer() { return xducer; }
/** Creates a global enumeration declaration. */
static BIEnumeration create( Element dom, BindInfo parent ) {
// create a class in the target package.
return new BIEnumeration(
dom,
new CEnumLeafInfo(
parent.model,
null,
new CClassInfoParent.Package(parent.getTargetPackage()),
DOMUtil.getAttribute(dom,"name"),
CBuiltinLeafInfo.STRING,
buildMemberList(parent.model,dom),
null, null/*TODO*/,
DOMLocator.getLocationInfo(dom)));
}
/** Creates an element-local enumeration declaration. */
static BIEnumeration create( Element dom, BIElement parent ) {
// create a class as a nested class
return new BIEnumeration(
dom,
new CEnumLeafInfo(
parent.parent.model,
null,
parent.clazz,
DOMUtil.getAttribute(dom,"name"),
CBuiltinLeafInfo.STRING,
buildMemberList(parent.parent.model,dom),
null, null/*TODO*/,
DOMLocator.getLocationInfo(dom) ));
}
private static List<CEnumConstant> buildMemberList( Model model, Element dom ) {
List<CEnumConstant> r = new ArrayList<CEnumConstant>();
String members = DOMUtil.getAttribute(dom,"members");
if(members==null) members=""; // TODO: error handling
StringTokenizer tokens = new StringTokenizer(members);
while(tokens.hasMoreTokens()) {
String token = tokens.nextToken();
r.add(new CEnumConstant(model.getNameConverter().toConstantName(token),
null,token,null/*TODO*/,null,null));
}
return r;
}
}

View File

@@ -0,0 +1,96 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.dtd.bindinfo;
import java.util.StringTokenizer;
import org.w3c.dom.Element;
import org.xml.sax.Locator;
/**
* &lt;interface> declaration in the binding file.
*/
public final class BIInterface
{
BIInterface( Element e ) {
this.dom = e;
name = DOMUtil.getAttribute(e,"name");
members = parseTokens(DOMUtil.getAttribute(e,"members"));
if(DOMUtil.getAttribute(e,"properties")!=null) {
fields = parseTokens(DOMUtil.getAttribute(e,"properties"));
throw new AssertionError("//interface/@properties is not supported");
} else // no property was specified
fields = new String[0];
}
/** &lt;interface> element in the binding file. */
private final Element dom;
/** Name of the generated Java interface. */
private final String name;
/**
* Gets the name of this interface.
* This name should also used as the class name.
*/
public String name() { return name; }
private final String[] members;
/**
* Gets the names of interfaces/classes that implement
* this interface.
*/
public String[] members() { return members; }
private final String[] fields;
/** Gets the names of fields in this interface. */
public String[] fields() { return fields; }
/** Gets the location where this declaration is declared. */
public Locator getSourceLocation() {
return DOMLocator.getLocationInfo(dom);
}
/** splits a list into an array of strings. */
private static String[] parseTokens( String value ) {
StringTokenizer tokens = new StringTokenizer(value);
String[] r = new String[tokens.countTokens()];
int i=0;
while(tokens.hasMoreTokens())
r[i++] = tokens.nextToken();
return r;
}
}

View File

@@ -0,0 +1,227 @@
/*
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.dtd.bindinfo;
import java.io.IOException;
import java.io.StringReader;
import java.util.Map;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import com.sun.codemodel.internal.JClass;
import com.sun.codemodel.internal.JClassAlreadyExistsException;
import com.sun.codemodel.internal.JCodeModel;
import com.sun.codemodel.internal.JDefinedClass;
import com.sun.codemodel.internal.JExpr;
import com.sun.codemodel.internal.JExpression;
import com.sun.codemodel.internal.JMethod;
import com.sun.codemodel.internal.JMod;
import com.sun.codemodel.internal.JPackage;
import com.sun.codemodel.internal.JPrimitiveType;
import com.sun.codemodel.internal.JType;
import com.sun.codemodel.internal.JVar;
import com.sun.tools.internal.xjc.model.CAdapter;
import com.sun.tools.internal.xjc.model.CBuiltinLeafInfo;
import com.sun.tools.internal.xjc.model.TypeUse;
import com.sun.tools.internal.xjc.model.TypeUseFactory;
import com.sun.xml.internal.bind.v2.util.XmlFactory;
import org.w3c.dom.Element;
import org.xml.sax.InputSource;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
/**
* &lt;conversion> declaration in the binding file.
* This declaration declares a conversion by user-specified methods.
*/
public class BIUserConversion implements BIConversion
{
/**
* Wraps a given &lt;conversion> element in the binding file.
*/
BIUserConversion( BindInfo bi, Element _e ) {
this.owner = bi;
this.e = _e;
}
private static void add( Map<String,BIConversion> m, BIConversion c ) {
m.put( c.name(), c );
}
/** Adds all built-in conversions into the given map. */
static void addBuiltinConversions( BindInfo bi, Map<String,BIConversion> m ) {
add( m, new BIUserConversion( bi, parse("<conversion name='boolean' type='java.lang.Boolean' parse='getBoolean' />")));
add( m, new BIUserConversion( bi, parse("<conversion name='byte' type='java.lang.Byte' parse='parseByte' />")));
add( m, new BIUserConversion( bi, parse("<conversion name='short' type='java.lang.Short' parse='parseShort' />")));
add( m, new BIUserConversion( bi, parse("<conversion name='int' type='java.lang.Integer' parse='parseInt' />")));
add( m, new BIUserConversion( bi, parse("<conversion name='long' type='java.lang.Long' parse='parseLong' />")));
add( m, new BIUserConversion( bi, parse("<conversion name='float' type='java.lang.Float' parse='parseFloat' />")));
add( m, new BIUserConversion( bi, parse("<conversion name='double' type='java.lang.Double' parse='parseDouble' />")));
}
private static Element parse(String text) {
try {
//this is parsing well known schemas, do not configure secure processing - always true
DocumentBuilderFactory dbf = XmlFactory.createDocumentBuilderFactory(false);
InputSource is = new InputSource(new StringReader(text));
return dbf.newDocumentBuilder().parse(is).getDocumentElement();
} catch (SAXException x) {
throw new Error(x);
} catch (IOException x) {
throw new Error(x);
} catch (ParserConfigurationException x) {
throw new Error(x);
}
}
/** The owner {@link BindInfo} object to which this object belongs. */
private final BindInfo owner;
/** &lt;conversion> element which this object is wrapping. */
private final Element e;
/** Gets the location where this declaration is declared. */
public Locator getSourceLocation() {
return DOMLocator.getLocationInfo(e);
}
/** Gets the conversion name. */
public String name() { return DOMUtil.getAttribute(e,"name"); }
/** Gets a transducer for this conversion. */
public TypeUse getTransducer() {
String ws = DOMUtil.getAttribute(e,"whitespace");
if(ws==null) ws = "collapse";
String type = DOMUtil.getAttribute(e,"type");
if(type==null) type=name();
JType t=null;
int idx = type.lastIndexOf('.');
if(idx<0) {
// no package name is specified.
try {
t = JPrimitiveType.parse(owner.codeModel,type);
} catch( IllegalArgumentException ex ) {
// otherwise treat it as a class name in the current package
type = owner.getTargetPackage().name()+'.'+type;
}
}
if(t==null) {
try {
// TODO: revisit this later
JDefinedClass cls = owner.codeModel._class(type);
cls.hide();
t = cls;
} catch( JClassAlreadyExistsException ex ) {
t = ex.getExistingClass();
}
}
String parse = DOMUtil.getAttribute(e,"parse");
if(parse==null) parse="new";
String print = DOMUtil.getAttribute(e,"print");
if(print==null) print="toString";
JDefinedClass adapter = generateAdapter(owner.codeModel, parse, print, t.boxify());
// XmlJavaType customization always converts between string and an user-defined type.
return TypeUseFactory.adapt(CBuiltinLeafInfo.STRING,new CAdapter(adapter));
}
// TODO: anyway to reuse this code between XML Schema compiler?
private JDefinedClass generateAdapter(JCodeModel cm, String parseMethod, String printMethod, JClass inMemoryType) {
JDefinedClass adapter = null;
int id = 1;
while(adapter==null) {
try {
JPackage pkg = owner.getTargetPackage();
adapter = pkg._class("Adapter"+id);
} catch (JClassAlreadyExistsException ex) {
// try another name in search for an unique name.
// this isn't too efficient, but we expect people to usually use
// a very small number of adapters.
id++;
}
}
adapter._extends(cm.ref(XmlAdapter.class).narrow(String.class).narrow(inMemoryType));
JMethod unmarshal = adapter.method(JMod.PUBLIC, inMemoryType, "unmarshal");
JVar $value = unmarshal.param(String.class, "value");
JExpression inv;
if( parseMethod.equals("new") ) {
// "new" indicates that the constructor of the target type
// will do the unmarshalling.
// RESULT: new <type>()
inv = JExpr._new(inMemoryType).arg($value);
} else {
int idx = parseMethod.lastIndexOf('.');
if(idx<0) {
// parseMethod specifies the static method of the target type
// which will do the unmarshalling.
// because of an error check at the constructor,
// we can safely assume that this cast works.
inv = inMemoryType.staticInvoke(parseMethod).arg($value);
} else {
inv = JExpr.direct(parseMethod+"(value)");
}
}
unmarshal.body()._return(inv);
JMethod marshal = adapter.method(JMod.PUBLIC, String.class, "marshal");
$value = marshal.param(inMemoryType,"value");
int idx = printMethod.lastIndexOf('.');
if(idx<0) {
// printMethod specifies a method in the target type
// which performs the serialization.
// RESULT: <value>.<method>()
inv = $value.invoke(printMethod);
} else {
// RESULT: <className>.<method>(<value>)
inv = JExpr.direct(printMethod+"(value)");
}
marshal.body()._return(inv);
return adapter;
}
}

View File

@@ -0,0 +1,334 @@
/*
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.dtd.bindinfo;
import java.io.IOException;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.validation.ValidatorHandler;
import com.sun.codemodel.internal.ClassType;
import com.sun.codemodel.internal.JClass;
import com.sun.codemodel.internal.JClassAlreadyExistsException;
import com.sun.codemodel.internal.JCodeModel;
import com.sun.codemodel.internal.JDefinedClass;
import com.sun.codemodel.internal.JPackage;
import com.sun.istack.internal.SAXParseException2;
import com.sun.tools.internal.xjc.AbortException;
import com.sun.tools.internal.xjc.ErrorReceiver;
import com.sun.tools.internal.xjc.SchemaCache;
import com.sun.tools.internal.xjc.model.CCustomizations;
import com.sun.tools.internal.xjc.model.CPluginCustomization;
import com.sun.tools.internal.xjc.model.Model;
import com.sun.tools.internal.xjc.reader.Const;
import com.sun.tools.internal.xjc.util.CodeModelClassFactory;
import com.sun.tools.internal.xjc.util.ErrorReceiverFilter;
import com.sun.tools.internal.xjc.util.ForkContentHandler;
import com.sun.xml.internal.bind.v2.util.XmlFactory;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
/**
* Root of the binding information.
*/
public class BindInfo
{
/** Controller object that can be used to report errors. */
protected final ErrorReceiver errorReceiver;
/*package*/ final Model model;
/**
* The -p option that should control the default Java package that
* will contain the generated code. Null if unspecified. This takes
* precedence over the value specified in the binding file.
*/
private final String defaultPackage;
public BindInfo(Model model, InputSource source, ErrorReceiver _errorReceiver) throws AbortException {
this( model, parse(model,source,_errorReceiver), _errorReceiver);
}
public BindInfo(Model model, Document _dom, ErrorReceiver _errorReceiver) {
this.model = model;
this.dom = _dom.getDocumentElement();
this.codeModel = model.codeModel;
this.errorReceiver = _errorReceiver;
this.classFactory = new CodeModelClassFactory(_errorReceiver);
// TODO: decide name converter from the binding file
this.defaultPackage = model.options.defaultPackage;
// copy global customizations to the model
model.getCustomizations().addAll(getGlobalCustomizations());
// process element declarations
for( Element ele : DOMUtil.getChildElements(dom,"element")) {
BIElement e = new BIElement(this,ele);
elements.put(e.name(),e);
}
// add built-in conversions
BIUserConversion.addBuiltinConversions(this,conversions);
// process conversion declarations
for( Element cnv : DOMUtil.getChildElements(dom,"conversion")) {
BIConversion c = new BIUserConversion(this,cnv);
conversions.put(c.name(),c);
}
for( Element en : DOMUtil.getChildElements(dom,"enumeration")) {
BIConversion c = BIEnumeration.create( en, this );
conversions.put(c.name(),c);
}
// TODO: check the uniquness of conversion name
// process interface definitions
for( Element itf : DOMUtil.getChildElements(dom,"interface")) {
BIInterface c = new BIInterface(itf);
interfaces.put(c.name(),c);
}
}
/** CodeModel object that is used by this binding file. */
final JCodeModel codeModel;
/** Wrap the codeModel object and automate error reporting. */
final CodeModelClassFactory classFactory;
/** DOM tree that represents binding info. */
private final Element dom;
/** Conversion declarations. */
private final Map<String,BIConversion> conversions = new HashMap<String,BIConversion>();
/** Element declarations keyed by names. */
private final Map<String,BIElement> elements = new HashMap<String,BIElement>();
/** interface declarations keyed by names. */
private final Map<String,BIInterface> interfaces = new HashMap<String,BIInterface>();
/** XJC extension namespace. */
private static final String XJC_NS = Const.XJC_EXTENSION_URI;
//
//
// Exposed public methods
//
//
/** Gets the serialVersionUID if it's turned on. */
public Long getSerialVersionUID() {
Element serial = DOMUtil.getElement(dom,XJC_NS,"serializable");
if(serial==null) return null;
String v = DOMUtil.getAttribute(serial,"uid");
if(v==null) v="1";
return new Long(v);
}
/** Gets the xjc:superClass customization if it's turned on. */
public JClass getSuperClass() {
Element sc = DOMUtil.getElement(dom,XJC_NS,"superClass");
if (sc == null) return null;
JDefinedClass c;
try {
String v = DOMUtil.getAttribute(sc,"name");
if(v==null) return null;
c = codeModel._class(v);
c.hide();
} catch (JClassAlreadyExistsException e) {
c = e.getExistingClass();
}
return c;
}
/** Gets the xjc:superInterface customization if it's turned on. */
public JClass getSuperInterface() {
Element sc = DOMUtil.getElement(dom,XJC_NS,"superInterface");
if (sc == null) return null;
String name = DOMUtil.getAttribute(sc,"name");
if (name == null) return null;
JDefinedClass c;
try {
c = codeModel._class(name, ClassType.INTERFACE);
c.hide();
} catch (JClassAlreadyExistsException e) {
c = e.getExistingClass();
}
return c;
}
/**
* Gets the specified package name (options/@package).
*/
public JPackage getTargetPackage() {
if(model.options.defaultPackage!=null)
// "-p" takes precedence over everything else
return codeModel._package(model.options.defaultPackage);
String p;
if( defaultPackage!=null )
p = defaultPackage;
else
p = getOption("package", "");
return codeModel._package(p);
}
/**
* Gets the conversion declaration from the binding info.
*
* @return
* A non-null valid BIConversion object.
*/
public BIConversion conversion(String name) {
BIConversion r = conversions.get(name);
if (r == null)
throw new AssertionError("undefined conversion name: this should be checked by the validator before we read it");
return r;
}
/**
* Gets the element declaration from the binding info.
*
* @return
* If there is no declaration with a given name,
* this method returns null.
*/
public BIElement element( String name ) {
return elements.get(name);
}
/** Iterates all {@link BIElement}s in a read-only set. */
public Collection<BIElement> elements() {
return elements.values();
}
/** Returns all {@link BIInterface}s in a read-only set. */
public Collection<BIInterface> interfaces() {
return interfaces.values();
}
/**
* Gets the list of top-level {@link CPluginCustomization}s.
*/
private CCustomizations getGlobalCustomizations() {
CCustomizations r=null;
for( Element e : DOMUtil.getChildElements(dom) ) {
if(!model.options.pluginURIs.contains(e.getNamespaceURI()))
continue; // this isn't a plugin customization
if(r==null)
r = new CCustomizations();
r.add(new CPluginCustomization(e, DOMLocator.getLocationInfo(e)));
}
if(r==null) r = CCustomizations.EMPTY;
return new CCustomizations(r);
}
//
//
// Internal utility methods
//
//
/** Gets the value from the option element. */
private String getOption(String attName, String defaultValue) {
Element opt = DOMUtil.getElement(dom,"options");
if (opt != null) {
String s = DOMUtil.getAttribute(opt,attName);
if (s != null)
return s;
}
return defaultValue;
}
/**
* Lazily parsed schema for the binding file.
*/
private static SchemaCache bindingFileSchema = new SchemaCache(BindInfo.class.getResource("bindingfile.xsd"));
/**
* Parses an InputSource into dom4j Document.
* Returns null in case of an exception.
*/
private static Document parse( Model model, InputSource is, ErrorReceiver receiver ) throws AbortException {
try {
ValidatorHandler validator = bindingFileSchema.newValidator();
// set up the pipe line as :
// /-> extensionChecker -> validator
// parser-> -<
// \-> DOM builder
SAXParserFactory pf = XmlFactory.createParserFactory(model.options.disableXmlSecurity);
DocumentBuilderFactory domFactory = XmlFactory.createDocumentBuilderFactory(model.options.disableXmlSecurity);
DOMBuilder builder = new DOMBuilder(domFactory);
ErrorReceiverFilter controller = new ErrorReceiverFilter(receiver);
validator.setErrorHandler(controller);
XMLReader reader = pf.newSAXParser().getXMLReader();
reader.setErrorHandler(controller);
DTDExtensionBindingChecker checker = new DTDExtensionBindingChecker("", model.options, controller);
checker.setContentHandler(validator);
reader.setContentHandler(new ForkContentHandler(checker,builder));
reader.parse(is);
if(controller.hadError()) throw new AbortException();
return (Document)builder.getDOM();
} catch( IOException e ) {
receiver.error( new SAXParseException2(e.getMessage(),null,e) );
} catch( SAXException e ) {
receiver.error( new SAXParseException2(e.getMessage(),null,e) );
} catch( ParserConfigurationException e ) {
receiver.error( new SAXParseException2(e.getMessage(),null,e) );
}
throw new AbortException();
}
}

View File

@@ -0,0 +1,57 @@
/*
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.dtd.bindinfo;
import javax.xml.parsers.ParserConfigurationException;
import com.sun.xml.internal.bind.marshaller.SAX2DOMEx;
import javax.xml.parsers.DocumentBuilderFactory;
import org.xml.sax.Attributes;
import org.xml.sax.Locator;
/**
* @author Kohsuke Kawaguchi
*/
final class DOMBuilder extends SAX2DOMEx {
private Locator locator;
public DOMBuilder(DocumentBuilderFactory f) throws ParserConfigurationException {
super(f);
}
@Override
public void setDocumentLocator(Locator locator) {
super.setDocumentLocator(locator);
this.locator = locator;
}
@Override
public void startElement(String namespace, String localName, String qName, Attributes attrs) {
super.startElement(namespace, localName, qName, attrs);
DOMLocator.setLocationInfo(getCurrentElement(),locator);
}
}

View File

@@ -0,0 +1,70 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.dtd.bindinfo;
import org.w3c.dom.Element;
import org.xml.sax.Locator;
class DOMLocator {
private static final String locationNamespace =
"http://www.sun.com/xmlns/jaxb/dom-location";
private static final String systemId = "systemid";
private static final String column = "column";
private static final String line = "line";
/** Sets the location information to a specified element. */
public static void setLocationInfo( Element e, Locator loc ) {
e.setAttributeNS(locationNamespace,"loc:"+systemId,loc.getSystemId());
e.setAttributeNS(locationNamespace,"loc:"+column,Integer.toString(loc.getLineNumber()));
e.setAttributeNS(locationNamespace,"loc:"+line,Integer.toString(loc.getColumnNumber()));
}
/**
* Gets the location information from an element.
*
* <p>
* For this method to work, the setLocationInfo method has to be
* called before.
*/
public static Locator getLocationInfo( final Element e ) {
if(DOMUtil.getAttribute(e,locationNamespace,systemId)==null)
return null; // no location information
return new Locator(){
public int getLineNumber() {
return Integer.parseInt(DOMUtil.getAttribute(e,locationNamespace,line));
}
public int getColumnNumber() {
return Integer.parseInt(DOMUtil.getAttribute(e,locationNamespace,column));
}
public String getSystemId() {
return DOMUtil.getAttribute(e,locationNamespace,systemId);
}
// we are not interested in PUBLIC ID.
public String getPublicId() { return null; }
};
}
}

View File

@@ -0,0 +1,108 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.dtd.bindinfo;
import java.util.ArrayList;
import java.util.List;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
* @author Kohsuke Kawaguchi
*/
public final class DOMUtil {
final static String getAttribute(Element e,String attName) {
if(e.getAttributeNode(attName)==null) return null;
return e.getAttribute(attName);
}
public static String getAttribute(Element e, String nsUri, String local) {
if(e.getAttributeNodeNS(nsUri,local)==null) return null;
return e.getAttributeNS(nsUri,local);
}
public static Element getElement(Element e, String nsUri, String localName) {
NodeList l = e.getChildNodes();
for(int i=0;i<l.getLength();i++) {
Node n = l.item(i);
if(n.getNodeType()==Node.ELEMENT_NODE) {
Element r = (Element)n;
if(equals(r.getLocalName(),localName) && equals(fixNull(r.getNamespaceURI()),nsUri))
return r;
}
}
return null;
}
/**
* Used for defensive string comparisons, as many DOM methods often return null
* depending on how they are created.
*/
private static boolean equals(String a,String b) {
if(a==b) return true;
if(a==null || b==null) return false;
return a.equals(b);
}
/**
* DOM API returns null for the default namespace whereas it should return "".
*/
private static String fixNull(String s) {
if(s==null) return "";
else return s;
}
public static Element getElement(Element e, String localName) {
return getElement(e,"",localName);
}
public static List<Element> getChildElements(Element e) {
List<Element> r = new ArrayList<Element>();
NodeList l = e.getChildNodes();
for(int i=0;i<l.getLength();i++) {
Node n = l.item(i);
if(n.getNodeType()==Node.ELEMENT_NODE)
r.add((Element)n);
}
return r;
}
public static List<Element> getChildElements(Element e,String localName) {
List<Element> r = new ArrayList<Element>();
NodeList l = e.getChildNodes();
for(int i=0;i<l.getLength();i++) {
Node n = l.item(i);
if(n.getNodeType()==Node.ELEMENT_NODE) {
Element c = (Element)n;
if(c.getLocalName().equals(localName))
r.add(c);
}
}
return r;
}
}

View File

@@ -0,0 +1,89 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.dtd.bindinfo;
import com.sun.tools.internal.xjc.Options;
import com.sun.tools.internal.xjc.reader.AbstractExtensionBindingChecker;
import com.sun.tools.internal.xjc.reader.Const;
import org.xml.sax.Attributes;
import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXException;
import org.xml.sax.XMLFilter;
/**
* {@link XMLFilter} that checks the use of extension namespace URIs
* (to see if they have corresponding plugins), and otherwise report an error.
*
* <p>
* This code also masks the recognized extensions from the validator that
* will be plugged as the next component to this.
*
* @author Kohsuke Kawaguchi
*/
final class DTDExtensionBindingChecker extends AbstractExtensionBindingChecker {
public DTDExtensionBindingChecker(String schemaLanguage, Options options, ErrorHandler handler) {
super(schemaLanguage, options, handler);
}
/**
* Returns true if the elements with the given namespace URI
* should be blocked by this filter.
*/
private boolean needsToBePruned( String uri ) {
if( uri.equals(schemaLanguage) )
return false;
if( uri.equals(Const.JAXB_NSURI) )
return false;
if( uri.equals(Const.XJC_EXTENSION_URI) )
return false;
// we don't want validator to see extensions that we understand ,
// because they will complain.
// OTOH, if this is an extension that we didn't understand,
// we want the validator to report an error
return enabledExtensions.contains(uri);
}
public void startElement(String uri, String localName, String qName, Attributes atts)
throws SAXException {
if( !isCutting() ) {
if(!uri.equals("")) {
// "" is the standard namespace
checkAndEnable(uri);
verifyTagName(uri, localName, qName);
if(needsToBePruned(uri))
startCutting();
}
}
super.startElement(uri, localName, qName, atts);
}
}

View File

@@ -0,0 +1,46 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.dtd.bindinfo;
import java.text.MessageFormat;
import java.util.ResourceBundle;
/**
* Formats error messages.
*/
class Messages
{
/** Loads a string resource and formats it with specified arguments. */
static String format( String property, Object... args ) {
String text = ResourceBundle.getBundle(Messages.class.getPackage().getName() + ".MessageBundle").getString(property);
return MessageFormat.format(text,args);
}
static final String ERR_UNDEFINED_FIELD = // arg:1
"BIConstructor.UndefinedField";
}

View File

@@ -0,0 +1,69 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.gbind;
/**
* {@link Expression} that represents the union of two expressions "A|B".
*
* @author Kohsuke Kawaguchi
*/
public final class Choice extends Expression {
/**
* "A" of "A|B".
*/
private final Expression lhs;
/**
* "B" of "A|B".
*/
private final Expression rhs;
/**
* Compute this value eagerly for better performance
*/
private final boolean isNullable;
public Choice(Expression lhs, Expression rhs) {
this.lhs = lhs;
this.rhs = rhs;
this.isNullable = lhs.isNullable() || rhs.isNullable();
}
boolean isNullable() {
return isNullable;
}
ElementSet lastSet() {
return ElementSets.union(lhs.lastSet(),rhs.lastSet());
}
void buildDAG(ElementSet incoming) {
lhs.buildDAG(incoming);
rhs.buildDAG(incoming);
}
public String toString() {
return '('+lhs.toString()+'|'+rhs.toString()+')';
}
}

View File

@@ -0,0 +1,98 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.gbind;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
* Represents one strongly-connected component
* of the {@link Element} graph.
*
* @author Kohsuke Kawaguchi
*/
public final class ConnectedComponent implements Iterable<Element> {
/**
* {@link Element}s that belong to this component.
*/
private final List<Element> elements = new ArrayList<Element>();
/*package*/ boolean isRequired;
/**
* Returns true iff this {@link ConnectedComponent}
* can match a substring whose length is greater than 1.
*
* <p>
* That means this property will become a collection property.
*/
public final boolean isCollection() {
assert !elements.isEmpty();
// a strongly connected component by definition has a cycle,
// so if its size is bigger than 1 there must be a cycle.
if(elements.size()>1)
return true;
// if size is 1, it might be still forming a self-cycle
Element n = elements.get(0);
return n.hasSelfLoop();
}
/**
* Returns true iff this {@link ConnectedComponent}
* forms a cut set of a graph.
*
* <p>
* That means any valid element sequence must have at least
* one value for this property.
*/
public final boolean isRequired() {
return isRequired;
}
/*package*/void add(Element e) {
assert !elements.contains(e);
elements.add(e);
}
public Iterator<Element> iterator() {
return elements.iterator();
}
/**
* Just produces debug representation
*/
public String toString() {
String s = elements.toString();
if(isRequired())
s += '!';
if(isCollection())
s += '*';
return s;
}
}

View File

@@ -0,0 +1,228 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.gbind;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
/**
* {@link Expression} that represents an alphabet of a regular language.
*
* <p>
* Since this package is about a regular expression over element declarations,
* this represents an XML element declaration (hence the name.)
*
* Element needs to be interned, meaning one {@link Element} per one tag name.
*
* <p>
* Implements {@link ElementSet} to represent a self.
*
* @author Kohsuke Kawaguchi
*/
public abstract class Element extends Expression implements ElementSet {
/**
* Once we build a graph from {@link Expression},
* we represent an edge e1 -> e2 by {@code e1.foreEdges.contains(e2)}
* and {@code e2.backEdges.contains(e1)}.
*/
final Set<Element> foreEdges = new LinkedHashSet<Element>();
final Set<Element> backEdges = new LinkedHashSet<Element>();
/**
* Previous element in the DFS post-order traveral
* of the element graph.
*
* <p>
* We use {@code prevPostOrder==null} as a check if the element is visted in DFS,
* so this chain terminates by a self-reference, not by having null.
*
* Set in {@link #assignDfsPostOrder(Element)}
*/
/*package*/ Element prevPostOrder;
/**
* {@link ConnectedComponent} to which this element belongs.
*
* Set in {@link #buildStronglyConnectedComponents(List<ConnectedComponent>)}
*/
private ConnectedComponent cc;
protected Element() {
}
ElementSet lastSet() {
return this;
}
boolean isNullable() {
return false;
}
/**
* True if this {@link Element} is {@link SourceNode}.
*/
boolean isSource() {
return false;
}
/**
* True if this {@link Element} is {@link SinkNode}.
*/
boolean isSink() {
return false;
}
void buildDAG(ElementSet incoming) {
incoming.addNext(this);
}
public void addNext(Element element) {
foreEdges.add(element);
element.backEdges.add(this);
}
public boolean contains(ElementSet rhs) {
return this==rhs || rhs==ElementSet.EMPTY_SET;
}
/**
* Just to satisfy the {@link ElementSet} contract.
*
* @deprecated
* if you statically call this method, there's something wrong.
*/
public Iterator<Element> iterator() {
return Collections.singleton(this).iterator();
}
/**
* Traverses the {@link Element} graph with DFS
* and set {@link #prevPostOrder}.
*
* Should be first invoked on the source node of the graph.
*/
/*package*/ Element assignDfsPostOrder(Element prev) {
if(prevPostOrder!=null)
return prev; // already visited
prevPostOrder = this; // set a dummy value to prepare for cycles
for (Element next : foreEdges) {
prev = next.assignDfsPostOrder(prev);
}
this.prevPostOrder = prev; // set to the real value
return this;
}
/**
* Builds a set of strongly connected components and puts them
* all into the given set.
*/
public void buildStronglyConnectedComponents(List<ConnectedComponent> ccs) {
// store visited elements - loop detection
List<Element> visitedElements = new ArrayList<Element>();
for(Element cur=this; cur!=cur.prevPostOrder; cur=cur.prevPostOrder) {
if(visitedElements.contains(cur)) {
// if I've already processed cur element, I'm in a loop
break;
} else {
visitedElements.add(cur);
}
if(cur.belongsToSCC())
continue;
// start a new component
ConnectedComponent cc = new ConnectedComponent();
ccs.add(cc);
cur.formConnectedComponent(cc);
}
}
private boolean belongsToSCC() {
return cc!=null || isSource() || isSink();
}
/**
* Forms a strongly connected component by doing a reverse DFS.
*/
private void formConnectedComponent(ConnectedComponent group) {
if(belongsToSCC())
return;
this.cc=group;
group.add(this);
for (Element prev : backEdges)
prev.formConnectedComponent(group);
}
public boolean hasSelfLoop() {
// if foreEdges have a loop, backEdges must have one. Or vice versa
assert foreEdges.contains(this)==backEdges.contains(this);
return foreEdges.contains(this);
}
/**
* Checks if the given {@link ConnectedComponent} forms a cut-set
* of a graph.
*
* @param visited
* Used to keep track of visited nodes.
* @return
* true if it is indeed a cut-set. false if not.
*/
/*package*/ final boolean checkCutSet(ConnectedComponent cc, Set<Element> visited) {
assert belongsToSCC(); // SCC discomposition must be done first
if(isSink())
// the definition of the cut set is that without those nodes
// you can't reach from soruce to sink
return false;
if(!visited.add(this))
return true;
if(this.cc==cc)
return true;
for (Element next : foreEdges) {
if(!next.checkCutSet(cc,visited))
// we've found a path to the sink
return false;
}
return true;
}
}

View File

@@ -0,0 +1,63 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.gbind;
import java.util.Collections;
import java.util.Iterator;
/**
* A set over a list of {@link Element}.
*
* @author Kohsuke Kawaguchi
*/
interface ElementSet extends Iterable<Element> {
/**
* For each element in this set, adds an edge to the given element.
*/
void addNext(Element element);
public static final ElementSet EMPTY_SET = new ElementSet() {
public void addNext(Element element) {
// noop
}
public boolean contains(ElementSet element) {
return this==element;
}
public Iterator<Element> iterator() {
return Collections.<Element>emptySet().iterator();
}
};
/**
* Doesn't have to be strict (it's OK for this method to return false
* when it's actually true) since this is used just for optimization.
*
* (Erring on the other side is NG)
*/
boolean contains(ElementSet rhs);
}

View File

@@ -0,0 +1,84 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.gbind;
import java.util.LinkedHashSet;
/**
* Factory methods for {@link ElementSet}.
*
* @author Kohsuke Kawaguchi
*/
public final class ElementSets {
/**
* Returns an union of two {@link ElementSet}s.
*
* This method performs better if lhs is bigger than rhs
*/
public static ElementSet union(ElementSet lhs, ElementSet rhs) {
if(lhs.contains(rhs))
return lhs;
if(lhs==ElementSet.EMPTY_SET)
return rhs;
if(rhs==ElementSet.EMPTY_SET)
return lhs;
return new MultiValueSet(lhs,rhs);
}
/**
* {@link ElementSet} that has multiple {@link Element}s in it.
*
* This isn't particularly efficient or anything, but it will do for now.
*/
private static final class MultiValueSet extends LinkedHashSet<Element> implements ElementSet {
public MultiValueSet(ElementSet lhs, ElementSet rhs) {
addAll(lhs);
addAll(rhs);
// not that anything will break with size==1 MultiValueSet,
// but it does suggest that we are missing an easy optimization
assert size()>1;
}
private void addAll(ElementSet lhs) {
if(lhs instanceof MultiValueSet) {
super.addAll((MultiValueSet)lhs);
} else {
for (Element e : lhs)
add(e);
}
}
public boolean contains(ElementSet rhs) {
// this isn't complete but sound
return super.contains(rhs) || rhs==ElementSet.EMPTY_SET;
}
public void addNext(Element element) {
for (Element e : this)
e.addNext(element);
}
}
}

View File

@@ -0,0 +1,72 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.gbind;
import java.util.Set;
/**
* This builds content models.
*
* @author Kohsuke Kawaguchi
*/
public abstract class Expression {
/**
* Computes <tt>LAST(exp)</tt>
*/
abstract ElementSet lastSet();
/**
* True of <tt>\epsilon \in L(exp)</tt>
*/
abstract boolean isNullable();
/**
* Builds up a DAG among {@link Element}s in this expression.
*/
abstract void buildDAG(ElementSet incoming);
/**
* {@link Expression} that represents epsilon, the length-0 string.
*/
public static final Expression EPSILON = new Expression() {
ElementSet lastSet() {
return ElementSet.EMPTY_SET;
}
boolean isNullable() {
return true;
}
void buildDAG(ElementSet incoming) {
// noop
}
public String toString() {
return "-";
}
};
}

View File

@@ -0,0 +1,88 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.gbind;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
/**
* Graph of {@link Element}s.
*
* @author Kohsuke Kawaguchi
*/
public final class Graph implements Iterable<ConnectedComponent> {
private final Element source = new SourceNode();
private final Element sink = new SinkNode();
/**
* Strongly connected components of this graph.
*/
private final List<ConnectedComponent> ccs = new ArrayList<ConnectedComponent>();
/**
* Builds a {@link Graph} from an {@link Expression} tree.
*
* {@link Expression} given to the graph will be modified forever,
* and it will not be able to create another {@link Graph}.
*/
public Graph(Expression body) {
// attach source and sink
Expression whole = new Sequence(new Sequence(source,body),sink);
// build up a graph
whole.buildDAG(ElementSet.EMPTY_SET);
// decompose into strongly connected components.
// the algorithm is standard DFS-based algorithm,
// one illustration of this algorithm is available at
// http://www.personal.kent.edu/~rmuhamma/Algorithms/MyAlgorithms/GraphAlgor/strongComponent.htm
source.assignDfsPostOrder(sink);
source.buildStronglyConnectedComponents(ccs);
// cut-set check
Set<Element> visited = new HashSet<Element>();
for (ConnectedComponent cc : ccs) {
visited.clear();
if(source.checkCutSet(cc,visited)) {
cc.isRequired = true;
}
}
}
/**
* List up {@link ConnectedComponent}s of this graph in an order.
*/
public Iterator<ConnectedComponent> iterator() {
return ccs.iterator();
}
public String toString() {
return ccs.toString();
}
}

View File

@@ -0,0 +1,58 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.gbind;
/**
* {@link Expression} that represents kleene-star operation (A+)
*
* @author Kohsuke Kawaguchi
*/
public final class OneOrMore extends Expression {
/**
* 'A' of 'A+'.
*/
private final Expression child;
public OneOrMore(Expression child) {
this.child = child;
}
ElementSet lastSet() {
return child.lastSet();
}
boolean isNullable() {
return child.isNullable();
}
void buildDAG(ElementSet incoming) {
child.buildDAG(ElementSets.union(incoming,child.lastSet()));
}
public String toString() {
return child.toString()+'+';
}
}

View File

@@ -0,0 +1,85 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.gbind;
/**
* {@link Expression} that represents a concatanation of two expressions
* "A,B".
*
* @author Kohsuke Kawaguchi
*/
public final class Sequence extends Expression {
/**
* 'A' of 'A,B'
*/
private final Expression lhs;
/**
* 'B' of 'A,B'
*/
private final Expression rhs;
/**
* Compute this value eagerly for better performance
*/
private final boolean isNullable;
/**
* Cached value of {@link #lastSet()} for better performance.
* Sequence tends to be where the recursive lastSet computation occurs.
*/
private ElementSet lastSet;
public Sequence(Expression lhs, Expression rhs) {
this.lhs = lhs;
this.rhs = rhs;
isNullable = lhs.isNullable() && rhs.isNullable();
}
ElementSet lastSet() {
if(lastSet==null) {
if(rhs.isNullable())
lastSet = ElementSets.union(lhs.lastSet(),rhs.lastSet());
else
lastSet = rhs.lastSet();
}
return lastSet;
}
boolean isNullable() {
return isNullable;
}
void buildDAG(ElementSet incoming) {
lhs.buildDAG(incoming);
if(lhs.isNullable())
rhs.buildDAG(ElementSets.union(incoming,lhs.lastSet()));
else
rhs.buildDAG(lhs.lastSet());
}
public String toString() {
return '('+lhs.toString()+','+rhs.toString()+')';
}
}

View File

@@ -0,0 +1,41 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.gbind;
/**
* Sink node of a grpah.
* @author Kohsuke Kawaguchi
*/
public final class SinkNode extends Element {
public String toString() {
return "#sink";
}
@Override
boolean isSink() {
return true;
}
}

View File

@@ -0,0 +1,41 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.gbind;
/**
* Source node of a graph.
* @author Kohsuke Kawaguchi
*/
public final class SourceNode extends Element {
public String toString() {
return "#source";
}
@Override
boolean isSource() {
return true;
}
}

View File

@@ -0,0 +1,132 @@
/*
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.internalizer;
import com.sun.istack.internal.SAXParseException2;
import org.xml.sax.Attributes;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.helpers.XMLFilterImpl;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
/**
* XMLFilter that finds references to other schema files from
* SAX events.
* <p/>
* This implementation is a base implementation for typical case
* where we just need to look for a particular attribute which
* contains an URL to another schema file.
*
* @author Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
*/
public abstract class AbstractReferenceFinderImpl extends XMLFilterImpl {
protected final DOMForest parent;
protected AbstractReferenceFinderImpl(DOMForest _parent) {
this.parent = _parent;
}
/**
* IF the given element contains a reference to an external resource,
* return its URL.
*
* @param nsURI Namespace URI of the current element
* @param localName Local name of the current element
* @return It's OK to return a relative URL.
*/
protected abstract String findExternalResource(String nsURI, String localName, Attributes atts);
@Override
public void startElement(String namespaceURI, String localName, String qName, Attributes atts)
throws SAXException {
super.startElement(namespaceURI, localName, qName, atts);
String relativeRef = findExternalResource(namespaceURI, localName, atts);
if (relativeRef == null) {
return; // not found
}
try {
// absolutize URL.
String lsi = locator.getSystemId();
String ref;
URI relRefURI = new URI(relativeRef);
if (relRefURI.isAbsolute())
ref = relativeRef;
else {
if (lsi.startsWith("jar:")) {
int bangIdx = lsi.indexOf('!');
if (bangIdx > 0) {
ref = lsi.substring(0, bangIdx + 1)
+ new URI(lsi.substring(bangIdx + 1)).resolve(new URI(relativeRef)).toString();
} else {
ref = relativeRef;
}
} else {
ref = new URI(lsi).resolve(new URI(relativeRef)).toString();
}
}
// then parse this schema as well,
// but don't mark this document as a root.
if (parent != null) { // this is there to allow easier testing
parent.parse(ref, false);
}
} catch (URISyntaxException e) {
String msg = e.getMessage();
if (new File(relativeRef).exists()) {
msg = Messages.format(Messages.ERR_FILENAME_IS_NOT_URI) + ' ' + msg;
}
SAXParseException spe = new SAXParseException2(
Messages.format(Messages.ERR_UNABLE_TO_PARSE, relativeRef, msg),
locator, e);
fatalError(spe);
throw spe;
} catch (IOException e) {
SAXParseException spe = new SAXParseException2(
Messages.format(Messages.ERR_UNABLE_TO_PARSE, relativeRef, e.getMessage()),
locator, e);
fatalError(spe);
throw spe;
}
}
private Locator locator;
@Override
public void setDocumentLocator(Locator locator) {
super.setDocumentLocator(locator);
this.locator = locator;
}
}

View File

@@ -0,0 +1,115 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.internalizer;
import javax.xml.XMLConstants;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.SAXNotRecognizedException;
import org.xml.sax.SAXNotSupportedException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.AttributesImpl;
import org.xml.sax.helpers.XMLFilterImpl;
/**
* {@link XMLReader} filter for supporting
* <tt>http://xml.org/sax/features/namespace-prefixes</tt> feature.
*
* @author Kohsuke Kawaguchi
*/
final class ContentHandlerNamespacePrefixAdapter extends XMLFilterImpl {
/**
* True if <tt>http://xml.org/sax/features/namespace-prefixes</tt> is set to true.
*/
private boolean namespacePrefixes = false;
private String[] nsBinding = new String[8];
private int len;
public ContentHandlerNamespacePrefixAdapter() {
}
public ContentHandlerNamespacePrefixAdapter(XMLReader parent) {
setParent(parent);
}
@Override
public boolean getFeature(String name) throws SAXNotRecognizedException, SAXNotSupportedException {
if(name.equals(PREFIX_FEATURE))
return namespacePrefixes;
return super.getFeature(name);
}
@Override
public void setFeature(String name, boolean value) throws SAXNotRecognizedException, SAXNotSupportedException {
if(name.equals(PREFIX_FEATURE)) {
this.namespacePrefixes = value;
return;
}
if(name.equals(NAMESPACE_FEATURE) && value)
return;
super.setFeature(name, value);
}
@Override
public void startPrefixMapping(String prefix, String uri) throws SAXException {
if (XMLConstants.XML_NS_URI.equals(uri)) return; //xml prefix shall not be declared based on jdk api javadoc
if(len==nsBinding.length) {
// reallocate
String[] buf = new String[nsBinding.length*2];
System.arraycopy(nsBinding,0,buf,0,nsBinding.length);
nsBinding = buf;
}
nsBinding[len++] = prefix;
nsBinding[len++] = uri;
super.startPrefixMapping(prefix,uri);
}
@Override
public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {
if(namespacePrefixes) {
this.atts.setAttributes(atts);
// add namespace bindings back as attributes
for( int i=0; i<len; i+=2 ) {
String prefix = nsBinding[i];
if(prefix.length()==0)
this.atts.addAttribute(XMLConstants.XML_NS_URI,"xmlns","xmlns","CDATA",nsBinding[i+1]);
else
this.atts.addAttribute(XMLConstants.XML_NS_URI,prefix,"xmlns:"+prefix,"CDATA",nsBinding[i+1]);
}
atts = this.atts;
}
len=0;
super.startElement(uri, localName, qName, atts);
}
private final AttributesImpl atts = new AttributesImpl();
private static final String PREFIX_FEATURE = "http://xml.org/sax/features/namespace-prefixes";
private static final String NAMESPACE_FEATURE = "http://xml.org/sax/features/namespaces";
}

View File

@@ -0,0 +1,86 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.internalizer;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.text.MessageFormat;
import java.util.ResourceBundle;
import java.util.WeakHashMap;
/**
* Simple utility ensuring that the value is cached only in case it is non-internal implementation
*/
abstract class ContextClassloaderLocal<V> {
private static final String FAILED_TO_CREATE_NEW_INSTANCE = "FAILED_TO_CREATE_NEW_INSTANCE";
private WeakHashMap<ClassLoader, V> CACHE = new WeakHashMap<ClassLoader, V>();
public V get() throws Error {
ClassLoader tccl = getContextClassLoader();
V instance = CACHE.get(tccl);
if (instance == null) {
instance = createNewInstance();
CACHE.put(tccl, instance);
}
return instance;
}
public void set(V instance) {
CACHE.put(getContextClassLoader(), instance);
}
protected abstract V initialValue() throws Exception;
private V createNewInstance() {
try {
return initialValue();
} catch (Exception e) {
throw new Error(format(FAILED_TO_CREATE_NEW_INSTANCE, getClass().getName()), e);
}
}
private static String format(String property, Object... args) {
String text = ResourceBundle.getBundle(ContextClassloaderLocal.class.getName()).getString(property);
return MessageFormat.format(text, args);
}
private static ClassLoader getContextClassLoader() {
return (ClassLoader)
AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
ClassLoader cl = null;
try {
cl = Thread.currentThread().getContextClassLoader();
} catch (SecurityException ex) {
}
return cl;
}
});
}
}

View File

@@ -0,0 +1,102 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.internalizer;
import java.util.Set;
import com.sun.tools.internal.xjc.reader.Const;
import com.sun.xml.internal.bind.marshaller.SAX2DOMEx;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.xml.sax.Attributes;
import org.xml.sax.Locator;
/**
* Builds DOM while keeping the location information.
*
* <p>
* This class also looks for outer most &lt;jaxb:bindings>
* customizations.
*
* @author
* Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
*/
class DOMBuilder extends SAX2DOMEx {
/**
* Grows a DOM tree under the given document, and
* stores location information to the given table.
*
* @param outerMostBindings
* This set will receive newly found outermost
* jaxb:bindings customizations.
*/
public DOMBuilder( Document dom, LocatorTable ltable, Set outerMostBindings ) {
super( dom );
this.locatorTable = ltable;
this.outerMostBindings = outerMostBindings;
}
/** Location information will be stored into this object. */
private final LocatorTable locatorTable;
private final Set outerMostBindings;
private Locator locator;
public void setDocumentLocator(Locator locator) {
this.locator = locator;
super.setDocumentLocator(locator);
}
public void startElement(String namespaceURI, String localName, String qName, Attributes atts) {
super.startElement(namespaceURI, localName, qName, atts);
Element e = getCurrentElement();
locatorTable.storeStartLocation( e, locator );
// check if this element is an outer-most <jaxb:bindings>
if( Const.JAXB_NSURI.equals(e.getNamespaceURI())
&& "bindings".equals(e.getLocalName()) ) {
// if this is the root node (meaning that this file is an
// external binding file) or if the parent is XML Schema element
// (meaning that this is an "inlined" external binding)
Node p = e.getParentNode();
if( p instanceof Document
||( p instanceof Element && !e.getNamespaceURI().equals(p.getNamespaceURI()))) {
outerMostBindings.add(e); // remember this value
}
}
}
public void endElement(String namespaceURI, String localName, String qName) {
locatorTable.storeEndLocation( getCurrentElement(), locator );
super.endElement(namespaceURI, localName, qName);
}
}

View File

@@ -0,0 +1,574 @@
/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.internalizer;
import com.sun.istack.internal.NotNull;
import com.sun.istack.internal.XMLStreamReaderToContentHandler;
import com.sun.tools.internal.xjc.ErrorReceiver;
import com.sun.tools.internal.xjc.Options;
import com.sun.tools.internal.xjc.reader.Const;
import com.sun.tools.internal.xjc.util.ErrorReceiverFilter;
import com.sun.xml.internal.bind.marshaller.DataWriter;
import com.sun.xml.internal.bind.v2.util.XmlFactory;
import com.sun.xml.internal.xsom.parser.JAXPParser;
import com.sun.xml.internal.xsom.parser.XMLParser;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.*;
import org.xml.sax.helpers.XMLFilterImpl;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.sax.SAXResult;
import javax.xml.transform.sax.SAXSource;
import javax.xml.validation.SchemaFactory;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.util.*;
import static com.sun.xml.internal.bind.v2.util.XmlFactory.allowExternalAccess;
import static javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI;
/**
* Builds a DOM forest and maintains association from
* system IDs to DOM trees.
*
* <p>
* A forest is a transitive reflexive closure of referenced documents.
* IOW, if a document is in a forest, all the documents referenced from
* it is in a forest, too. To support this semantics, {@link DOMForest}
* uses {@link InternalizationLogic} to find referenced documents.
*
* <p>
* Some documents are marked as "root"s, meaning those documents were
* put into a forest explicitly, not because it is referenced from another
* document. (However, a root document can be referenced from other
* documents, too.)
*
* @author
* Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
*/
public final class DOMForest {
/** actual data storage map&lt;SystemId,Document>. */
private final Map<String,Document> core = new HashMap<String,Document>();
/**
* To correctly feed documents to a schema parser, we need to remember
* which documents (of the forest) were given as the root
* documents, and which of them are read as included/imported
* documents.
*
* <p>
* Set of system ids as strings.
*/
private final Set<String> rootDocuments = new HashSet<String>();
/** Stores location information for all the trees in this forest. */
public final LocatorTable locatorTable = new LocatorTable();
/** Stores all the outer-most &lt;jaxb:bindings> customizations. */
public final Set<Element> outerMostBindings = new HashSet<Element>();
/** Used to resolve references to other schema documents. */
private EntityResolver entityResolver = null;
/** Errors encountered during the parsing will be sent to this object. */
private ErrorReceiver errorReceiver = null;
/** Schema language dependent part of the processing. */
protected final InternalizationLogic logic;
private final SAXParserFactory parserFactory;
private final DocumentBuilder documentBuilder;
private final Options options;
public DOMForest(
SAXParserFactory parserFactory, DocumentBuilder documentBuilder,
InternalizationLogic logic ) {
this.parserFactory = parserFactory;
this.documentBuilder = documentBuilder;
this.logic = logic;
this.options = null;
}
public DOMForest( InternalizationLogic logic, Options opt ) {
if (opt == null) throw new AssertionError("Options object null");
this.options = opt;
try {
DocumentBuilderFactory dbf = XmlFactory.createDocumentBuilderFactory(opt.disableXmlSecurity);
this.documentBuilder = dbf.newDocumentBuilder();
this.parserFactory = XmlFactory.createParserFactory(opt.disableXmlSecurity);
} catch( ParserConfigurationException e ) {
throw new AssertionError(e);
}
this.logic = logic;
}
/**
* Gets the DOM tree associated with the specified system ID,
* or null if none is found.
*/
public Document get( String systemId ) {
Document doc = core.get(systemId);
if( doc==null && systemId.startsWith("file:/") && !systemId.startsWith("file://") ) {
// As of JDK1.4, java.net.URL.toExternal method returns URLs like
// "file:/abc/def/ghi" which is an incorrect file protocol URL according to RFC1738.
// Some other correctly functioning parts return the correct URLs ("file:///abc/def/ghi"),
// and this descripancy breaks DOM look up by system ID.
// this extra check solves this problem.
doc = core.get( "file://"+systemId.substring(5) );
}
if( doc==null && systemId.startsWith("file:") ) {
// on Windows, filenames are case insensitive.
// perform case-insensitive search for improved user experience
String systemPath = getPath(systemId);
for (String key : core.keySet()) {
if(key.startsWith("file:") && getPath(key).equalsIgnoreCase(systemPath)) {
doc = core.get(key);
break;
}
}
}
return doc;
}
/**
* Strips off the leading 'file:///' portion from an URL.
*/
private String getPath(String key) {
key = key.substring(5); // skip 'file:'
while(key.length()>0 && key.charAt(0)=='/') {
key = key.substring(1);
}
return key;
}
/**
* Returns a read-only set of root document system IDs.
*/
public Set<String> getRootDocuments() {
return Collections.unmodifiableSet(rootDocuments);
}
/**
* Picks one document at random and returns it.
*/
public Document getOneDocument() {
for (Document dom : core.values()) {
if (!dom.getDocumentElement().getNamespaceURI().equals(Const.JAXB_NSURI))
return dom;
}
// we should have caught this error very early on
throw new AssertionError();
}
/**
* Checks the correctness of the XML Schema documents and return true
* if it's OK.
*
* <p>
* This method performs a weaker version of the tests where error messages
* are provided without line number information. So whenever possible
* use {@link SchemaConstraintChecker}.
*
* @see SchemaConstraintChecker
*/
public boolean checkSchemaCorrectness(ErrorReceiver errorHandler) {
try {
boolean disableXmlSecurity = false;
if (options != null) {
disableXmlSecurity = options.disableXmlSecurity;
}
SchemaFactory sf = XmlFactory.createSchemaFactory(W3C_XML_SCHEMA_NS_URI, disableXmlSecurity);
ErrorReceiverFilter filter = new ErrorReceiverFilter(errorHandler);
sf.setErrorHandler(filter);
Set<String> roots = getRootDocuments();
Source[] sources = new Source[roots.size()];
int i=0;
for (String root : roots) {
sources[i++] = new DOMSource(get(root),root);
}
sf.newSchema(sources);
return !filter.hadError();
} catch (SAXException e) {
// the errors should have been reported
return false;
}
}
/**
* Gets the system ID from which the given DOM is parsed.
* <p>
* Poor-man's base URI.
*/
public String getSystemId( Document dom ) {
for (Map.Entry<String,Document> e : core.entrySet()) {
if (e.getValue() == dom)
return e.getKey();
}
return null;
}
public Document parse( InputSource source, boolean root ) throws SAXException {
if( source.getSystemId()==null )
throw new IllegalArgumentException();
return parse( source.getSystemId(), source, root );
}
/**
* Parses an XML at the given location (
* and XMLs referenced by it) into DOM trees
* and stores them to this forest.
*
* @return the parsed DOM document object.
*/
public Document parse( String systemId, boolean root ) throws SAXException, IOException {
systemId = Options.normalizeSystemId(systemId);
if( core.containsKey(systemId) )
// this document has already been parsed. Just ignore.
return core.get(systemId);
InputSource is=null;
// allow entity resolver to find the actual byte stream.
if( entityResolver!=null )
is = entityResolver.resolveEntity(null,systemId);
if( is==null )
is = new InputSource(systemId);
// but we still use the original system Id as the key.
return parse( systemId, is, root );
}
/**
* Returns a {@link ContentHandler} to feed SAX events into.
*
* <p>
* The client of this class can feed SAX events into the handler
* to parse a document into this DOM forest.
*
* This version requires that the DOM object to be created and registered
* to the map beforehand.
*/
private ContentHandler getParserHandler( Document dom ) {
ContentHandler handler = new DOMBuilder(dom,locatorTable,outerMostBindings);
handler = new WhitespaceStripper(handler,errorReceiver,entityResolver);
handler = new VersionChecker(handler,errorReceiver,entityResolver);
// insert the reference finder so that
// included/imported schemas will be also parsed
XMLFilterImpl f = logic.createExternalReferenceFinder(this);
f.setContentHandler(handler);
if(errorReceiver!=null)
f.setErrorHandler(errorReceiver);
if(entityResolver!=null)
f.setEntityResolver(entityResolver);
return f;
}
public interface Handler extends ContentHandler {
/**
* Gets the DOM that was built.
*/
public Document getDocument();
}
private static abstract class HandlerImpl extends XMLFilterImpl implements Handler {
}
/**
* Returns a {@link ContentHandler} to feed SAX events into.
*
* <p>
* The client of this class can feed SAX events into the handler
* to parse a document into this DOM forest.
*/
public Handler getParserHandler( String systemId, boolean root ) {
final Document dom = documentBuilder.newDocument();
core.put( systemId, dom );
if(root)
rootDocuments.add(systemId);
ContentHandler handler = getParserHandler(dom);
// we will register the DOM to the map once the system ID becomes available.
// but the SAX allows the event source to not to provide that information,
// so be prepared for such case.
HandlerImpl x = new HandlerImpl() {
public Document getDocument() {
return dom;
}
};
x.setContentHandler(handler);
return x;
}
/**
* Parses the given document and add it to the DOM forest.
*
* @return
* null if there was a parse error. otherwise non-null.
*/
public Document parse( String systemId, InputSource inputSource, boolean root ) throws SAXException {
Document dom = documentBuilder.newDocument();
systemId = Options.normalizeSystemId(systemId);
// put into the map before growing a tree, to
// prevent recursive reference from causing infinite loop.
core.put( systemId, dom );
if(root)
rootDocuments.add(systemId);
try {
XMLReader reader = parserFactory.newSAXParser().getXMLReader();
reader.setContentHandler(getParserHandler(dom));
if(errorReceiver!=null)
reader.setErrorHandler(errorReceiver);
if(entityResolver!=null)
reader.setEntityResolver(entityResolver);
reader.parse(inputSource);
} catch( ParserConfigurationException e ) {
// in practice, this exception won't happen.
errorReceiver.error(e.getMessage(),e);
core.remove(systemId);
rootDocuments.remove(systemId);
return null;
} catch( IOException e ) {
errorReceiver.error(Messages.format(Messages.DOMFOREST_INPUTSOURCE_IOEXCEPTION, systemId, e.toString()),e);
core.remove(systemId);
rootDocuments.remove(systemId);
return null;
}
return dom;
}
public Document parse( String systemId, XMLStreamReader parser, boolean root ) throws XMLStreamException {
Document dom = documentBuilder.newDocument();
systemId = Options.normalizeSystemId(systemId);
if(root)
rootDocuments.add(systemId);
if(systemId==null)
throw new IllegalArgumentException("system id cannot be null");
core.put( systemId, dom );
new XMLStreamReaderToContentHandler(parser,getParserHandler(dom),false,false).bridge();
return dom;
}
/**
* Performs internalization.
*
* This method should be called only once, only after all the
* schemas are parsed.
*
* @return
* the returned bindings need to be applied after schema
* components are built.
*/
public SCDBasedBindingSet transform(boolean enableSCD) {
return Internalizer.transform(this, enableSCD, options.disableXmlSecurity);
}
/**
* Performs the schema correctness check by using JAXP 1.3.
*
* <p>
* This is "weak", because {@link SchemaFactory#newSchema(Source[])}
* doesn't handle inclusions very correctly (it ends up parsing it
* from its original source, not in this tree), and because
* it doesn't handle two documents for the same namespace very
* well.
*
* <p>
* We should eventually fix JAXP (and Xerces), but meanwhile
* this weaker and potentially wrong correctness check is still
* better than nothing when used inside JAX-WS (JAXB CLI and Ant
* does a better job of checking this.)
*
* <p>
* To receive errors, use {@link SchemaFactory#setErrorHandler(ErrorHandler)}.
*/
public void weakSchemaCorrectnessCheck(SchemaFactory sf) {
List<SAXSource> sources = new ArrayList<SAXSource>();
for( String systemId : getRootDocuments() ) {
Document dom = get(systemId);
if (dom.getDocumentElement().getNamespaceURI().equals(Const.JAXB_NSURI))
continue; // this isn't a schema. we have to do a negative check because if we see completely unrelated ns, we want to report that as an error
SAXSource ss = createSAXSource(systemId);
try {
ss.getXMLReader().setFeature("http://xml.org/sax/features/namespace-prefixes",true);
} catch (SAXException e) {
throw new AssertionError(e); // Xerces wants this. See 6395322.
}
sources.add(ss);
}
try {
allowExternalAccess(sf, "file,http", options.disableXmlSecurity).newSchema(sources.toArray(new SAXSource[0]));
} catch (SAXException e) {
// error should have been reported.
} catch (RuntimeException re) {
// JAXP RI isn't very trustworthy when it comes to schema error check,
// and we know some cases where it just dies with NPE. So handle it gracefully.
// this masks a bug in the JAXP RI, but we need a release that we have to make.
try {
sf.getErrorHandler().warning(
new SAXParseException(Messages.format(
Messages.ERR_GENERAL_SCHEMA_CORRECTNESS_ERROR,re.getMessage()),
null,null,-1,-1,re));
} catch (SAXException e) {
// ignore
}
}
}
/**
* Creates a {@link SAXSource} that, when parsed, reads from this {@link DOMForest}
* (instead of parsing the original source identified by the system ID.)
*/
public @NotNull SAXSource createSAXSource(String systemId) {
ContentHandlerNamespacePrefixAdapter reader = new ContentHandlerNamespacePrefixAdapter(new XMLFilterImpl() {
// XMLReader that uses XMLParser to parse. We need to use XMLFilter to indrect
// handlers, since SAX allows handlers to be changed while parsing.
@Override
public void parse(InputSource input) throws SAXException, IOException {
createParser().parse(input, this, this, this);
}
@Override
public void parse(String systemId) throws SAXException, IOException {
parse(new InputSource(systemId));
}
});
return new SAXSource(reader,new InputSource(systemId));
}
/**
* Creates {@link XMLParser} for XSOM which reads documents from
* this DOMForest rather than doing a fresh parse.
*
* The net effect is that XSOM will read transformed XML Schemas
* instead of the original documents.
*/
public XMLParser createParser() {
return new DOMForestParser(this, new JAXPParser(XmlFactory.createParserFactory(options.disableXmlSecurity)));
}
public EntityResolver getEntityResolver() {
return entityResolver;
}
public void setEntityResolver(EntityResolver entityResolver) {
this.entityResolver = entityResolver;
}
public ErrorReceiver getErrorHandler() {
return errorReceiver;
}
public void setErrorHandler(ErrorReceiver errorHandler) {
this.errorReceiver = errorHandler;
}
/**
* Gets all the parsed documents.
*/
public Document[] listDocuments() {
return core.values().toArray(new Document[core.size()]);
}
/**
* Gets all the system IDs of the documents.
*/
public String[] listSystemIDs() {
return core.keySet().toArray(new String[core.keySet().size()]);
}
/**
* Dumps the contents of the forest to the specified stream.
*
* This is a debug method. As such, error handling is sloppy.
*/
@SuppressWarnings("CallToThreadDumpStack")
public void dump( OutputStream out ) throws IOException {
try {
// create identity transformer
boolean disableXmlSecurity = false;
if (options != null) {
disableXmlSecurity = options.disableXmlSecurity;
}
TransformerFactory tf = XmlFactory.createTransformerFactory(disableXmlSecurity);
Transformer it = tf.newTransformer();
for (Map.Entry<String, Document> e : core.entrySet()) {
out.write( ("---<< "+e.getKey()+'\n').getBytes() );
DataWriter dw = new DataWriter(new OutputStreamWriter(out),null);
dw.setIndentStep(" ");
it.transform( new DOMSource(e.getValue()),
new SAXResult(dw));
out.write( "\n\n\n".getBytes() );
}
} catch( TransformerException e ) {
e.printStackTrace();
}
}
}

View File

@@ -0,0 +1,91 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.internalizer;
import java.io.IOException;
import com.sun.xml.internal.xsom.parser.XMLParser;
import org.w3c.dom.Document;
import org.xml.sax.ContentHandler;
import org.xml.sax.EntityResolver;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
/**
* {@link XMLParser} implementation that
* parses XML from a DOM forest instead of parsing it from
* its original location.
*
* @author
* Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
*/
class DOMForestParser implements XMLParser {
/** DOM forest to be "parsed". */
private final DOMForest forest;
/** Scanner object will do the actual SAX events generation. */
private final DOMForestScanner scanner;
private final XMLParser fallbackParser;
/**
* @param fallbackParser
* This parser will be used when DOMForestParser needs to parse
* documents that are not in the forest.
*/
DOMForestParser( DOMForest forest, XMLParser fallbackParser ) {
this.forest = forest;
this.scanner = new DOMForestScanner(forest);
this.fallbackParser = fallbackParser;
}
public void parse(
InputSource source,
ContentHandler contentHandler,
ErrorHandler errorHandler,
EntityResolver entityResolver )
throws SAXException, IOException {
String systemId = source.getSystemId();
Document dom = forest.get(systemId);
if(dom==null) {
// if no DOM tree is built for it,
// let the fall back parser parse the original document.
//
// for example, XSOM parses datatypes.xsd (XML Schema part 2)
// but this will never be built into the forest.
fallbackParser.parse( source, contentHandler, errorHandler, entityResolver );
return;
}
scanner.scan( dom, contentHandler );
}
}

View File

@@ -0,0 +1,177 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.internalizer;
import com.sun.xml.internal.bind.unmarshaller.DOMScanner;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.XMLFilterImpl;
/**
* Produces a complete series of SAX events from any DOM node
* in the DOMForest.
*
* <p>
* This class hides a logic of re-associating {@link Locator}
* to the generated SAX event stream.
*
* @author
* Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
*/
public class DOMForestScanner {
private final DOMForest forest;
/**
* Scans DOM nodes of the given forest.
*
* DOM node parameters to the scan method must be a part of
* this forest.
*/
public DOMForestScanner( DOMForest _forest ) {
this.forest = _forest;
}
/**
* Generates the whole set of SAX events by treating
* element e as if it's a root element.
*/
public void scan( Element e, ContentHandler contentHandler ) throws SAXException {
DOMScanner scanner = new DOMScanner();
// insert the location resolver into the pipe line
LocationResolver resolver = new LocationResolver(scanner);
resolver.setContentHandler(contentHandler);
// parse this DOM.
scanner.setContentHandler(resolver);
scanner.scan(e);
}
/**
* Generates the whole set of SAX events from the given Document
* in the DOMForest.
*/
public void scan( Document d, ContentHandler contentHandler ) throws SAXException {
scan( d.getDocumentElement(), contentHandler );
}
/**
* Intercepts the invocation of the setDocumentLocator method
* and passes itself as the locator.
*
* If the client calls one of the methods on the Locator interface,
* use the LocatorTable to resolve the source location.
*/
private class LocationResolver extends XMLFilterImpl implements Locator {
LocationResolver( DOMScanner _parent ) {
this.parent = _parent;
}
private final DOMScanner parent;
/**
* Flag that tells us whether we are processing a start element event
* or an end element event.
*
* DOMScanner's getCurrentLocation method doesn't tell us which, but
* this information is necessary to return the correct source line information.
*
* Thus we set this flag appropriately before we pass an event to
* the next ContentHandler, thereby making it possible to figure
* out which location to return.
*/
private boolean inStart = false;
@Override
public void setDocumentLocator(Locator locator) {
// ignore one set by the parent.
super.setDocumentLocator(this);
}
@Override
public void endElement(String namespaceURI, String localName, String qName) throws SAXException {
inStart = false;
super.endElement(namespaceURI, localName, qName);
}
@Override
public void startElement(String namespaceURI, String localName, String qName, Attributes atts)
throws SAXException {
inStart = true;
super.startElement(namespaceURI, localName, qName, atts);
}
private Locator findLocator() {
Node n = parent.getCurrentLocation();
if( n instanceof Element ) {
Element e = (Element)n;
if( inStart )
return forest.locatorTable.getStartLocation( e );
else
return forest.locatorTable.getEndLocation( e );
}
return null;
}
//
//
// Locator methods
//
//
public int getColumnNumber() {
Locator l = findLocator();
if(l!=null) return l.getColumnNumber();
return -1;
}
public int getLineNumber() {
Locator l = findLocator();
if(l!=null) return l.getLineNumber();
return -1;
}
public String getPublicId() {
Locator l = findLocator();
if(l!=null) return l.getPublicId();
return null;
}
public String getSystemId() {
Locator l = findLocator();
if(l!=null) return l.getSystemId();
return null;
}
}
}

View File

@@ -0,0 +1,94 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.internalizer;
import org.w3c.dom.Element;
import org.xml.sax.helpers.XMLFilterImpl;
/**
* Encapsulates schema-language dependent internalization logic.
*
* {@link Internalizer} and {@link DOMForest} are responsible for
* doing schema language independent part, and this object is responsible
* for schema language dependent part.
*
* @author
* Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
*/
public interface InternalizationLogic {
/**
* Creates a new instance of XMLFilter that can be used to
* find references to external schemas.
*
* <p>
* Schemas that are included/imported need to be a part of
* {@link DOMForest}, and this filter will be expected to
* find such references.
*
* <p>
* Once such a reference is found, the filter is expected to
* call the parse method of DOMForest.
*
* <p>
* {@link DOMForest} will register ErrorHandler to the returned
* object, so any error should be sent to that error handler.
*
* @return
* This method returns {@link XMLFilterImpl} because
* the filter has to be usable for two directions
* (wrapping a reader and wrapping a ContentHandler)
*/
XMLFilterImpl createExternalReferenceFinder( DOMForest parent );
/**
* Checks if the specified element is a valid target node
* to attach a customization.
*
* @param parent
* The owner DOMForest object. Probably useful only
* to obtain context information, such as error handler.
* @param bindings
* &lt;jaxb:bindings> element or a customization element.
* @return
* true if it's OK, false if not.
*/
boolean checkIfValidTargetNode( DOMForest parent, Element bindings, Element target );
/**
* Prepares an element that actually receives customizations.
*
* <p>
* For example, in XML Schema, target nodes can be any schema
* element but it is always the &lt;xsd:appinfo> element that
* receives customization.
*
* @param target
* The target node designated by the customization.
* @return
* Always return non-null valid object
*/
Element refineTarget( Element target );
}

View File

@@ -0,0 +1,615 @@
/*
* Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.internalizer;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.text.ParseException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import com.sun.istack.internal.SAXParseException2;
import com.sun.istack.internal.NotNull;
import com.sun.istack.internal.Nullable;
import com.sun.tools.internal.xjc.ErrorReceiver;
import com.sun.tools.internal.xjc.reader.Const;
import com.sun.tools.internal.xjc.util.DOMUtils;
import com.sun.xml.internal.bind.v2.util.EditDistance;
import com.sun.xml.internal.bind.v2.util.XmlFactory;
import com.sun.xml.internal.xsom.SCD;
import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.XMLConstants;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXParseException;
/**
* Internalizes external binding declarations.
*
* <p>
* The {@link #transform(DOMForest,boolean)} method is the entry point.
*
* @author
* Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
*/
class Internalizer {
private static final String WSDL_NS = "http://schemas.xmlsoap.org/wsdl/";
private final XPath xpath;
/**
* Internalize all &lt;jaxb:bindings> customizations in the given forest.
*
* @return
* if the SCD support is enabled, the return bindings need to be applied
* after schema components are parsed.
* If disabled, the returned binding set will be empty.
* SCDs are only for XML Schema, and doesn't make any sense for other
* schema languages.
*/
static SCDBasedBindingSet transform( DOMForest forest, boolean enableSCD, boolean disableSecureProcessing ) {
return new Internalizer(forest, enableSCD, disableSecureProcessing).transform();
}
private Internalizer(DOMForest forest, boolean enableSCD, boolean disableSecureProcessing) {
this.errorHandler = forest.getErrorHandler();
this.forest = forest;
this.enableSCD = enableSCD;
xpath = XmlFactory.createXPathFactory(disableSecureProcessing).newXPath();
}
/**
* DOMForest object currently being processed.
*/
private final DOMForest forest;
/**
* All errors found during the transformation is sent to this object.
*/
private ErrorReceiver errorHandler;
/**
* If true, the SCD-based target selection is supported.
*/
private boolean enableSCD;
private SCDBasedBindingSet transform() {
// either target nodes are conventional DOM nodes (as per spec),
Map<Element,List<Node>> targetNodes = new HashMap<Element,List<Node>>();
// ... or it will be schema components by means of SCD (RI extension)
SCDBasedBindingSet scd = new SCDBasedBindingSet(forest);
//
// identify target nodes for all <jaxb:bindings>
//
for (Element jaxbBindings : forest.outerMostBindings) {
// initially, the inherited context is itself
buildTargetNodeMap(jaxbBindings, jaxbBindings, null, targetNodes, scd);
}
//
// then move them to their respective positions.
//
for (Element jaxbBindings : forest.outerMostBindings) {
move(jaxbBindings, targetNodes);
}
return scd;
}
/**
* Validates attributes of a &lt;jaxb:bindings> element.
*/
private void validate( Element bindings ) {
NamedNodeMap atts = bindings.getAttributes();
for( int i=0; i<atts.getLength(); i++ ) {
Attr a = (Attr)atts.item(i);
if( a.getNamespaceURI()!=null )
continue; // all foreign namespace OK.
if( a.getLocalName().equals("node") )
continue;
if( a.getLocalName().equals("schemaLocation"))
continue;
if( a.getLocalName().equals("scd") )
continue;
// enhancements
if( a.getLocalName().equals("required") ) //
continue;
if( a.getLocalName().equals("multiple") ) //
continue;
// TODO: flag error for this undefined attribute
}
}
/**
* Determines the target node of the "bindings" element
* by using the inherited target node, then put
* the result into the "result" map and the "scd" map.
*
* @param inheritedTarget
* The current target node. This always exists, even if
* the user starts specifying targets via SCD (in that case
* this inherited target is just not going to be used.)
* @param inheritedSCD
* If the ancestor &lt;bindings> node specifies @scd to
* specify the target via SCD, then this parameter represents that context.
*/
private void buildTargetNodeMap( Element bindings, @NotNull Node inheritedTarget,
@Nullable SCDBasedBindingSet.Target inheritedSCD,
Map<Element,List<Node>> result, SCDBasedBindingSet scdResult ) {
// start by the inherited target
Node target = inheritedTarget;
ArrayList<Node> targetMultiple = null;
validate(bindings); // validate this node
boolean required = true;
boolean multiple = false;
if(bindings.getAttribute("required") != null) {
String requiredAttr = bindings.getAttribute("required");
if(requiredAttr.equals("no") || requiredAttr.equals("false") || requiredAttr.equals("0"))
required = false;
}
if(bindings.getAttribute("multiple") != null) {
String requiredAttr = bindings.getAttribute("multiple");
if(requiredAttr.equals("yes") || requiredAttr.equals("true") || requiredAttr.equals("1"))
multiple = true;
}
// look for @schemaLocation
if( bindings.getAttributeNode("schemaLocation")!=null ) {
String schemaLocation = bindings.getAttribute("schemaLocation");
// enhancement - schemaLocation="*" = bind to all schemas..
if(schemaLocation.equals("*")) {
for(String systemId : forest.listSystemIDs()) {
if (result.get(bindings) == null)
result.put(bindings, new ArrayList<Node>());
result.get(bindings).add(forest.get(systemId).getDocumentElement());
Element[] children = DOMUtils.getChildElements(bindings, Const.JAXB_NSURI, "bindings");
for (Element value : children)
buildTargetNodeMap(value, forest.get(systemId).getDocumentElement(), inheritedSCD, result, scdResult);
}
return;
} else {
try {
// TODO: use the URI class
// TODO: honor xml:base
URL loc = new URL(
new URL(forest.getSystemId(bindings.getOwnerDocument())), schemaLocation
);
schemaLocation = loc.toExternalForm();
target = forest.get(schemaLocation);
if ((target == null) && (loc.getProtocol().startsWith("file"))) {
File f = new File(loc.getFile());
schemaLocation = new File(f.getCanonicalPath()).toURI().toString();
}
} catch( MalformedURLException e ) {
} catch( IOException e ) {
Logger.getLogger(Internalizer.class.getName()).log(Level.FINEST, e.getLocalizedMessage());
}
target = forest.get(schemaLocation);
if(target==null) {
reportError( bindings,
Messages.format(Messages.ERR_INCORRECT_SCHEMA_REFERENCE,
schemaLocation,
EditDistance.findNearest(schemaLocation,forest.listSystemIDs())));
return; // abort processing this <jaxb:bindings>
}
target = ((Document)target).getDocumentElement();
}
}
// look for @node
if( bindings.getAttributeNode("node")!=null ) {
String nodeXPath = bindings.getAttribute("node");
// evaluate this XPath
NodeList nlst;
try {
xpath.setNamespaceContext(new NamespaceContextImpl(bindings));
nlst = (NodeList)xpath.evaluate(nodeXPath,target,XPathConstants.NODESET);
} catch (XPathExpressionException e) {
if(required) {
reportError( bindings,
Messages.format(Messages.ERR_XPATH_EVAL,e.getMessage()), e );
return; // abort processing this <jaxb:bindings>
} else {
return;
}
}
if( nlst.getLength()==0 ) {
if(required)
reportError( bindings,
Messages.format(Messages.NO_XPATH_EVAL_TO_NO_TARGET, nodeXPath) );
return; // abort
}
if( nlst.getLength()!=1 ) {
if(!multiple) {
reportError( bindings,
Messages.format(Messages.NO_XPATH_EVAL_TOO_MANY_TARGETS, nodeXPath,nlst.getLength()) );
return; // abort
} else {
if(targetMultiple == null) targetMultiple = new ArrayList<Node>();
for(int i = 0; i < nlst.getLength(); i++) {
targetMultiple.add(nlst.item(i));
}
}
}
// check
if(!multiple || nlst.getLength() == 1) {
Node rnode = nlst.item(0);
if (!(rnode instanceof Element)) {
reportError(bindings,
Messages.format(Messages.NO_XPATH_EVAL_TO_NON_ELEMENT, nodeXPath));
return; // abort
}
if (!forest.logic.checkIfValidTargetNode(forest, bindings, (Element) rnode)) {
reportError(bindings,
Messages.format(Messages.XPATH_EVAL_TO_NON_SCHEMA_ELEMENT,
nodeXPath, rnode.getNodeName()));
return; // abort
}
target = rnode;
} else {
for(Node rnode : targetMultiple) {
if (!(rnode instanceof Element)) {
reportError(bindings,
Messages.format(Messages.NO_XPATH_EVAL_TO_NON_ELEMENT, nodeXPath));
return; // abort
}
if (!forest.logic.checkIfValidTargetNode(forest, bindings, (Element) rnode)) {
reportError(bindings,
Messages.format(Messages.XPATH_EVAL_TO_NON_SCHEMA_ELEMENT,
nodeXPath, rnode.getNodeName()));
return; // abort
}
}
}
}
// look for @scd
if( bindings.getAttributeNode("scd")!=null ) {
String scdPath = bindings.getAttribute("scd");
if(!enableSCD) {
// SCD selector was found, but it's not activated. report an error
// but recover by handling it anyway. this also avoids repeated error messages.
reportError(bindings,
Messages.format(Messages.SCD_NOT_ENABLED));
enableSCD = true;
}
try {
inheritedSCD = scdResult.createNewTarget( inheritedSCD, bindings,
SCD.create(scdPath, new NamespaceContextImpl(bindings)) );
} catch (ParseException e) {
reportError( bindings, Messages.format(Messages.ERR_SCD_EVAL,e.getMessage()),e );
return; // abort processing this bindings
}
}
// update the result map
if (inheritedSCD != null) {
inheritedSCD.addBinidng(bindings);
} else if (!multiple || targetMultiple == null) {
if (result.get(bindings) == null)
result.put(bindings, new ArrayList<Node>());
result.get(bindings).add(target);
} else {
for (Node rnode : targetMultiple) {
if (result.get(bindings) == null)
result.put(bindings, new ArrayList<Node>());
result.get(bindings).add(rnode);
}
}
// look for child <jaxb:bindings> and process them recursively
Element[] children = DOMUtils.getChildElements( bindings, Const.JAXB_NSURI, "bindings" );
for (Element value : children)
if(!multiple || targetMultiple == null)
buildTargetNodeMap(value, target, inheritedSCD, result, scdResult);
else {
for(Node rnode : targetMultiple) {
buildTargetNodeMap(value, rnode, inheritedSCD, result, scdResult);
}
}
}
/**
* Moves JAXB customizations under their respective target nodes.
*/
private void move(Element bindings, Map<Element, List<Node>> targetNodes) {
List<Node> nodelist = targetNodes.get(bindings);
if(nodelist == null) {
return; // abort
}
for (Node target : nodelist) {
if (target == null) // this must be the result of an error on the external binding.
// recover from the error by ignoring this node
{
return;
}
for (Element item : DOMUtils.getChildElements(bindings)) {
String localName = item.getLocalName();
if ("bindings".equals(localName)) {
// process child <jaxb:bindings> recursively
move(item, targetNodes);
} else if ("globalBindings".equals(localName)) {
// <jaxb:globalBindings> always go to the root of document.
Element root = forest.getOneDocument().getDocumentElement();
if (root.getNamespaceURI().equals(WSDL_NS)) {
NodeList elements = root.getElementsByTagNameNS(XMLConstants.W3C_XML_SCHEMA_NS_URI, "schema");
if ((elements == null) || (elements.getLength() < 1)) {
reportError(item, Messages.format(Messages.ORPHANED_CUSTOMIZATION, item.getNodeName()));
return;
} else {
moveUnder(item, (Element)elements.item(0));
}
} else {
moveUnder(item, root);
}
} else {
if (!(target instanceof Element)) {
reportError(item,
Messages.format(Messages.CONTEXT_NODE_IS_NOT_ELEMENT));
return; // abort
}
if (!forest.logic.checkIfValidTargetNode(forest, item, (Element) target)) {
reportError(item,
Messages.format(Messages.ORPHANED_CUSTOMIZATION, item.getNodeName()));
return; // abort
}
// move this node under the target
moveUnder(item, (Element) target);
}
}
}
}
/**
* Moves the "decl" node under the "target" node.
*
* @param decl
* A JAXB customization element (e.g., &lt;jaxb:class>)
*
* @param target
* XML Schema element under which the declaration should move.
* For example, &lt;xs:element>
*/
private void moveUnder( Element decl, Element target ) {
Element realTarget = forest.logic.refineTarget(target);
declExtensionNamespace( decl, target );
// copy in-scope namespace declarations of the decl node
// to the decl node itself so that this move won't change
// the in-scope namespace bindings.
Element p = decl;
Set<String> inscopes = new HashSet<String>();
while(true) {
NamedNodeMap atts = p.getAttributes();
for( int i=0; i<atts.getLength(); i++ ) {
Attr a = (Attr)atts.item(i);
if( Const.XMLNS_URI.equals(a.getNamespaceURI()) ) {
String prefix;
if( a.getName().indexOf(':')==-1 ) prefix = "";
else prefix = a.getLocalName();
if( inscopes.add(prefix) && p!=decl ) {
// if this is the first time we see this namespace bindings,
// copy the declaration.
// if p==decl, there's no need to. Note that
// we want to add prefix to inscopes even if p==Decl
decl.setAttributeNodeNS( (Attr)a.cloneNode(true) );
}
}
}
if( p.getParentNode() instanceof Document )
break;
p = (Element)p.getParentNode();
}
if( !inscopes.contains("") ) {
// if the default namespace was undeclared in the context of decl,
// it must be explicitly set to "" since the new environment might
// have a different default namespace URI.
decl.setAttributeNS(Const.XMLNS_URI,"xmlns","");
}
// finally move the declaration to the target node.
if( realTarget.getOwnerDocument()!=decl.getOwnerDocument() ) {
// if they belong to different DOM documents, we need to clone them
Element original = decl;
decl = (Element)realTarget.getOwnerDocument().importNode(decl,true);
// this effectively clones a ndoe,, so we need to copy locators.
copyLocators( original, decl );
}
realTarget.appendChild( decl );
}
/**
* Recursively visits sub-elements and declare all used namespaces.
* TODO: the fact that we recognize all namespaces in the extension
* is a bad design.
*/
private void declExtensionNamespace(Element decl, Element target) {
// if this comes from external namespaces, add the namespace to
// @extensionBindingPrefixes.
if( !Const.JAXB_NSURI.equals(decl.getNamespaceURI()) )
declareExtensionNamespace( target, decl.getNamespaceURI() );
NodeList lst = decl.getChildNodes();
for( int i=0; i<lst.getLength(); i++ ) {
Node n = lst.item(i);
if( n instanceof Element )
declExtensionNamespace( (Element)n, target );
}
}
/** Attribute name. */
private static final String EXTENSION_PREFIXES = "extensionBindingPrefixes";
/**
* Adds the specified namespace URI to the jaxb:extensionBindingPrefixes
* attribute of the target document.
*/
private void declareExtensionNamespace( Element target, String nsUri ) {
// look for the attribute
Element root = target.getOwnerDocument().getDocumentElement();
Attr att = root.getAttributeNodeNS(Const.JAXB_NSURI,EXTENSION_PREFIXES);
if( att==null ) {
String jaxbPrefix = allocatePrefix(root,Const.JAXB_NSURI);
// no such attribute. Create one.
att = target.getOwnerDocument().createAttributeNS(
Const.JAXB_NSURI,jaxbPrefix+':'+EXTENSION_PREFIXES);
root.setAttributeNodeNS(att);
}
String prefix = allocatePrefix(root,nsUri);
if( att.getValue().indexOf(prefix)==-1 )
// avoid redeclaring the same namespace twice.
att.setValue( att.getValue()+' '+prefix);
}
/**
* Declares a new prefix on the given element and associates it
* with the specified namespace URI.
* <p>
* Note that this method doesn't use the default namespace
* even if it can.
*/
private String allocatePrefix( Element e, String nsUri ) {
// look for existing namespaces.
NamedNodeMap atts = e.getAttributes();
for( int i=0; i<atts.getLength(); i++ ) {
Attr a = (Attr)atts.item(i);
if( Const.XMLNS_URI.equals(a.getNamespaceURI()) ) {
if( a.getName().indexOf(':')==-1 ) continue;
if( a.getValue().equals(nsUri) )
return a.getLocalName(); // found one
}
}
// none found. allocate new.
while(true) {
String prefix = "p"+(int)(Math.random()*1000000)+'_';
if(e.getAttributeNodeNS(Const.XMLNS_URI,prefix)!=null)
continue; // this prefix is already allocated.
e.setAttributeNS(Const.XMLNS_URI,"xmlns:"+prefix,nsUri);
return prefix;
}
}
/**
* Copies location information attached to the "src" node to the "dst" node.
*/
private void copyLocators( Element src, Element dst ) {
forest.locatorTable.storeStartLocation(
dst, forest.locatorTable.getStartLocation(src) );
forest.locatorTable.storeEndLocation(
dst, forest.locatorTable.getEndLocation(src) );
// recursively process child elements
Element[] srcChilds = DOMUtils.getChildElements(src);
Element[] dstChilds = DOMUtils.getChildElements(dst);
for( int i=0; i<srcChilds.length; i++ )
copyLocators( srcChilds[i], dstChilds[i] );
}
private void reportError( Element errorSource, String formattedMsg ) {
reportError( errorSource, formattedMsg, null );
}
private void reportError( Element errorSource,
String formattedMsg, Exception nestedException ) {
SAXParseException e = new SAXParseException2( formattedMsg,
forest.locatorTable.getStartLocation(errorSource),
nestedException );
errorHandler.error(e);
}
}

View File

@@ -0,0 +1,63 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.internalizer;
import java.util.HashMap;
import java.util.Map;
import org.w3c.dom.Element;
import org.xml.sax.Locator;
import org.xml.sax.helpers.LocatorImpl;
/**
* Stores {@link Locator} objects for every {@link Element}.
*
* @author
* Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
*/
public final class LocatorTable {
/** Locations of the start element. */
private final Map startLocations = new HashMap();
/** Locations of the end element. */
private final Map endLocations = new HashMap();
public void storeStartLocation( Element e, Locator loc ) {
startLocations.put(e,new LocatorImpl(loc));
}
public void storeEndLocation( Element e, Locator loc ) {
endLocations.put(e,new LocatorImpl(loc));
}
public Locator getStartLocation( Element e ) {
return (Locator)startLocations.get(e);
}
public Locator getEndLocation( Element e ) {
return (Locator)endLocations.get(e);
}
}

View File

@@ -0,0 +1,85 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.internalizer;
import java.text.MessageFormat;
import java.util.ResourceBundle;
/**
* Formats error messages.
*/
class Messages
{
/** Loads a string resource and formats it with specified arguments. */
static String format( String property, Object... args ) {
String text = ResourceBundle.getBundle(Messages.class.getPackage().getName() +".MessageBundle").getString(property);
return MessageFormat.format(text,args);
}
static final String ERR_INCORRECT_SCHEMA_REFERENCE = // args:2
"Internalizer.IncorrectSchemaReference";
static final String ERR_XPATH_EVAL = // arg:1
"Internalizer.XPathEvaluationError";
static final String NO_XPATH_EVAL_TO_NO_TARGET = // arg:1
"Internalizer.XPathEvaluatesToNoTarget";
static final String NO_XPATH_EVAL_TOO_MANY_TARGETS = // arg:2
"Internalizer.XPathEvaulatesToTooManyTargets";
static final String NO_XPATH_EVAL_TO_NON_ELEMENT = // arg:1
"Internalizer.XPathEvaluatesToNonElement";
static final String XPATH_EVAL_TO_NON_SCHEMA_ELEMENT = // arg:2
"Internalizer.XPathEvaluatesToNonSchemaElement";
static final String SCD_NOT_ENABLED = // arg:0
"SCD_NOT_ENABLED";
static final String ERR_SCD_EVAL = // arg: 1
"ERR_SCD_EVAL";
static final String ERR_SCD_EVALUATED_EMPTY = // arg:1
"ERR_SCD_EVALUATED_EMPTY";
static final String ERR_SCD_MATCHED_MULTIPLE_NODES = // arg:2
"ERR_SCD_MATCHED_MULTIPLE_NODES";
static final String ERR_SCD_MATCHED_MULTIPLE_NODES_FIRST = // arg:1
"ERR_SCD_MATCHED_MULTIPLE_NODES_FIRST";
static final String ERR_SCD_MATCHED_MULTIPLE_NODES_SECOND = // arg:1
"ERR_SCD_MATCHED_MULTIPLE_NODES_SECOND";
static final String CONTEXT_NODE_IS_NOT_ELEMENT = // arg:0
"Internalizer.ContextNodeIsNotElement";
static final String ERR_INCORRECT_VERSION = // arg:0
"Internalizer.IncorrectVersion";
static final String ERR_VERSION_NOT_FOUND = // arg:0
"Internalizer.VersionNotPresent";
static final String TWO_VERSION_ATTRIBUTES = // arg:0
"Internalizer.TwoVersionAttributes";
static final String ORPHANED_CUSTOMIZATION = // arg:1
"Internalizer.OrphanedCustomization";
static final String ERR_UNABLE_TO_PARSE = // arg:2
"AbstractReferenceFinderImpl.UnableToParse";
static final String ERR_FILENAME_IS_NOT_URI = // arg:0
"ERR_FILENAME_IS_NOT_URI";
static final String ERR_GENERAL_SCHEMA_CORRECTNESS_ERROR = // arg:1
"ERR_GENERAL_SCHEMA_CORRECTNESS_ERROR";
static final String DOMFOREST_INPUTSOURCE_IOEXCEPTION = // arg:2
"DOMFOREST_INPUTSOURCE_IOEXCEPTION";
}

View File

@@ -0,0 +1,106 @@
/*
* reserved comment block
* DO NOT REMOVE OR ALTER!
*/
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
* THIS FILE WAS MODIFIED BY SUN MICROSYSTEMS, INC.
*/
package com.sun.tools.internal.xjc.reader.internalizer;
import java.util.Iterator;
import javax.xml.XMLConstants;
import javax.xml.namespace.NamespaceContext;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
/**
* Implements {@link NamespaceContext} by looking at the in-scope
* namespace binding of a DOM element.
*
* @author Kohsuke Kawaguchi
*/
final class NamespaceContextImpl implements NamespaceContext {
private final Element e;
public NamespaceContextImpl(Element e) {
this.e = e;
}
public String getNamespaceURI(String prefix) {
Node parent = e;
String namespace = null;
final String prefixColon = prefix + ':';
if (prefix.equals("xml")) {
namespace = XMLConstants.XML_NS_URI;
} else {
int type;
while ((null != parent) && (null == namespace)
&& (((type = parent.getNodeType()) == Node.ELEMENT_NODE)
|| (type == Node.ENTITY_REFERENCE_NODE))) {
if (type == Node.ELEMENT_NODE) {
if (parent.getNodeName().startsWith(prefixColon))
return parent.getNamespaceURI();
NamedNodeMap nnm = parent.getAttributes();
for (int i = 0; i < nnm.getLength(); i++) {
Node attr = nnm.item(i);
String aname = attr.getNodeName();
boolean isPrefix = aname.startsWith("xmlns:");
if (isPrefix || aname.equals("xmlns")) {
int index = aname.indexOf(':');
String p = isPrefix ? aname.substring(index + 1) : "";
if (p.equals(prefix)) {
namespace = attr.getNodeValue();
break;
}
}
}
}
parent = parent.getParentNode();
}
}
if(prefix.equals(""))
return ""; // default namespace
return namespace;
}
public String getPrefix(String namespaceURI) {
throw new UnsupportedOperationException();
}
public Iterator getPrefixes(String namespaceURI) {
throw new UnsupportedOperationException();
}
}

View File

@@ -0,0 +1,246 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.internalizer;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.UnmarshallerHandler;
import javax.xml.validation.ValidatorHandler;
import com.sun.istack.internal.NotNull;
import com.sun.istack.internal.SAXParseException2;
import com.sun.tools.internal.xjc.ErrorReceiver;
import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIDeclaration;
import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BindInfo;
import com.sun.tools.internal.xjc.util.ForkContentHandler;
import com.sun.tools.internal.xjc.util.DOMUtils;
import com.sun.xml.internal.xsom.SCD;
import com.sun.xml.internal.xsom.XSAnnotation;
import com.sun.xml.internal.xsom.XSComponent;
import com.sun.xml.internal.xsom.XSSchemaSet;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
/**
* Set of binding nodes that have target nodes specified via SCD.
*
* This is parsed during {@link Internalizer} works on the tree,
* but applying this has to wait for {@link XSSchemaSet} to be parsed.
*
* @author Kohsuke Kawaguchi
* @see SCD
*/
public final class SCDBasedBindingSet {
/**
* Represents the target schema component of the
* customization identified by SCD.
*
* @author Kohsuke Kawaguchi
*/
final class Target {
/**
* SCDs can be specified via multiple steps, like:
*
* <xmp>
* <bindings scd="foo/bar">
* <bindings scd="zot/xyz">
* </xmp>
*
* This field and {@link #nextSibling} form a single-linked list that
* represent the children that shall be evaluated within this target.
* Think of it as {@code List<Target>}.
*/
private Target firstChild;
private final Target nextSibling;
/**
* Compiled SCD.
*/
private final @NotNull SCD scd;
/**
* The element on which SCD was found.
*/
private final @NotNull Element src;
/**
* Bindings that apply to this SCD.
*/
private final List<Element> bindings = new ArrayList<Element>();
private Target(Target parent, Element src, SCD scd) {
if(parent==null) {
this.nextSibling = topLevel;
topLevel = this;
} else {
this.nextSibling = parent.firstChild;
parent.firstChild = this;
}
this.src = src;
this.scd = scd;
}
/**
* Adds a new binding declaration to be associated to the schema component
* identified by {@link #scd}.
*/
void addBinidng(Element binding) {
bindings.add(binding);
}
/**
* Applies bindings to the schema component for this and its siblings.
*/
private void applyAll(Collection<? extends XSComponent> contextNode) {
for( Target self=this; self!=null; self=self.nextSibling )
self.apply(contextNode);
}
/**
* Applies bindings to the schema component for just this node.
*/
private void apply(Collection<? extends XSComponent> contextNode) {
// apply the SCD...
Collection<XSComponent> childNodes = scd.select(contextNode);
if(childNodes.isEmpty()) {
// no node matched
if(src.getAttributeNode("if-exists")!=null) {
// if this attribute exists, it's not an error if SCD didn't match.
return;
}
reportError( src, Messages.format(Messages.ERR_SCD_EVALUATED_EMPTY,scd) );
return;
}
if(firstChild!=null)
firstChild.applyAll(childNodes);
if(!bindings.isEmpty()) {
// error to match more than one components
Iterator<XSComponent> itr = childNodes.iterator();
XSComponent target = itr.next();
if(itr.hasNext()) {
reportError( src, Messages.format(Messages.ERR_SCD_MATCHED_MULTIPLE_NODES,scd,childNodes.size()) );
errorReceiver.error( target.getLocator(), Messages.format(Messages.ERR_SCD_MATCHED_MULTIPLE_NODES_FIRST) );
errorReceiver.error( itr.next().getLocator(), Messages.format(Messages.ERR_SCD_MATCHED_MULTIPLE_NODES_SECOND) );
}
// apply bindings to the target
for (Element binding : bindings) {
for (Element item : DOMUtils.getChildElements(binding)) {
String localName = item.getLocalName();
if ("bindings".equals(localName))
continue; // this should be already in Target.bindings of some SpecVersion.
try {
new DOMForestScanner(forest).scan(item,loader);
BIDeclaration decl = (BIDeclaration)unmarshaller.getResult();
// add this binding to the target
XSAnnotation ann = target.getAnnotation(true);
BindInfo bi = (BindInfo)ann.getAnnotation();
if(bi==null) {
bi = new BindInfo();
ann.setAnnotation(bi);
}
bi.addDecl(decl);
} catch (SAXException e) {
// the error should have already been reported.
} catch (JAXBException e) {
// if validation didn't fail, then unmarshalling can't go wrong
throw new AssertionError(e);
}
}
}
}
}
}
private Target topLevel;
/**
* The forest where binding elements came from. Needed to report line numbers for errors.
*/
private final DOMForest forest;
// variables used only during the apply method
//
private ErrorReceiver errorReceiver;
private UnmarshallerHandler unmarshaller;
private ForkContentHandler loader; // unmarshaller+validator
SCDBasedBindingSet(DOMForest forest) {
this.forest = forest;
}
Target createNewTarget(Target parent, Element src, SCD scd) {
return new Target(parent,src,scd);
}
/**
* Applies the additional binding customizations.
*/
public void apply(XSSchemaSet schema, ErrorReceiver errorReceiver) {
if(topLevel!=null) {
this.errorReceiver = errorReceiver;
Unmarshaller u = BindInfo.getCustomizationUnmarshaller();
this.unmarshaller = u.getUnmarshallerHandler();
ValidatorHandler v = BindInfo.bindingFileSchema.newValidator();
v.setErrorHandler(errorReceiver);
loader = new ForkContentHandler(v,unmarshaller);
topLevel.applyAll(schema.getSchemas());
this.loader = null;
this.unmarshaller = null;
this.errorReceiver = null;
}
}
private void reportError( Element errorSource, String formattedMsg ) {
reportError( errorSource, formattedMsg, null );
}
private void reportError( Element errorSource,
String formattedMsg, Exception nestedException ) {
SAXParseException e = new SAXParseException2( formattedMsg,
forest.locatorTable.getStartLocation(errorSource),
nestedException );
errorReceiver.error(e);
}
}

View File

@@ -0,0 +1,139 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.internalizer;
import java.util.Set;
import java.util.HashSet;
import java.util.Arrays;
import com.sun.tools.internal.xjc.reader.Const;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.EntityResolver;
import org.xml.sax.ErrorHandler;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.LocatorImpl;
import org.xml.sax.helpers.XMLFilterImpl;
/**
* Checks the jaxb:version attribute on a XML Schema document.
*
* jaxb:version is optional if no binding customization is used,
* but if present, its value must be "1.0".
*
* @author
* Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
*/
public class VersionChecker extends XMLFilterImpl {
/**
* We store the value of the version attribute in this variable
* when we hit the root element.
*/
private String version = null ;
/** Will be set to true once we hit the root element. */
private boolean seenRoot = false;
/** Will be set to true once we hit a binding declaration. */
private boolean seenBindings = false;
private Locator locator;
/**
* Stores the location of the start tag of the root tag.
*/
private Locator rootTagStart;
public VersionChecker( XMLReader parent ) {
setParent(parent);
}
public VersionChecker( ContentHandler handler,ErrorHandler eh,EntityResolver er ) {
setContentHandler(handler);
if(eh!=null) setErrorHandler(eh);
if(er!=null) setEntityResolver(er);
}
public void startElement(String namespaceURI, String localName, String qName, Attributes atts)
throws SAXException {
super.startElement(namespaceURI, localName, qName, atts);
if(!seenRoot) {
// if this is the root element
seenRoot = true;
rootTagStart = new LocatorImpl(locator);
version = atts.getValue(Const.JAXB_NSURI,"version");
if( namespaceURI.equals(Const.JAXB_NSURI) ) {
String version2 = atts.getValue("","version");
if( version!=null && version2!=null ) {
// we have both @version and @jaxb:version. error.
SAXParseException e = new SAXParseException(
Messages.format( Messages.TWO_VERSION_ATTRIBUTES ), locator );
getErrorHandler().error(e);
}
if( version==null )
version = version2;
}
}
if( Const.JAXB_NSURI.equals(namespaceURI) )
seenBindings = true;
}
public void endDocument() throws SAXException {
super.endDocument();
if( seenBindings && version==null ) {
// if we see a binding declaration but not version attribute
SAXParseException e = new SAXParseException(
Messages.format(Messages.ERR_VERSION_NOT_FOUND),rootTagStart);
getErrorHandler().error(e);
}
// if present, the value must be either 1.0 or 2.0
if( version!=null && !VERSIONS.contains(version) ) {
SAXParseException e = new SAXParseException(
Messages.format(Messages.ERR_INCORRECT_VERSION),rootTagStart);
getErrorHandler().error(e);
}
}
public void setDocumentLocator(Locator locator) {
super.setDocumentLocator(locator);
this.locator = locator;
}
private static final Set<String> VERSIONS = new HashSet<String>(Arrays.asList("1.0","2.0","2.1"));
}

View File

@@ -0,0 +1,127 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.internalizer;
import com.sun.xml.internal.bind.WhiteSpaceProcessor;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.EntityResolver;
import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.XMLFilterImpl;
/**
* Strips ignorable whitespace from SAX event stream.
*
* <p>
* This filter works only when the event stream doesn't
* contain any mixed content.
*
* @author
* Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
*/
class WhitespaceStripper extends XMLFilterImpl {
private int state = 0;
private char[] buf = new char[1024];
private int bufLen = 0;
private static final int AFTER_START_ELEMENT = 1;
private static final int AFTER_END_ELEMENT = 2;
public WhitespaceStripper(XMLReader reader) {
setParent(reader);
}
public WhitespaceStripper(ContentHandler handler,ErrorHandler eh,EntityResolver er) {
setContentHandler(handler);
if(eh!=null) setErrorHandler(eh);
if(er!=null) setEntityResolver(er);
}
public void characters(char[] ch, int start, int length) throws SAXException {
switch(state) {
case AFTER_START_ELEMENT:
// we have to store the characters here, even if it consists entirely
// of whitespaces. This is because successive characters event might
// include non-whitespace char, in which case all the whitespaces in
// this event may suddenly become significant.
if( bufLen+length>buf.length ) {
// reallocate buffer
char[] newBuf = new char[Math.max(bufLen+length,buf.length*2)];
System.arraycopy(buf,0,newBuf,0,bufLen);
buf = newBuf;
}
System.arraycopy(ch,start,buf,bufLen,length);
bufLen += length;
break;
case AFTER_END_ELEMENT:
// check if this is ignorable.
int len = start+length;
for( int i=start; i<len; i++ )
if( !WhiteSpaceProcessor.isWhiteSpace(ch[i]) ) {
super.characters(ch, start, length);
return;
}
// if it's entirely whitespace, ignore it.
break;
}
}
public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {
processPendingText();
super.startElement(uri, localName, qName, atts);
state = AFTER_START_ELEMENT;
bufLen = 0;
}
public void endElement(String uri, String localName, String qName) throws SAXException {
processPendingText();
super.endElement(uri, localName, qName);
state = AFTER_END_ELEMENT;
}
/**
* Forwars the buffered characters if it contains any non-whitespace
* character.
*/
private void processPendingText() throws SAXException {
if(state==AFTER_START_ELEMENT) {
for( int i=bufLen-1; i>=0; i-- )
if( !WhiteSpaceProcessor.isWhiteSpace(buf[i]) ) {
super.characters(buf, 0, bufLen);
return;
}
}
}
public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException {
// ignore completely.
}
}

View File

@@ -0,0 +1,33 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.relaxng;
/**
* @author Kohsuke Kawaguchi
*/
enum BindStyle {
TYPE, ELEMENT
}

View File

@@ -0,0 +1,130 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.relaxng;
import javax.xml.namespace.QName;
import com.sun.tools.internal.xjc.model.CAttributePropertyInfo;
import com.sun.tools.internal.xjc.model.CClassInfo;
import com.sun.tools.internal.xjc.model.CElementPropertyInfo;
import com.sun.tools.internal.xjc.model.CReferencePropertyInfo;
import com.sun.tools.internal.xjc.model.Multiplicity;
import com.sun.tools.internal.xjc.reader.RawTypeSet;
import com.sun.xml.internal.bind.v2.model.core.ID;
import com.sun.xml.internal.rngom.digested.DAttributePattern;
import com.sun.xml.internal.rngom.digested.DChoicePattern;
import com.sun.xml.internal.rngom.digested.DMixedPattern;
import com.sun.xml.internal.rngom.digested.DOneOrMorePattern;
import com.sun.xml.internal.rngom.digested.DOptionalPattern;
import com.sun.xml.internal.rngom.digested.DPattern;
import com.sun.xml.internal.rngom.digested.DPatternWalker;
import com.sun.xml.internal.rngom.digested.DZeroOrMorePattern;
import static com.sun.tools.internal.xjc.model.CElementPropertyInfo.CollectionMode.REPEATED_ELEMENT;
/**
* Recursively visits {@link DPattern} and
* decides which patterns to map to properties.
*
* @author Kohsuke Kawaguchi
*/
final class ContentModelBinder extends DPatternWalker {
private final RELAXNGCompiler compiler;
private final CClassInfo clazz;
private boolean insideOptional = false;
private int iota=1;
public ContentModelBinder(RELAXNGCompiler compiler,CClassInfo clazz) {
this.compiler = compiler;
this.clazz = clazz;
}
public Void onMixed(DMixedPattern p) {
throw new UnsupportedOperationException();
}
public Void onChoice(DChoicePattern p) {
boolean old = insideOptional;
insideOptional = true;
super.onChoice(p);
insideOptional = old;
return null;
}
public Void onOptional(DOptionalPattern p) {
boolean old = insideOptional;
insideOptional = true;
super.onOptional(p);
insideOptional = old;
return null;
}
public Void onZeroOrMore(DZeroOrMorePattern p) {
return onRepeated(p,true);
}
public Void onOneOrMore(DOneOrMorePattern p) {
return onRepeated(p,insideOptional);
}
private Void onRepeated(DPattern p,boolean optional) {
RawTypeSet rts = RawTypeSetBuilder.build(compiler, p, optional? Multiplicity.STAR : Multiplicity.PLUS);
if(rts.canBeTypeRefs==RawTypeSet.Mode.SHOULD_BE_TYPEREF) {
CElementPropertyInfo prop = new CElementPropertyInfo(
calcName(p),REPEATED_ELEMENT,ID.NONE,null,null,null,p.getLocation(),!optional);
rts.addTo(prop);
clazz.addProperty(prop);
} else {
CReferencePropertyInfo prop = new CReferencePropertyInfo(
calcName(p),true,!optional,false/*TODO*/,null,null,p.getLocation(), false, false, false);
rts.addTo(prop);
clazz.addProperty(prop);
}
return null;
}
public Void onAttribute(DAttributePattern p) {
// TODO: support multiple names
QName name = p.getName().listNames().iterator().next();
CAttributePropertyInfo ap = new CAttributePropertyInfo(
calcName(p), null,null/*TODO*/, p.getLocation(), name,
p.getChild().accept(compiler.typeUseBinder), null,
!insideOptional);
clazz.addProperty(ap);
return null;
}
private String calcName(DPattern p) {
// TODO
return "field"+(iota++);
}
}

View File

@@ -0,0 +1,76 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.relaxng;
import java.util.HashMap;
import java.util.Map;
import com.sun.tools.internal.xjc.model.CBuiltinLeafInfo;
import com.sun.tools.internal.xjc.model.TypeUse;
import com.sun.tools.internal.xjc.reader.xmlschema.SimpleTypeBuilder;
import com.sun.xml.internal.rngom.xml.util.WellKnownNamespaces;
/**
* Data-bindable datatype library.
*
* @author Kohsuke Kawaguchi
*/
final class DatatypeLib {
/**
* Datatype library's namespace URI.
*/
public final String nsUri;
private final Map<String,TypeUse> types = new HashMap<String,TypeUse>();
public DatatypeLib(String nsUri) {
this.nsUri = nsUri;
}
/**
* Maps the type name to the information.
*/
TypeUse get(String name) {
return types.get(name);
}
/**
* Datatype library for the built-in type.
*/
public static final DatatypeLib BUILTIN = new DatatypeLib("");
/**
* Datatype library for XML Schema datatypes.
*/
public static final DatatypeLib XMLSCHEMA = new DatatypeLib(WellKnownNamespaces.XML_SCHEMA_DATATYPES);
static {
BUILTIN.types.put("token",CBuiltinLeafInfo.TOKEN);
BUILTIN.types.put("string",CBuiltinLeafInfo.STRING);
XMLSCHEMA.types.putAll(SimpleTypeBuilder.builtinConversions);
}
}

View File

@@ -0,0 +1,61 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.relaxng;
import java.util.HashSet;
import java.util.Set;
import com.sun.xml.internal.rngom.digested.DDefine;
import com.sun.xml.internal.rngom.digested.DGrammarPattern;
import com.sun.xml.internal.rngom.digested.DPatternWalker;
import com.sun.xml.internal.rngom.digested.DRefPattern;
/**
* Recursively find all {@link DDefine}s in the grammar.
*
* @author Kohsuke Kawaguchi
*/
final class DefineFinder extends DPatternWalker {
public final Set<DDefine> defs = new HashSet<DDefine>();
public Void onGrammar(DGrammarPattern p) {
for( DDefine def : p ) {
defs.add(def);
def.getPattern().accept(this);
}
return p.getStart().accept(this);
}
/**
* We visit all {@link DDefine}s from {@link DGrammarPattern},
* so no point in resolving refs.
*/
public Void onRef(DRefPattern p) {
return null;
}
}

View File

@@ -0,0 +1,35 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.relaxng;
import com.sun.xml.internal.rngom.digested.DPatternWalker;
/**
* Decides the name for a particle.
* @author Kohsuke Kawaguchi
*/
class NameCalculator extends DPatternWalker {
}

View File

@@ -0,0 +1,270 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.relaxng;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.xml.namespace.QName;
import com.sun.codemodel.internal.JCodeModel;
import com.sun.codemodel.internal.JPackage;
import com.sun.tools.internal.xjc.Options;
import com.sun.tools.internal.xjc.model.CBuiltinLeafInfo;
import com.sun.tools.internal.xjc.model.CClassInfo;
import com.sun.tools.internal.xjc.model.CClassInfoParent;
import com.sun.tools.internal.xjc.model.CEnumConstant;
import com.sun.tools.internal.xjc.model.CEnumLeafInfo;
import com.sun.tools.internal.xjc.model.CNonElement;
import com.sun.tools.internal.xjc.model.CTypeInfo;
import com.sun.tools.internal.xjc.model.Model;
import com.sun.tools.internal.xjc.model.TypeUse;
import com.sun.xml.internal.bind.api.impl.NameConverter;
import com.sun.xml.internal.rngom.digested.DChoicePattern;
import com.sun.xml.internal.rngom.digested.DDefine;
import com.sun.xml.internal.rngom.digested.DElementPattern;
import com.sun.xml.internal.rngom.digested.DPattern;
import com.sun.xml.internal.rngom.digested.DPatternWalker;
import com.sun.xml.internal.rngom.digested.DRefPattern;
import com.sun.xml.internal.rngom.digested.DValuePattern;
import com.sun.xml.internal.rngom.nc.NameClass;
import com.sun.xml.internal.rngom.xml.util.WellKnownNamespaces;
/**
* @author Kohsuke Kawaguchi
*/
public final class RELAXNGCompiler {
/**
* Schema to compile.
*/
final DPattern grammar;
/**
* All named patterns in this schema.
*/
final Set<DDefine> defs;
final Options opts;
final Model model;
/**
* The package to which we generate the code into.
*/
final JPackage pkg;
final Map<String,DatatypeLib> datatypes = new HashMap<String, DatatypeLib>();
/**
* Patterns that are mapped to Java concepts.
*
* <p>
* The value is an array because we map elements with finite names
* to multiple classes.
*
* TODO: depending on the type of the key, the type of the values can be further
* restricted. Make this into its own class to represent those constraints better.
*/
final Map<DPattern,CTypeInfo[]> classes = new HashMap<DPattern,CTypeInfo[]>();
/**
* Classes that need to be bound.
*
* The value is the content model to be bound.
*/
final Map<CClassInfo,DPattern> bindQueue = new HashMap<CClassInfo,DPattern>();
final TypeUseBinder typeUseBinder = new TypeUseBinder(this);
public static Model build(DPattern grammar, JCodeModel codeModel, Options opts ) {
RELAXNGCompiler compiler = new RELAXNGCompiler(grammar, codeModel, opts);
compiler.compile();
return compiler.model;
}
public RELAXNGCompiler(DPattern grammar, JCodeModel codeModel, Options opts) {
this.grammar = grammar;
this.opts = opts;
this.model = new Model(opts,codeModel, NameConverter.smart,opts.classNameAllocator,null);
datatypes.put("",DatatypeLib.BUILTIN);
datatypes.put(WellKnownNamespaces.XML_SCHEMA_DATATYPES,DatatypeLib.XMLSCHEMA);
// find all defines
DefineFinder deff = new DefineFinder();
grammar.accept(deff);
this.defs = deff.defs;
if(opts.defaultPackage2!=null)
pkg = codeModel._package(opts.defaultPackage2);
else
if(opts.defaultPackage!=null)
pkg = codeModel._package(opts.defaultPackage);
else
pkg = codeModel.rootPackage();
}
private void compile() {
// decide which patterns to map to classes
promoteElementDefsToClasses();
promoteTypeSafeEnums();
// TODO: promote patterns with <jaxb:class> to classes
// TODO: promote 'type' patterns to classes
promoteTypePatternsToClasses();
for (Map.Entry<CClassInfo,DPattern> e : bindQueue.entrySet())
bindContentModel(e.getKey(),e.getValue());
}
private void bindContentModel(CClassInfo clazz, DPattern pattern) {
// first we decide which patterns in it map to properties
// then we process each of them by using RawTypeSetBuilder.
// much like DefaultParticleBinder in XSD
pattern.accept(new ContentModelBinder(this,clazz));
}
private void promoteTypeSafeEnums() {
// we'll be trying a lot of choices,
// and most of them will not be type-safe enum.
// using the same list improves the memory efficiency.
List<CEnumConstant> members = new ArrayList<CEnumConstant>();
OUTER:
for( DDefine def : defs ) {
DPattern p = def.getPattern();
if (p instanceof DChoicePattern) {
DChoicePattern cp = (DChoicePattern) p;
members.clear();
// check if the choice consists of all value patterns
// and that they are of the same datatype
DValuePattern vp = null;
for( DPattern child : cp ) {
if(child instanceof DValuePattern) {
DValuePattern c = (DValuePattern) child;
if(vp==null)
vp=c;
else {
if(!vp.getDatatypeLibrary().equals(c.getDatatypeLibrary())
|| !vp.getType().equals(c.getType()) )
continue OUTER; // different type name
}
members.add(new CEnumConstant(
model.getNameConverter().toConstantName(c.getValue()),
null, c.getValue(), null, null/*TODO*/, c.getLocation()
));
} else
continue OUTER; // not a value
}
if(members.isEmpty())
continue; // empty choice
CNonElement base = CBuiltinLeafInfo.STRING;
DatatypeLib lib = datatypes.get(vp.getNs());
if(lib!=null) {
TypeUse use = lib.get(vp.getType());
if(use instanceof CNonElement)
base = (CNonElement)use;
}
CEnumLeafInfo xducer = new CEnumLeafInfo(model, null,
new CClassInfoParent.Package(pkg), def.getName(), base,
new ArrayList<CEnumConstant>(members),
null, null/*TODO*/, cp.getLocation());
classes.put(cp,new CTypeInfo[]{xducer});
}
}
}
private void promoteElementDefsToClasses() {
// look for elements among named patterns
for( DDefine def : defs ) {
DPattern p = def.getPattern();
if (p instanceof DElementPattern) {
DElementPattern ep = (DElementPattern) p;
mapToClass(ep);
}
}
// also look for root elements
grammar.accept(new DPatternWalker() {
public Void onRef(DRefPattern p) {
return null; // stop recursion
}
public Void onElement(DElementPattern p) {
mapToClass(p);
return null;
}
});
}
private void mapToClass(DElementPattern p) {
NameClass nc = p.getName();
if(nc.isOpen())
return; // infinite name. can't map to a class.
Set<QName> names = nc.listNames();
CClassInfo[] types = new CClassInfo[names.size()];
int i=0;
for( QName n : names ) {
// TODO: read class names from customization
String name = model.getNameConverter().toClassName(n.getLocalPart());
bindQueue.put(
types[i++] = new CClassInfo(model,pkg,name,p.getLocation(),null,n,null,null/*TODO*/),
p.getChild() );
}
classes.put(p,types);
}
/**
* Looks for named patterns that are not bound to classes so far,
* but that can be bound to classes.
*/
private void promoteTypePatternsToClasses() {
// for( DDefine def : defs ) {
// ;
//
// def.getPattern().accept(new InheritanceChecker());
// }
}
}

View File

@@ -0,0 +1,76 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.relaxng;
import com.sun.tools.internal.xjc.reader.Const;
import com.sun.tools.internal.xjc.reader.internalizer.AbstractReferenceFinderImpl;
import com.sun.tools.internal.xjc.reader.internalizer.DOMForest;
import com.sun.tools.internal.xjc.reader.internalizer.InternalizationLogic;
import org.w3c.dom.Element;
import org.xml.sax.Attributes;
import org.xml.sax.helpers.XMLFilterImpl;
/**
* RELAX NG specific internalization logic.
*
* @author
* Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
*/
public class RELAXNGInternalizationLogic implements InternalizationLogic {
/**
* This filter looks for &lt;xs:import> and &lt;xs:include>
* and parses those documents referenced by them.
*/
private static final class ReferenceFinder extends AbstractReferenceFinderImpl {
ReferenceFinder( DOMForest parent ) {
super(parent);
}
protected String findExternalResource( String nsURI, String localName, Attributes atts) {
if( Const.RELAXNG_URI.equals(nsURI)
&& ("include".equals(localName) || "externalRef".equals(localName) ) )
return atts.getValue("href");
else
return null;
}
};
public XMLFilterImpl createExternalReferenceFinder(DOMForest parent) {
return new ReferenceFinder(parent);
}
public boolean checkIfValidTargetNode(DOMForest parent, Element bindings, Element target) {
return Const.RELAXNG_URI.equals(target.getNamespaceURI());
}
public Element refineTarget(Element target) {
// no refinement necessary
return target;
}
}

View File

@@ -0,0 +1,137 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.relaxng;
import java.util.HashSet;
import java.util.Set;
import com.sun.tools.internal.xjc.model.CClassInfo;
import com.sun.tools.internal.xjc.model.CElementPropertyInfo;
import com.sun.tools.internal.xjc.model.CReferencePropertyInfo;
import com.sun.tools.internal.xjc.model.CTypeInfo;
import com.sun.tools.internal.xjc.model.CTypeRef;
import com.sun.tools.internal.xjc.model.Multiplicity;
import com.sun.tools.internal.xjc.reader.RawTypeSet;
import com.sun.xml.internal.bind.v2.model.core.ID;
import com.sun.xml.internal.rngom.digested.DAttributePattern;
import com.sun.xml.internal.rngom.digested.DElementPattern;
import com.sun.xml.internal.rngom.digested.DOneOrMorePattern;
import com.sun.xml.internal.rngom.digested.DPattern;
import com.sun.xml.internal.rngom.digested.DPatternWalker;
import com.sun.xml.internal.rngom.digested.DZeroOrMorePattern;
/**
* Builds {@link RawTypeSet} for RELAX NG.
*
* @author Kohsuke Kawaguchi
*/
public final class RawTypeSetBuilder extends DPatternWalker {
public static RawTypeSet build( RELAXNGCompiler compiler, DPattern contentModel, Multiplicity mul ) {
RawTypeSetBuilder builder = new RawTypeSetBuilder(compiler,mul);
contentModel.accept(builder);
return builder.create();
}
/**
* Multiplicity of the property.
*/
private Multiplicity mul;
/**
* Accumulates discovered {@link RawTypeSet.Ref}s.
*/
private final Set<RawTypeSet.Ref> refs = new HashSet<RawTypeSet.Ref>();
private final RELAXNGCompiler compiler;
public RawTypeSetBuilder(RELAXNGCompiler compiler,Multiplicity mul) {
this.mul = mul;
this.compiler = compiler;
}
private RawTypeSet create() {
return new RawTypeSet(refs,mul);
}
public Void onAttribute(DAttributePattern p) {
// attributes form their own properties
return null;
}
public Void onElement(DElementPattern p) {
CTypeInfo[] tis = compiler.classes.get(p);
if(tis!=null) {
for( CTypeInfo ti : tis )
refs.add(new CClassInfoRef((CClassInfo)ti));
} else {
// TODO
assert false;
}
return null;
}
public Void onZeroOrMore(DZeroOrMorePattern p) {
mul = mul.makeRepeated();
return super.onZeroOrMore(p);
}
public Void onOneOrMore(DOneOrMorePattern p) {
mul = mul.makeRepeated();
return super.onOneOrMore(p);
}
/**
* For {@link CClassInfo}s that map to elements.
*/
private static final class CClassInfoRef extends RawTypeSet.Ref {
private final CClassInfo ci;
CClassInfoRef(CClassInfo ci) {
this.ci = ci;
assert ci.isElement();
}
protected ID id() {
return ID.NONE;
}
protected boolean isListOfValues() {
return false;
}
protected RawTypeSet.Mode canBeType(RawTypeSet parent) {
return RawTypeSet.Mode.SHOULD_BE_TYPEREF;
}
protected void toElementRef(CReferencePropertyInfo prop) {
prop.getElements().add(ci);
}
protected CTypeRef toTypeRef(CElementPropertyInfo ep) {
return new CTypeRef(ci,ci.getElementName(),ci.getTypeName(),false,null);
}
}
}

View File

@@ -0,0 +1,140 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.relaxng;
import java.util.HashSet;
import java.util.Set;
import java.util.Stack;
import com.sun.xml.internal.rngom.digested.DAttributePattern;
import com.sun.xml.internal.rngom.digested.DChoicePattern;
import com.sun.xml.internal.rngom.digested.DDefine;
import com.sun.xml.internal.rngom.digested.DListPattern;
import com.sun.xml.internal.rngom.digested.DMixedPattern;
import com.sun.xml.internal.rngom.digested.DOneOrMorePattern;
import com.sun.xml.internal.rngom.digested.DOptionalPattern;
import com.sun.xml.internal.rngom.digested.DPatternWalker;
import com.sun.xml.internal.rngom.digested.DRefPattern;
import com.sun.xml.internal.rngom.digested.DZeroOrMorePattern;
/**
* Fumigate the named patterns that can be bound to inheritance.
*
* @author Kohsuke Kawaguchi
*/
final class TypePatternBinder extends DPatternWalker {
private boolean canInherit;
private final Stack<Boolean> stack = new Stack<Boolean>();
/**
* Patterns that are determined not to be bindable to inheritance.
*/
private final Set<DDefine> cannotBeInherited = new HashSet<DDefine>();
void reset() {
canInherit = true;
stack.clear();
}
public Void onRef(DRefPattern p) {
if(!canInherit) {
cannotBeInherited.add(p.getTarget());
} else {
// if the whole pattern is like "A,B", we can only inherit from
// either A or B. For now, always derive from A.
// it might be worthwhile to have a smarter binding logic where
// we pick A and B based on their 'usefulness' --- by taking into
// account how many other paterns are derived from those.
canInherit = false;
}
return null;
}
/*
Set the flag to false if we hit a pattern that cannot include
a <ref> to be bound as an inheritance.
All the following code are the same
*/
public Void onChoice(DChoicePattern p) {
push(false);
super.onChoice(p);
pop();
return null;
}
public Void onAttribute(DAttributePattern p) {
push(false);
super.onAttribute(p);
pop();
return null;
}
public Void onList(DListPattern p) {
push(false);
super.onList(p);
pop();
return null;
}
public Void onMixed(DMixedPattern p) {
push(false);
super.onMixed(p);
pop();
return null;
}
public Void onOneOrMore(DOneOrMorePattern p) {
push(false);
super.onOneOrMore(p);
pop();
return null;
}
public Void onZeroOrMore(DZeroOrMorePattern p) {
push(false);
super.onZeroOrMore(p);
pop();
return null;
}
public Void onOptional(DOptionalPattern p) {
push(false);
super.onOptional(p);
pop();
return null;
}
private void push(boolean v) {
stack.push(canInherit);
canInherit = v;
}
private void pop() {
canInherit = stack.pop();
}
}

View File

@@ -0,0 +1,172 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.relaxng;
import com.sun.tools.internal.xjc.model.CBuiltinLeafInfo;
import com.sun.tools.internal.xjc.model.TypeUse;
import com.sun.tools.internal.xjc.model.TypeUseFactory;
import com.sun.xml.internal.rngom.digested.DAttributePattern;
import com.sun.xml.internal.rngom.digested.DChoicePattern;
import com.sun.xml.internal.rngom.digested.DContainerPattern;
import com.sun.xml.internal.rngom.digested.DDataPattern;
import com.sun.xml.internal.rngom.digested.DElementPattern;
import com.sun.xml.internal.rngom.digested.DEmptyPattern;
import com.sun.xml.internal.rngom.digested.DGrammarPattern;
import com.sun.xml.internal.rngom.digested.DGroupPattern;
import com.sun.xml.internal.rngom.digested.DInterleavePattern;
import com.sun.xml.internal.rngom.digested.DListPattern;
import com.sun.xml.internal.rngom.digested.DMixedPattern;
import com.sun.xml.internal.rngom.digested.DNotAllowedPattern;
import com.sun.xml.internal.rngom.digested.DOneOrMorePattern;
import com.sun.xml.internal.rngom.digested.DOptionalPattern;
import com.sun.xml.internal.rngom.digested.DPattern;
import com.sun.xml.internal.rngom.digested.DPatternVisitor;
import com.sun.xml.internal.rngom.digested.DRefPattern;
import com.sun.xml.internal.rngom.digested.DTextPattern;
import com.sun.xml.internal.rngom.digested.DValuePattern;
import com.sun.xml.internal.rngom.digested.DZeroOrMorePattern;
/**
* Walks the pattern tree and binds it to a {@link TypeUse}.
*
* The singleton instance is kept in {@link RELAXNGCompiler}.
*
* TODO: I should really normalize before process.
*
* @author Kohsuke Kawaguchi
*/
final class TypeUseBinder implements DPatternVisitor<TypeUse> {
private final RELAXNGCompiler compiler;
public TypeUseBinder(RELAXNGCompiler compiler) {
this.compiler = compiler;
}
public TypeUse onGrammar(DGrammarPattern p) {
return CBuiltinLeafInfo.STRING;
}
public TypeUse onChoice(DChoicePattern p) {
// can't support unions
return CBuiltinLeafInfo.STRING;
}
public TypeUse onData(DDataPattern p) {
return onDataType(p.getDatatypeLibrary(), p.getType());
}
public TypeUse onValue(DValuePattern p) {
return onDataType(p.getDatatypeLibrary(),p.getType());
}
private TypeUse onDataType(String datatypeLibrary, String type) {
DatatypeLib lib = compiler.datatypes.get(datatypeLibrary);
if(lib!=null) {
TypeUse use = lib.get(type);
if(use!=null)
return use;
}
// unknown
return CBuiltinLeafInfo.STRING;
}
public TypeUse onInterleave(DInterleavePattern p) {
return onContainer(p);
}
public TypeUse onGroup(DGroupPattern p) {
return onContainer(p);
}
private TypeUse onContainer(DContainerPattern p) {
TypeUse t=null;
for( DPattern child : p ) {
TypeUse s = child.accept(this);
if(t!=null && t!=s)
return CBuiltinLeafInfo.STRING; // heterogenous
t = s;
}
return t;
}
public TypeUse onNotAllowed(DNotAllowedPattern p) {
// TODO
return error();
}
public TypeUse onEmpty(DEmptyPattern p) {
return CBuiltinLeafInfo.STRING;
}
public TypeUse onList(DListPattern p) {
return p.getChild().accept(this);
}
public TypeUse onOneOrMore(DOneOrMorePattern p) {
return TypeUseFactory.makeCollection( p.getChild().accept(this) );
}
public TypeUse onZeroOrMore(DZeroOrMorePattern p) {
return TypeUseFactory.makeCollection( p.getChild().accept(this) );
}
public TypeUse onOptional(DOptionalPattern p) {
return CBuiltinLeafInfo.STRING;
}
public TypeUse onRef(DRefPattern p) {
// TODO: check for enums
return p.getTarget().getPattern().accept(this);
}
public TypeUse onText(DTextPattern p) {
return CBuiltinLeafInfo.STRING;
}
//
//
// Not allowed in this context
//
//
public TypeUse onAttribute(DAttributePattern p) {
return error();
}
public TypeUse onElement(DElementPattern p) {
return error();
}
public TypeUse onMixed(DMixedPattern p) {
return error();
}
private TypeUse error() {
throw new IllegalStateException();
}
}

View File

@@ -0,0 +1,55 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.xmlschema;
import com.sun.tools.internal.xjc.model.CElement;
import com.sun.xml.internal.xsom.XSComplexType;
import com.sun.xml.internal.xsom.XSElementDecl;
/**
* {@link ClassBinder} that marks abstract components as abstract.
*
* @author Kohsuke Kawaguchi (kk@kohsuke.org)
*/
class Abstractifier extends ClassBinderFilter {
public Abstractifier(ClassBinder core) {
super(core);
}
public CElement complexType(XSComplexType xs) {
CElement ci = super.complexType(xs);
if(ci!=null && xs.isAbstract())
ci.setAbstract();
return ci;
}
public CElement elementDecl(XSElementDecl xs) {
CElement ci = super.elementDecl(xs);
if(ci!=null && xs.isAbstract())
ci.setAbstract();
return ci;
}
}

View File

@@ -0,0 +1,568 @@
/*
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.xmlschema;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.xml.namespace.QName;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerFactory;
import com.sun.codemodel.internal.JCodeModel;
import com.sun.codemodel.internal.fmt.JTextFile;
import com.sun.istack.internal.NotNull;
import com.sun.istack.internal.Nullable;
import com.sun.tools.internal.xjc.ErrorReceiver;
import com.sun.tools.internal.xjc.Options;
import com.sun.tools.internal.xjc.Plugin;
import com.sun.tools.internal.xjc.generator.bean.field.FieldRendererFactory;
import com.sun.tools.internal.xjc.model.CClassInfoParent;
import com.sun.tools.internal.xjc.model.Model;
import com.sun.tools.internal.xjc.reader.ModelChecker;
import com.sun.tools.internal.xjc.reader.Ring;
import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIDeclaration;
import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIDom;
import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIGlobalBinding;
import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BISchemaBinding;
import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BISerializable;
import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BindInfo;
import com.sun.tools.internal.xjc.util.CodeModelClassFactory;
import com.sun.tools.internal.xjc.util.ErrorReceiverFilter;
import com.sun.xml.internal.bind.api.impl.NameConverter;
import com.sun.xml.internal.bind.v2.util.XmlFactory;
import com.sun.xml.internal.xsom.XSAnnotation;
import com.sun.xml.internal.xsom.XSAttributeUse;
import com.sun.xml.internal.xsom.XSComponent;
import com.sun.xml.internal.xsom.XSDeclaration;
import com.sun.xml.internal.xsom.XSParticle;
import com.sun.xml.internal.xsom.XSSchema;
import com.sun.xml.internal.xsom.XSSchemaSet;
import com.sun.xml.internal.xsom.XSSimpleType;
import com.sun.xml.internal.xsom.XSTerm;
import com.sun.xml.internal.xsom.XSType;
import com.sun.xml.internal.xsom.XSWildcard;
import com.sun.xml.internal.xsom.util.XSFinder;
import org.xml.sax.Locator;
/**
* Root of the XML Schema binder.
*
* <div><img src="doc-files/binding_chart.png"/></div>
*
* @author Kohsuke Kawaguchi
*/
public class BGMBuilder extends BindingComponent {
/**
* Entry point.
*/
public static Model build( XSSchemaSet _schemas, JCodeModel codeModel,
ErrorReceiver _errorReceiver, Options opts ) {
// set up a ring
final Ring old = Ring.begin();
try {
ErrorReceiverFilter ef = new ErrorReceiverFilter(_errorReceiver);
Ring.add(XSSchemaSet.class,_schemas);
Ring.add(codeModel);
Model model = new Model(opts, codeModel, null/*set later*/, opts.classNameAllocator, _schemas);
Ring.add(model);
Ring.add(ErrorReceiver.class,ef);
Ring.add(CodeModelClassFactory.class,new CodeModelClassFactory(ef));
BGMBuilder builder = new BGMBuilder(opts.defaultPackage,opts.defaultPackage2,
opts.isExtensionMode(),opts.getFieldRendererFactory(), opts.activePlugins);
builder._build();
if(ef.hadError()) return null;
else return model;
} finally {
Ring.end(old);
}
}
/**
* True if the compiler is running in the extension mode
* (as opposed to the strict conformance mode.)
*/
public final boolean inExtensionMode;
/**
* If this is non-null, this package name takes over
* all the schema customizations.
*/
public final String defaultPackage1;
/**
* If this is non-null, this package name will be
* used when no customization is specified.
*/
public final String defaultPackage2;
private final BindGreen green = Ring.get(BindGreen.class);
private final BindPurple purple = Ring.get(BindPurple.class);
public final Model model = Ring.get(Model.class);
public final FieldRendererFactory fieldRendererFactory;
/**
* Lazily computed {@link RefererFinder}.
*
* @see #getReferer
*/
private RefererFinder refFinder;
private List<Plugin> activePlugins;
protected BGMBuilder(String defaultPackage1, String defaultPackage2,
boolean _inExtensionMode, FieldRendererFactory fieldRendererFactory,
List<Plugin> activePlugins) {
this.inExtensionMode = _inExtensionMode;
this.defaultPackage1 = defaultPackage1;
this.defaultPackage2 = defaultPackage2;
this.fieldRendererFactory = fieldRendererFactory;
this.activePlugins = activePlugins;
promoteGlobalBindings();
}
private void _build() {
// do the binding
buildContents();
getClassSelector().executeTasks();
// additional error check
// Reports unused customizations to the user as errors.
Ring.get(UnusedCustomizationChecker.class).run();
Ring.get(ModelChecker.class).check();
for( Plugin ma : activePlugins )
ma.postProcessModel(model, Ring.get(ErrorReceiver.class));
}
/** List up all the global bindings. */
private void promoteGlobalBindings() {
// promote any global bindings in the schema
XSSchemaSet schemas = Ring.get(XSSchemaSet.class);
for( XSSchema s : schemas.getSchemas() ) {
BindInfo bi = getBindInfo(s);
// collect all global customizations
model.getCustomizations().addAll(bi.toCustomizationList());
BIGlobalBinding gb = bi.get(BIGlobalBinding.class);
if(gb==null)
continue;
gb.markAsAcknowledged();
if(globalBinding==null) {
globalBinding = gb;
} else {
if (!globalBinding.isEqual(gb)) { // see Issue 687 - this may happen with syntactically imported documents
// acknowledge this customization and report an error
// otherwise the user will see "customization is attached to a wrong place" error,
// which is incorrect
getErrorReporter().error( gb.getLocation(),
Messages.ERR_MULTIPLE_GLOBAL_BINDINGS);
getErrorReporter().error( globalBinding.getLocation(),
Messages.ERR_MULTIPLE_GLOBAL_BINDINGS_OTHER);
}
}
}
if( globalBinding==null ) {
// no global customization is present.
// use the default one
globalBinding = new BIGlobalBinding();
BindInfo big = new BindInfo();
big.addDecl(globalBinding);
big.setOwner(this,null);
}
// code generation mode
model.strategy = globalBinding.getCodeGenerationStrategy();
model.rootClass = globalBinding.getSuperClass();
model.rootInterface = globalBinding.getSuperInterface();
particleBinder = globalBinding.isSimpleMode() ? new ExpressionParticleBinder() : new DefaultParticleBinder();
// check XJC extensions and realize them
BISerializable serial = globalBinding.getSerializable();
if(serial!=null) {
model.serializable = true;
model.serialVersionUID = serial.uid;
}
// obtain the name conversion mode
if (globalBinding.nameConverter!=null)
model.setNameConverter(globalBinding.nameConverter);
// attach global conversions to the appropriate simple types
globalBinding.dispatchGlobalConversions(schemas);
globalBinding.errorCheck();
}
/**
* Global bindings.
*
* The empty global binding is set as the default, so that
* there will be no need to test if the value is null.
*/
private BIGlobalBinding globalBinding;
/**
* Gets the global bindings.
*/
public @NotNull BIGlobalBinding getGlobalBinding() { return globalBinding; }
private ParticleBinder particleBinder;
/**
* Gets the particle binder for this binding.
*/
public @NotNull ParticleBinder getParticleBinder() { return particleBinder; }
/**
* Name converter that implements "XML->Java name conversion"
* as specified in the spec.
*
* This object abstracts the detail that we use different name
* conversion depending on the customization.
*
* <p>
* This object should be used to perform any name conversion
* needs, instead of the JJavaName class in CodeModel.
*/
public NameConverter getNameConverter() { return model.getNameConverter(); }
/** Fill-in the contents of each classes. */
private void buildContents() {
ClassSelector cs = getClassSelector();
SimpleTypeBuilder stb = Ring.get(SimpleTypeBuilder.class);
for( XSSchema s : Ring.get(XSSchemaSet.class).getSchemas() ) {
BISchemaBinding sb = getBindInfo(s).get(BISchemaBinding.class);
if(sb!=null && !sb.map) {
sb.markAsAcknowledged();
continue; // no mapping for this package
}
getClassSelector().pushClassScope( new CClassInfoParent.Package(
getClassSelector().getPackage(s.getTargetNamespace())) );
checkMultipleSchemaBindings(s);
processPackageJavadoc(s);
populate(s.getAttGroupDecls(),s);
populate(s.getAttributeDecls(),s);
populate(s.getElementDecls(),s);
populate(s.getModelGroupDecls(),s);
// fill in typeUses
for (XSType t : s.getTypes().values()) {
stb.refererStack.push(t);
model.typeUses().put( getName(t), cs.bindToType(t,s) );
stb.refererStack.pop();
}
getClassSelector().popClassScope();
}
}
/** Reports an error if there are more than one jaxb:schemaBindings customization. */
private void checkMultipleSchemaBindings( XSSchema schema ) {
ArrayList<Locator> locations = new ArrayList<Locator>();
BindInfo bi = getBindInfo(schema);
for( BIDeclaration bid : bi ) {
if( bid.getName()==BISchemaBinding.NAME )
locations.add( bid.getLocation() );
}
if(locations.size()<=1) return; // OK
// error
getErrorReporter().error( locations.get(0),
Messages.ERR_MULTIPLE_SCHEMA_BINDINGS,
schema.getTargetNamespace() );
for( int i=1; i<locations.size(); i++ )
getErrorReporter().error( (Locator)locations.get(i),
Messages.ERR_MULTIPLE_SCHEMA_BINDINGS_LOCATION);
}
/**
* Calls {@link ClassSelector} for each item in the iterator
* to populate class items if there is any.
*/
private void populate( Map<String,? extends XSComponent> col, XSSchema schema ) {
ClassSelector cs = getClassSelector();
for( XSComponent sc : col.values() )
cs.bindToType(sc,schema);
}
/**
* Generates <code>package.html</code> if the customization
* says so.
*/
private void processPackageJavadoc( XSSchema s ) {
// look for the schema-wide customization
BISchemaBinding cust = getBindInfo(s).get(BISchemaBinding.class);
if(cust==null) return; // not present
cust.markAsAcknowledged();
if( cust.getJavadoc()==null ) return; // no javadoc customization
// produce a HTML file
JTextFile html = new JTextFile("package.html");
html.setContents(cust.getJavadoc());
getClassSelector().getPackage(s.getTargetNamespace()).addResourceFile(html);
}
/**
* Gets or creates the BindInfo object associated to a schema component.
*
* @return
* Always return a non-null valid BindInfo object.
* Even if no declaration was specified, this method creates
* a new BindInfo so that new decls can be added.
*/
public BindInfo getOrCreateBindInfo( XSComponent schemaComponent ) {
BindInfo bi = _getBindInfoReadOnly(schemaComponent);
if(bi!=null) return bi;
// XSOM is read-only, so we cannot add new annotations.
// for components that didn't have annotations,
// we maintain an external map.
bi = new BindInfo();
bi.setOwner(this,schemaComponent);
externalBindInfos.put(schemaComponent,bi);
return bi;
}
/**
* Used as a constant instance to represent the empty {@link BindInfo}.
*/
private final BindInfo emptyBindInfo = new BindInfo();
/**
* Gets the BindInfo object associated to a schema component.
*
* @return
* always return a valid {@link BindInfo} object. If none
* is specified for the given component, a dummy empty BindInfo
* will be returned.
*/
public BindInfo getBindInfo( XSComponent schemaComponent ) {
BindInfo bi = _getBindInfoReadOnly(schemaComponent);
if(bi!=null) return bi;
else return emptyBindInfo;
}
/**
* Gets the BindInfo object associated to a schema component.
*
* @return
* null if no bind info is associated to this schema component.
*/
private BindInfo _getBindInfoReadOnly( XSComponent schemaComponent ) {
BindInfo bi = externalBindInfos.get(schemaComponent);
if(bi!=null) return bi;
XSAnnotation annon = schemaComponent.getAnnotation();
if(annon!=null) {
bi = (BindInfo)annon.getAnnotation();
if(bi!=null) {
if(bi.getOwner()==null)
bi.setOwner(this,schemaComponent);
return bi;
}
}
return null;
}
/**
* A map that stores binding declarations augmented by XJC.
*/
private final Map<XSComponent,BindInfo> externalBindInfos = new HashMap<XSComponent,BindInfo>();
/**
* Gets the {@link BIDom} object that applies to the given particle.
*/
protected final BIDom getLocalDomCustomization( XSParticle p ) {
if (p == null) {
return null;
}
BIDom dom = getBindInfo(p).get(BIDom.class);
if(dom!=null) return dom;
// if not, the term might have one.
dom = getBindInfo(p.getTerm()).get(BIDom.class);
if(dom!=null) return dom;
XSTerm t = p.getTerm();
// type could also have one, in case of the dom customization
if(t.isElementDecl())
return getBindInfo(t.asElementDecl().getType()).get(BIDom.class);
// similarly the model group in a model group definition may have one.
if(t.isModelGroupDecl())
return getBindInfo(t.asModelGroupDecl().getModelGroup()).get(BIDom.class);
return null;
}
/**
* Returns true if the component should be processed by purple.
*/
private final XSFinder toPurple = new XSFinder() {
@Override
public Boolean attributeUse(XSAttributeUse use) {
// attribute use always maps to a property
return true;
}
@Override
public Boolean simpleType(XSSimpleType xsSimpleType) {
// simple type always maps to a type, hence we should take purple
return true;
}
@Override
public Boolean wildcard(XSWildcard xsWildcard) {
// attribute wildcards always maps to a property.
// element wildcards should have been processed with particle binders
return true;
}
};
/**
* If the component maps to a property, forwards to purple, otherwise to green.
*
* If the component is mapped to a type, this method needs to return true.
* See the chart at the class javadoc.
*/
public void ying( XSComponent sc, @Nullable XSComponent referer ) {
if(sc.apply(toPurple)==true || getClassSelector().bindToType(sc,referer)!=null)
sc.visit(purple);
else
sc.visit(green);
}
private Transformer identityTransformer;
/**
* Gets the shared instance of the identity transformer.
*/
public Transformer getIdentityTransformer() {
try {
if(identityTransformer==null) {
TransformerFactory tf = XmlFactory.createTransformerFactory(model.options.disableXmlSecurity);
identityTransformer = tf.newTransformer();
}
return identityTransformer;
} catch (TransformerConfigurationException e) {
throw new Error(e); // impossible
}
}
/**
* Find all types that refer to the given complex type.
*/
public Set<XSComponent> getReferer(XSType c) {
if(refFinder==null) {
refFinder = new RefererFinder();
refFinder.schemaSet(Ring.get(XSSchemaSet.class));
}
return refFinder.getReferer(c);
}
/**
* Returns the QName of the declaration.
* @return null
* if the declaration is anonymous.
*/
public static QName getName(XSDeclaration decl) {
String local = decl.getName();
if(local==null) return null;
return new QName(decl.getTargetNamespace(),local);
}
/**
* Derives a name from a schema component.
*
* This method handles prefix/suffix modification and
* XML-to-Java name conversion.
*
* @param name
* The base name. This should be things like element names
* or type names.
* @param comp
* The component from which the base name was taken.
* Used to determine how names are modified.
*/
public String deriveName( String name, XSComponent comp ) {
XSSchema owner = comp.getOwnerSchema();
name = getNameConverter().toClassName(name);
if( owner!=null ) {
BISchemaBinding sb = getBindInfo(owner).get(BISchemaBinding.class);
if(sb!=null) name = sb.mangleClassName(name,comp);
}
return name;
}
public boolean isGenerateMixedExtensions() {
if (globalBinding != null) {
return globalBinding.isGenerateMixedExtensions();
}
return false;
}
}

View File

@@ -0,0 +1,107 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.xmlschema;
import com.sun.xml.internal.xsom.XSAttGroupDecl;
import com.sun.xml.internal.xsom.XSAttributeDecl;
import com.sun.xml.internal.xsom.XSAttributeUse;
import com.sun.xml.internal.xsom.XSComplexType;
import com.sun.xml.internal.xsom.XSContentType;
import com.sun.xml.internal.xsom.XSElementDecl;
import com.sun.xml.internal.xsom.XSModelGroup;
import com.sun.xml.internal.xsom.XSModelGroupDecl;
import com.sun.xml.internal.xsom.XSParticle;
import com.sun.xml.internal.xsom.XSSimpleType;
import com.sun.xml.internal.xsom.XSWildcard;
/**
* This is the first color invoked from the parent component.
*
* @author Kohsuke Kawaguchi
*/
final class BindBlue extends ColorBinder {
public void complexType(XSComplexType ct) {
// TODO: implement this method later
throw new UnsupportedOperationException();
}
public void elementDecl(XSElementDecl e) {
// TODO: implement this method later
throw new UnsupportedOperationException();
}
public void wildcard(XSWildcard xsWildcard) {
// TODO: implement this method later
throw new UnsupportedOperationException();
}
public void attGroupDecl(XSAttGroupDecl xsAttGroupDecl) {
// TODO
throw new UnsupportedOperationException();
}
public void attributeDecl(XSAttributeDecl xsAttributeDecl) {
// TODO
throw new UnsupportedOperationException();
}
public void attributeUse(XSAttributeUse use) {
// TODO
throw new UnsupportedOperationException();
}
public void modelGroupDecl(XSModelGroupDecl xsModelGroupDecl) {
// TODO
throw new UnsupportedOperationException();
}
public void modelGroup(XSModelGroup xsModelGroup) {
// TODO
throw new UnsupportedOperationException();
}
public void particle(XSParticle xsParticle) {
// TODO
throw new UnsupportedOperationException();
}
public void empty(XSContentType xsContentType) {
// TODO
throw new UnsupportedOperationException();
}
/**
* Components that always map to a type
*/
public void simpleType(XSSimpleType type) {
throw new IllegalStateException();
}
}

View File

@@ -0,0 +1,131 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.xmlschema;
import java.util.Iterator;
import com.sun.tools.internal.xjc.reader.Ring;
import com.sun.tools.internal.xjc.reader.xmlschema.ct.ComplexTypeFieldBuilder;
import com.sun.xml.internal.xsom.XSAttContainer;
import com.sun.xml.internal.xsom.XSAttGroupDecl;
import com.sun.xml.internal.xsom.XSAttributeDecl;
import com.sun.xml.internal.xsom.XSAttributeUse;
import com.sun.xml.internal.xsom.XSComplexType;
import com.sun.xml.internal.xsom.XSContentType;
import com.sun.xml.internal.xsom.XSElementDecl;
import com.sun.xml.internal.xsom.XSModelGroup;
import com.sun.xml.internal.xsom.XSModelGroupDecl;
import com.sun.xml.internal.xsom.XSParticle;
import com.sun.xml.internal.xsom.XSSimpleType;
import com.sun.xml.internal.xsom.XSWildcard;
/**
* @author Kohsuke Kawaguchi
*/
public final class BindGreen extends ColorBinder {
private final ComplexTypeFieldBuilder ctBuilder = Ring.get(ComplexTypeFieldBuilder.class);
public void attGroupDecl(XSAttGroupDecl ag) {
attContainer(ag);
}
public void attContainer(XSAttContainer cont) {
// inline
Iterator itr = cont.iterateDeclaredAttributeUses();
while(itr.hasNext())
builder.ying((XSAttributeUse)itr.next(),cont);
itr = cont.iterateAttGroups();
while(itr.hasNext())
builder.ying((XSAttGroupDecl)itr.next(),cont);
XSWildcard w = cont.getAttributeWildcard();
if(w!=null)
builder.ying(w,cont);
}
public void complexType(XSComplexType ct) {
ctBuilder.build(ct);
}
public void attributeDecl(XSAttributeDecl xsAttributeDecl) {
// TODO: implement this method later
throw new UnsupportedOperationException();
}
public void wildcard(XSWildcard xsWildcard) {
// TODO: implement this method later
throw new UnsupportedOperationException();
}
public void modelGroupDecl(XSModelGroupDecl xsModelGroupDecl) {
// TODO: implement this method later
throw new UnsupportedOperationException();
}
public void modelGroup(XSModelGroup xsModelGroup) {
// TODO: implement this method later
throw new UnsupportedOperationException();
}
public void elementDecl(XSElementDecl xsElementDecl) {
// TODO: implement this method later
throw new UnsupportedOperationException();
}
public void particle(XSParticle xsParticle) {
// TODO: implement this method later
throw new UnsupportedOperationException();
}
public void empty(XSContentType xsContentType) {
// TODO: implement this method later
throw new UnsupportedOperationException();
}
/*
Components for which ying should yield to purple.
*/
public void simpleType(XSSimpleType xsSimpleType) {
// simple type always maps to a type, so this is never possible
throw new IllegalStateException();
}
public void attributeUse(XSAttributeUse use) {
// attribute use always maps to a property
throw new IllegalStateException();
}
}

View File

@@ -0,0 +1,153 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.xmlschema;
import com.sun.tools.internal.xjc.model.CClassInfo;
import com.sun.tools.internal.xjc.model.CDefaultValue;
import com.sun.tools.internal.xjc.model.CPropertyInfo;
import com.sun.tools.internal.xjc.model.TypeUse;
import com.sun.tools.internal.xjc.model.CClass;
import com.sun.tools.internal.xjc.reader.Ring;
import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIProperty;
import com.sun.xml.internal.xsom.XSAttGroupDecl;
import com.sun.xml.internal.xsom.XSAttributeDecl;
import com.sun.xml.internal.xsom.XSAttributeUse;
import com.sun.xml.internal.xsom.XSComplexType;
import com.sun.xml.internal.xsom.XSContentType;
import com.sun.xml.internal.xsom.XSElementDecl;
import com.sun.xml.internal.xsom.XSModelGroup;
import com.sun.xml.internal.xsom.XSModelGroupDecl;
import com.sun.xml.internal.xsom.XSParticle;
import com.sun.xml.internal.xsom.XSSimpleType;
import com.sun.xml.internal.xsom.XSWildcard;
/**
* @author Kohsuke Kawaguchi
*/
public class BindPurple extends ColorBinder {
public void attGroupDecl(XSAttGroupDecl xsAttGroupDecl) {
// TODO
throw new UnsupportedOperationException();
}
public void attributeDecl(XSAttributeDecl xsAttributeDecl) {
// TODO
throw new UnsupportedOperationException();
}
/**
* Attribute use always becomes a property.
*/
public void attributeUse(XSAttributeUse use) {
boolean hasFixedValue = use.getFixedValue()!=null;
BIProperty pc = BIProperty.getCustomization(use);
// map to a constant property ?
boolean toConstant = pc.isConstantProperty() && hasFixedValue;
TypeUse attType = bindAttDecl(use.getDecl());
CPropertyInfo prop = pc.createAttributeProperty( use, attType );
if(toConstant) {
prop.defaultValue = CDefaultValue.create(attType,use.getFixedValue());
prop.realization = builder.fieldRendererFactory.getConst(prop.realization);
} else
if(!attType.isCollection() && (prop.baseType == null ? true : !prop.baseType.isPrimitive())) {
// don't support a collection default value. That's difficult to do.
// primitive types default value is problematic too - we can't check whether it has been set or no ( ==null) isn't possible TODO: emit a waring in these cases
if(use.getDefaultValue()!=null) {
// this attribute use has a default value.
// the item type is guaranteed to be a leaf type... or TODO: is it really so?
// don't support default values if it's a list
prop.defaultValue = CDefaultValue.create(attType,use.getDefaultValue());
} else
if(use.getFixedValue()!=null) {
prop.defaultValue = CDefaultValue.create(attType,use.getFixedValue());
}
} else if(prop.baseType != null && prop.baseType.isPrimitive()) {
ErrorReporter errorReporter = Ring.get(ErrorReporter.class);
errorReporter.warning(prop.getLocator(), Messages.WARN_DEFAULT_VALUE_PRIMITIVE_TYPE, prop.baseType.name());
}
getCurrentBean().addProperty(prop);
}
private TypeUse bindAttDecl(XSAttributeDecl decl) {
SimpleTypeBuilder stb = Ring.get(SimpleTypeBuilder.class);
stb.refererStack.push( decl );
try {
return stb.build(decl.getType());
} finally {
stb.refererStack.pop();
}
}
public void complexType(XSComplexType ct) {
CClass ctBean = selector.bindToType(ct,null,false);
if(getCurrentBean()!=ctBean)
// in some case complex type and element binds to the same class
// don't make it has-a. Just make it is-a.
getCurrentBean().setBaseClass(ctBean);
}
public void wildcard(XSWildcard xsWildcard) {
// element wildcards are processed by particle binders,
// so this one is for attribute wildcard.
getCurrentBean().hasAttributeWildcard(true);
}
public void modelGroupDecl(XSModelGroupDecl xsModelGroupDecl) {
// TODO
throw new UnsupportedOperationException();
}
public void modelGroup(XSModelGroup xsModelGroup) {
// TODO
throw new UnsupportedOperationException();
}
public void elementDecl(XSElementDecl xsElementDecl) {
// TODO
throw new UnsupportedOperationException();
}
public void simpleType(XSSimpleType type) {
createSimpleTypeProperty(type,"Value");
}
public void particle(XSParticle xsParticle) {
// TODO
throw new UnsupportedOperationException();
}
public void empty(XSContentType ct) {
// empty generates nothing
}
}

View File

@@ -0,0 +1,102 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.xmlschema;
import com.sun.tools.internal.xjc.reader.Ring;
import com.sun.tools.internal.xjc.reader.xmlschema.ct.ComplexTypeFieldBuilder;
import com.sun.xml.internal.bind.v2.TODO;
import com.sun.xml.internal.xsom.XSAttGroupDecl;
import com.sun.xml.internal.xsom.XSAttributeDecl;
import com.sun.xml.internal.xsom.XSAttributeUse;
import com.sun.xml.internal.xsom.XSComplexType;
import com.sun.xml.internal.xsom.XSContentType;
import com.sun.xml.internal.xsom.XSElementDecl;
import com.sun.xml.internal.xsom.XSModelGroup;
import com.sun.xml.internal.xsom.XSModelGroupDecl;
import com.sun.xml.internal.xsom.XSParticle;
import com.sun.xml.internal.xsom.XSSimpleType;
import com.sun.xml.internal.xsom.XSWildcard;
/**
* This is where a binding of a new class starts.
*
* @author Kohsuke Kawaguchi
*/
public final class BindRed extends ColorBinder {
private final ComplexTypeFieldBuilder ctBuilder = Ring.get(ComplexTypeFieldBuilder.class);
public void complexType(XSComplexType ct) {
ctBuilder.build(ct);
}
public void wildcard(XSWildcard xsWildcard) {
// TODO: implement this method later
// I guess we might allow this to be mapped to a generic element property ---
// not sure exactly how do we do it.
TODO.checkSpec();
throw new UnsupportedOperationException();
}
public void elementDecl(XSElementDecl e) {
SimpleTypeBuilder stb = Ring.get(SimpleTypeBuilder.class);
stb.refererStack.push(e); // referer is element
builder.ying(e.getType(),e);
stb.refererStack.pop();
}
public void simpleType(XSSimpleType type) {
SimpleTypeBuilder stb = Ring.get(SimpleTypeBuilder.class);
stb.refererStack.push(type); // referer is itself
createSimpleTypeProperty(type,"Value");
stb.refererStack.pop();
}
/*
Components that can never be mapped to a class
*/
public void attGroupDecl(XSAttGroupDecl ag) {
throw new IllegalStateException();
}
public void attributeDecl(XSAttributeDecl ad) {
throw new IllegalStateException();
}
public void attributeUse(XSAttributeUse au) {
throw new IllegalStateException();
}
public void empty(XSContentType xsContentType) {
throw new IllegalStateException();
}
public void modelGroupDecl(XSModelGroupDecl xsModelGroupDecl) {
throw new IllegalStateException();
}
public void modelGroup(XSModelGroup xsModelGroup) {
throw new IllegalStateException();
}
public void particle(XSParticle p) {
throw new IllegalStateException();
}
}

View File

@@ -0,0 +1,96 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.xmlschema;
import com.sun.xml.internal.xsom.XSAttGroupDecl;
import com.sun.xml.internal.xsom.XSAttributeDecl;
import com.sun.xml.internal.xsom.XSAttributeUse;
import com.sun.xml.internal.xsom.XSComplexType;
import com.sun.xml.internal.xsom.XSContentType;
import com.sun.xml.internal.xsom.XSElementDecl;
import com.sun.xml.internal.xsom.XSModelGroup;
import com.sun.xml.internal.xsom.XSModelGroupDecl;
import com.sun.xml.internal.xsom.XSParticle;
import com.sun.xml.internal.xsom.XSSimpleType;
import com.sun.xml.internal.xsom.XSWildcard;
/**
* @author Kohsuke Kawaguchi
*/
public final class BindYellow extends ColorBinder {
public void complexType(XSComplexType ct) {
}
public void wildcard(XSWildcard xsWildcard) {
// TODO: implement this method later
throw new UnsupportedOperationException();
}
public void elementDecl(XSElementDecl xsElementDecl) {
// TODO: implement this method later
throw new UnsupportedOperationException();
}
public void simpleType(XSSimpleType xsSimpleType) {
// TODO: implement this method later
throw new UnsupportedOperationException();
}
public void attributeDecl(XSAttributeDecl xsAttributeDecl) {
// TODO: implement this method later
throw new UnsupportedOperationException();
}
/*
Components that can never map to a type
*/
public void attGroupDecl(XSAttGroupDecl xsAttGroupDecl) {
throw new IllegalStateException();
}
public void attributeUse(XSAttributeUse use) {
throw new IllegalStateException();
}
public void modelGroupDecl(XSModelGroupDecl xsModelGroupDecl) {
throw new IllegalStateException();
}
public void modelGroup(XSModelGroup xsModelGroup) {
throw new IllegalStateException();
}
public void particle(XSParticle xsParticle) {
throw new IllegalStateException();
}
public void empty(XSContentType xsContentType) {
throw new IllegalStateException();
}
}

View File

@@ -0,0 +1,52 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.xmlschema;
import com.sun.tools.internal.xjc.reader.Ring;
/**
* Component accessible from {@link Ring}.
*
* @author Kohsuke Kawaguchi
*/
public abstract class BindingComponent {
protected BindingComponent() {
Ring.add(this);
}
//
//
// Accessor to common components.
//
//
protected final ErrorReporter getErrorReporter() {
return Ring.get(ErrorReporter.class);
}
protected final ClassSelector getClassSelector() {
return Ring.get(ClassSelector.class);
}
}

View File

@@ -0,0 +1,41 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.xmlschema;
import com.sun.tools.internal.xjc.model.CClassInfo;
import com.sun.tools.internal.xjc.model.CElement;
import com.sun.tools.internal.xjc.model.CElementInfo;
import com.sun.xml.internal.xsom.visitor.XSFunction;
/**
* Marker interface for an object that determines how to map
* a component to a class. If a component is mapped to a class,
* this object returns a {@link CClassInfo} pr {@link CElementInfo} object.
*
* Otherwise, return null.
*/
interface ClassBinder extends XSFunction<CElement> {
}

View File

@@ -0,0 +1,126 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.xmlschema;
import com.sun.tools.internal.xjc.model.CElement;
import com.sun.xml.internal.xsom.XSAnnotation;
import com.sun.xml.internal.xsom.XSAttGroupDecl;
import com.sun.xml.internal.xsom.XSAttributeDecl;
import com.sun.xml.internal.xsom.XSAttributeUse;
import com.sun.xml.internal.xsom.XSComplexType;
import com.sun.xml.internal.xsom.XSContentType;
import com.sun.xml.internal.xsom.XSElementDecl;
import com.sun.xml.internal.xsom.XSFacet;
import com.sun.xml.internal.xsom.XSIdentityConstraint;
import com.sun.xml.internal.xsom.XSModelGroup;
import com.sun.xml.internal.xsom.XSModelGroupDecl;
import com.sun.xml.internal.xsom.XSNotation;
import com.sun.xml.internal.xsom.XSParticle;
import com.sun.xml.internal.xsom.XSSchema;
import com.sun.xml.internal.xsom.XSSimpleType;
import com.sun.xml.internal.xsom.XSWildcard;
import com.sun.xml.internal.xsom.XSXPath;
/**
* {@link ClassBinder} that delegates the call to another {@link ClassBinder}.
*
* @author Kohsuke Kawaguchi (kk@kohsuke.org)
*/
abstract class ClassBinderFilter implements ClassBinder {
private final ClassBinder core;
protected ClassBinderFilter(ClassBinder core) {
this.core = core;
}
public CElement annotation(XSAnnotation xsAnnotation) {
return core.annotation(xsAnnotation);
}
public CElement attGroupDecl(XSAttGroupDecl xsAttGroupDecl) {
return core.attGroupDecl(xsAttGroupDecl);
}
public CElement attributeDecl(XSAttributeDecl xsAttributeDecl) {
return core.attributeDecl(xsAttributeDecl);
}
public CElement attributeUse(XSAttributeUse xsAttributeUse) {
return core.attributeUse(xsAttributeUse);
}
public CElement complexType(XSComplexType xsComplexType) {
return core.complexType(xsComplexType);
}
public CElement schema(XSSchema xsSchema) {
return core.schema(xsSchema);
}
public CElement facet(XSFacet xsFacet) {
return core.facet(xsFacet);
}
public CElement notation(XSNotation xsNotation) {
return core.notation(xsNotation);
}
public CElement simpleType(XSSimpleType xsSimpleType) {
return core.simpleType(xsSimpleType);
}
public CElement particle(XSParticle xsParticle) {
return core.particle(xsParticle);
}
public CElement empty(XSContentType xsContentType) {
return core.empty(xsContentType);
}
public CElement wildcard(XSWildcard xsWildcard) {
return core.wildcard(xsWildcard);
}
public CElement modelGroupDecl(XSModelGroupDecl xsModelGroupDecl) {
return core.modelGroupDecl(xsModelGroupDecl);
}
public CElement modelGroup(XSModelGroup xsModelGroup) {
return core.modelGroup(xsModelGroup);
}
public CElement elementDecl(XSElementDecl xsElementDecl) {
return core.elementDecl(xsElementDecl);
}
public CElement identityConstraint(XSIdentityConstraint xsIdentityConstraint) {
return core.identityConstraint(xsIdentityConstraint);
}
public CElement xpath(XSXPath xsxPath) {
return core.xpath(xsxPath);
}
}

View File

@@ -0,0 +1,485 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.xmlschema;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.Stack;
import com.sun.codemodel.internal.JCodeModel;
import com.sun.codemodel.internal.JJavaName;
import com.sun.codemodel.internal.JPackage;
import com.sun.codemodel.internal.util.JavadocEscapeWriter;
import com.sun.istack.internal.NotNull;
import com.sun.tools.internal.xjc.model.CBuiltinLeafInfo;
import com.sun.tools.internal.xjc.model.CClassInfo;
import com.sun.tools.internal.xjc.model.CClassInfoParent;
import com.sun.tools.internal.xjc.model.CElement;
import com.sun.tools.internal.xjc.model.CElementInfo;
import com.sun.tools.internal.xjc.model.CTypeInfo;
import com.sun.tools.internal.xjc.model.TypeUse;
import com.sun.tools.internal.xjc.model.CClass;
import com.sun.tools.internal.xjc.model.CNonElement;
import com.sun.tools.internal.xjc.reader.Ring;
import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIProperty;
import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BISchemaBinding;
import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.LocalScoping;
import com.sun.xml.internal.bind.v2.WellKnownNamespace;
import com.sun.xml.internal.xsom.XSComplexType;
import com.sun.xml.internal.xsom.XSComponent;
import com.sun.xml.internal.xsom.XSDeclaration;
import com.sun.xml.internal.xsom.XSElementDecl;
import com.sun.xml.internal.xsom.XSSchema;
import com.sun.xml.internal.xsom.XSSchemaSet;
import com.sun.xml.internal.xsom.XSSimpleType;
import com.sun.xml.internal.xsom.XSType;
import com.sun.xml.internal.xsom.impl.util.SchemaWriter;
import com.sun.xml.internal.xsom.util.ComponentNameFunction;
import org.xml.sax.Locator;
/**
* Manages association between {@link XSComponent}s and generated
* {@link CTypeInfo}s.
*
* <p>
* This class determines which component is mapped to (or is not mapped to)
* what types.
*
* @author
* Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
*/
public final class ClassSelector extends BindingComponent {
/** Center of owner classes. */
private final BGMBuilder builder = Ring.get(BGMBuilder.class);
/**
* Map from XSComponents to {@link Binding}s. Keeps track of all
* content interfaces that are already built or being built.
*/
private final Map<XSComponent,Binding> bindMap = new HashMap<XSComponent,Binding>();
/**
* UGLY HACK.
* <p>
* To avoid cyclic dependency between binding elements and types,
* we need additional markers that tell which elements are definitely not bound
* to a class.
* <p>
* the cyclic dependency is as follows:
* elements need to bind its types first, because otherwise it can't
* determine T of JAXBElement<T>.
* OTOH, types need to know whether its parent is bound to a class to decide
* which class name to use.
*/
/*package*/ final Map<XSComponent,CElementInfo> boundElements = new HashMap<XSComponent,CElementInfo>();
/**
* A list of {@link Binding}s object that needs to be built.
*/
private final Stack<Binding> bindQueue = new Stack<Binding>();
/**
* {@link CClassInfo}s that are already {@link Binding#build() built}.
*/
private final Set<CClassInfo> built = new HashSet<CClassInfo>();
/**
* Object that determines components that are mapped
* to classes.
*/
private final ClassBinder classBinder;
/**
* {@link CClassInfoParent}s that determines where a new class
* should be created.
*/
private final Stack<CClassInfoParent> classScopes = new Stack<CClassInfoParent>();
/**
* The component that is being bound to {@link #currentBean}.
*/
private XSComponent currentRoot;
/**
* The bean representation we are binding right now.
*/
private CClassInfo currentBean;
private final class Binding {
private final XSComponent sc;
private final CTypeInfo bean;
public Binding(XSComponent sc, CTypeInfo bean) {
this.sc = sc;
this.bean = bean;
}
void build() {
if(!(this.bean instanceof CClassInfo))
return; // no need to "build"
CClassInfo bean = (CClassInfo)this.bean;
if(!built.add(bean))
return; // already built
for( String reservedClassName : reservedClassNames ) {
if( bean.getName().equals(reservedClassName) ) {
getErrorReporter().error( sc.getLocator(),
Messages.ERR_RESERVED_CLASS_NAME, reservedClassName );
break;
}
}
// if this schema component is an element declaration
// and it satisfies a set of conditions specified in the spec,
// this class will receive a constructor.
if(needValueConstructor(sc)) {
// TODO: fragile. There is no guarantee that the property name
// is in fact "value".
bean.addConstructor("value");
}
if(bean.javadoc==null)
addSchemaFragmentJavadoc(bean,sc);
// build the body
if(builder.getGlobalBinding().getFlattenClasses()==LocalScoping.NESTED)
pushClassScope(bean);
else
pushClassScope(bean.parent());
XSComponent oldRoot = currentRoot;
CClassInfo oldBean = currentBean;
currentRoot = sc;
currentBean = bean;
sc.visit(Ring.get(BindRed.class));
currentBean = oldBean;
currentRoot = oldRoot;
popClassScope();
// acknowledge property customization on this schema component,
// since it is OK to have a customization at the point of declaration
// even when no one is using it.
BIProperty prop = builder.getBindInfo(sc).get(BIProperty.class);
if(prop!=null) prop.markAsAcknowledged();
}
}
// should be instanciated only from BGMBuilder.
public ClassSelector() {
classBinder = new Abstractifier(new DefaultClassBinder());
Ring.add(ClassBinder.class,classBinder);
classScopes.push(null); // so that the getClassFactory method returns null
XSComplexType anyType = Ring.get(XSSchemaSet.class).getComplexType(WellKnownNamespace.XML_SCHEMA,"anyType");
bindMap.put(anyType,new Binding(anyType,CBuiltinLeafInfo.ANYTYPE));
}
/** Gets the current class scope. */
public final CClassInfoParent getClassScope() {
assert !classScopes.isEmpty();
return classScopes.peek();
}
public final void pushClassScope( CClassInfoParent clsFctry ) {
assert clsFctry!=null;
classScopes.push(clsFctry);
}
public final void popClassScope() {
classScopes.pop();
}
public XSComponent getCurrentRoot() {
return currentRoot;
}
public CClassInfo getCurrentBean() {
return currentBean;
}
/**
* Checks if the given component is bound to a class.
*/
public final CElement isBound( XSElementDecl x, XSComponent referer ) {
CElementInfo r = boundElements.get(x);
if(r!=null)
return r;
return bindToType(x,referer);
}
/**
* Checks if the given component is being mapped to a type.
* If so, build that type and return that object.
* If it is not being mapped to a type item, return null.
*/
public CTypeInfo bindToType( XSComponent sc, XSComponent referer ) {
return _bindToClass(sc,referer,false);
}
//
// some schema components are guaranteed to map to a particular CTypeInfo.
// the following versions capture those constraints in the signature
// and making the bindToType invocation more type safe.
//
public CElement bindToType( XSElementDecl e, XSComponent referer ) {
return (CElement)_bindToClass(e,referer,false);
}
public CClass bindToType( XSComplexType t, XSComponent referer, boolean cannotBeDelayed ) {
// this assumption that a complex type always binds to a ClassInfo
// does not hold for xs:anyType --- our current approach of handling
// this idiosynchracy is to make sure that xs:anyType doesn't use
// this codepath.
return (CClass)_bindToClass(t,referer,cannotBeDelayed);
}
public TypeUse bindToType( XSType t, XSComponent referer ) {
if(t instanceof XSSimpleType) {
return Ring.get(SimpleTypeBuilder.class).build((XSSimpleType)t);
} else
return (CNonElement)_bindToClass(t,referer,false);
}
/**
* The real meat of the "bindToType" code.
*
* @param cannotBeDelayed
* if the binding of the body of the class cannot be defered
* and needs to be done immediately. If the flag is false,
* the binding of the body will be done later, to avoid
* cyclic binding problem.
* @param referer
* The component that refers to <tt>sc</tt>. This can be null,
* if figuring out the referer is too hard, in which case
* the error message might be less user friendly.
*/
// TODO: consider getting rid of "cannotBeDelayed"
CTypeInfo _bindToClass( @NotNull XSComponent sc, XSComponent referer, boolean cannotBeDelayed ) {
// check if this class is already built.
if(!bindMap.containsKey(sc)) {
// craete a bind task
// if this is a global declaration, make sure they will be generated
// under a package.
boolean isGlobal = false;
if( sc instanceof XSDeclaration ) {
isGlobal = ((XSDeclaration)sc).isGlobal();
if( isGlobal )
pushClassScope( new CClassInfoParent.Package(
getPackage(((XSDeclaration)sc).getTargetNamespace())) );
}
// otherwise check if this component should become a class.
CElement bean = sc.apply(classBinder);
if( isGlobal )
popClassScope();
if(bean==null)
return null;
// can this namespace generate a class?
if (bean instanceof CClassInfo) {
XSSchema os = sc.getOwnerSchema();
BISchemaBinding sb = builder.getBindInfo(os).get(BISchemaBinding.class);
if(sb!=null && !sb.map) {
// nope
getErrorReporter().error(sc.getLocator(),
Messages.ERR_REFERENCE_TO_NONEXPORTED_CLASS, sc.apply( new ComponentNameFunction() ) );
getErrorReporter().error(sb.getLocation(),
Messages.ERR_REFERENCE_TO_NONEXPORTED_CLASS_MAP_FALSE, os.getTargetNamespace() );
if(referer!=null)
getErrorReporter().error(referer.getLocator(),
Messages.ERR_REFERENCE_TO_NONEXPORTED_CLASS_REFERER, referer.apply( new ComponentNameFunction() ) );
}
}
queueBuild( sc, bean );
}
Binding bind = bindMap.get(sc);
if( cannotBeDelayed )
bind.build();
return bind.bean;
}
/**
* Runs all the pending build tasks.
*/
public void executeTasks() {
while( bindQueue.size()!=0 )
bindQueue.pop().build();
}
/**
* Determines if the given component needs to have a value
* constructor (a constructor that takes a parmater.) on ObjectFactory.
*/
private boolean needValueConstructor( XSComponent sc ) {
if(!(sc instanceof XSElementDecl)) return false;
XSElementDecl decl = (XSElementDecl)sc;
if(!decl.getType().isSimpleType()) return false;
return true;
}
private static final String[] reservedClassNames = new String[]{"ObjectFactory"};
public void queueBuild( XSComponent sc, CElement bean ) {
// it is an error if the same component is built twice,
// or the association is modified.
Binding b = new Binding(sc,bean);
bindQueue.push(b);
Binding old = bindMap.put(sc, b);
assert old==null || old.bean==bean;
}
/**
* Copies a schema fragment into the javadoc of the generated class.
*/
private void addSchemaFragmentJavadoc( CClassInfo bean, XSComponent sc ) {
// first, pick it up from <documentation> if any.
String doc = builder.getBindInfo(sc).getDocumentation();
if(doc!=null)
append(bean, doc);
// then the description of where this component came from
Locator loc = sc.getLocator();
String fileName = null;
if(loc!=null) {
fileName = loc.getPublicId();
if(fileName==null)
fileName = loc.getSystemId();
}
if(fileName==null) fileName="";
String lineNumber=Messages.format( Messages.JAVADOC_LINE_UNKNOWN);
if(loc!=null && loc.getLineNumber()!=-1)
lineNumber = String.valueOf(loc.getLineNumber());
String componentName = sc.apply( new ComponentNameFunction() );
String jdoc = Messages.format( Messages.JAVADOC_HEADING, componentName, fileName, lineNumber );
append(bean,jdoc);
// then schema fragment
StringWriter out = new StringWriter();
out.write("<pre>\n");
SchemaWriter sw = new SchemaWriter(new JavadocEscapeWriter(out));
sc.visit(sw);
out.write("</pre>");
append(bean,out.toString());
}
private void append(CClassInfo bean, String doc) {
if(bean.javadoc==null)
bean.javadoc = doc+'\n';
else
bean.javadoc += '\n'+doc+'\n';
}
/**
* Set of package names that are tested (set of <code>String</code>s.)
*
* This set is used to avoid duplicating "incorrect package name"
* errors.
*/
private static Set<String> checkedPackageNames = new HashSet<String>();
/**
* Gets the Java package to which classes from
* this namespace should go.
*
* <p>
* Usually, the getOuterClass method should be used
* to determine where to put a class.
*/
public JPackage getPackage(String targetNamespace) {
XSSchema s = Ring.get(XSSchemaSet.class).getSchema(targetNamespace);
BISchemaBinding sb =
builder.getBindInfo(s).get(BISchemaBinding.class);
if(sb!=null) sb.markAsAcknowledged();
String name = null;
// "-p" takes precedence over everything else
if( builder.defaultPackage1 != null )
name = builder.defaultPackage1;
// use the <jaxb:package> customization
if( name == null && sb!=null && sb.getPackageName()!=null )
name = sb.getPackageName();
// the JAX-RPC option goes below the <jaxb:package>
if( name == null && builder.defaultPackage2 != null )
name = builder.defaultPackage2;
// generate the package name from the targetNamespace
if( name == null )
name = builder.getNameConverter().toPackageName( targetNamespace );
// hardcode a package name because the code doesn't compile
// if it generated into the default java package
if( name == null )
name = "generated"; // the last resort
// check if the package name is a valid name.
if( checkedPackageNames.add(name) ) {
// this is the first time we hear about this package name.
if( !JJavaName.isJavaPackageName(name) )
// TODO: s.getLocator() is not very helpful.
// ideally, we'd like to use the locator where this package name
// comes from.
getErrorReporter().error(s.getLocator(),
Messages.ERR_INCORRECT_PACKAGE_NAME, targetNamespace, name );
}
return Ring.get(JCodeModel.class)._package(name);
}
}

View File

@@ -0,0 +1,68 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.xmlschema;
import org.xml.sax.Locator;
/**
* Details of a name collision.
*
* @author
* Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
*/
final class CollisionInfo {
private final String name;
private final Locator source1;
private final Locator source2;
public CollisionInfo(String name, Locator source1, Locator source2) {
this.name = name;
this.source1 = source1;
this.source2 = source2;
}
/**
* Returns a localized message that describes the collision.
*/
public String toString() {
return Messages.format( Messages.MSG_COLLISION_INFO,
name, printLocator(source1), printLocator(source2) );
}
private String printLocator(Locator loc) {
if( loc==null ) return "";
int line = loc.getLineNumber();
String sysId = loc.getSystemId();
if(sysId==null) sysId = Messages.format(Messages.MSG_UNKNOWN_FILE);
if( line!=-1 )
return Messages.format( Messages.MSG_LINE_X_OF_Y,
Integer.toString(line), sysId );
else
return sysId;
}
}

View File

@@ -0,0 +1,93 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.xmlschema;
import com.sun.tools.internal.xjc.model.CClassInfo;
import com.sun.tools.internal.xjc.model.CPropertyInfo;
import com.sun.tools.internal.xjc.reader.Ring;
import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIProperty;
import com.sun.xml.internal.xsom.XSAnnotation;
import com.sun.xml.internal.xsom.XSComponent;
import com.sun.xml.internal.xsom.XSFacet;
import com.sun.xml.internal.xsom.XSIdentityConstraint;
import com.sun.xml.internal.xsom.XSNotation;
import com.sun.xml.internal.xsom.XSSchema;
import com.sun.xml.internal.xsom.XSSimpleType;
import com.sun.xml.internal.xsom.XSXPath;
import com.sun.xml.internal.xsom.visitor.XSVisitor;
/**
* @author Kohsuke Kawaguchi
*/
abstract class ColorBinder extends BindingComponent implements XSVisitor {
protected final BGMBuilder builder = Ring.get(BGMBuilder.class);
protected final ClassSelector selector = getClassSelector();
protected final CClassInfo getCurrentBean() {
return selector.getCurrentBean();
}
protected final XSComponent getCurrentRoot() {
return selector.getCurrentRoot();
}
protected final void createSimpleTypeProperty(XSSimpleType type,String propName) {
BIProperty prop = BIProperty.getCustomization(type);
SimpleTypeBuilder stb = Ring.get(SimpleTypeBuilder.class);
// since we are building the simple type here, use buildDef
CPropertyInfo p = prop.createValueProperty(propName,false,type,stb.buildDef(type),BGMBuilder.getName(type));
getCurrentBean().addProperty(p);
}
public final void annotation(XSAnnotation xsAnnotation) {
throw new IllegalStateException();
}
public final void schema(XSSchema xsSchema) {
throw new IllegalStateException();
}
public final void facet(XSFacet xsFacet) {
throw new IllegalStateException();
}
public final void notation(XSNotation xsNotation) {
throw new IllegalStateException();
}
public final void identityConstraint(XSIdentityConstraint xsIdentityConstraint) {
throw new IllegalStateException();
}
public final void xpath(XSXPath xsxPath) {
throw new IllegalStateException();
}
}

View File

@@ -0,0 +1,558 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.xmlschema;
import static com.sun.tools.internal.xjc.reader.xmlschema.BGMBuilder.getName;
import java.util.Set;
import javax.xml.namespace.QName;
import com.sun.codemodel.internal.JJavaName;
import com.sun.codemodel.internal.JPackage;
import com.sun.istack.internal.NotNull;
import com.sun.istack.internal.Nullable;
import com.sun.tools.internal.xjc.ErrorReceiver;
import com.sun.tools.internal.xjc.model.CClassInfo;
import com.sun.tools.internal.xjc.model.CClassInfoParent;
import com.sun.tools.internal.xjc.model.CClassRef;
import com.sun.tools.internal.xjc.model.CCustomizations;
import com.sun.tools.internal.xjc.model.CElement;
import com.sun.tools.internal.xjc.model.CElementInfo;
import com.sun.tools.internal.xjc.model.Model;
import com.sun.tools.internal.xjc.reader.Ring;
import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIClass;
import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIGlobalBinding;
import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BISchemaBinding;
import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BindInfo;
import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIXSubstitutable;
import com.sun.tools.internal.xjc.reader.xmlschema.ct.ComplexTypeFieldBuilder;
import com.sun.tools.internal.xjc.reader.xmlschema.ct.ComplexTypeBindingMode;
import com.sun.xml.internal.xsom.XSAnnotation;
import com.sun.xml.internal.xsom.XSAttGroupDecl;
import com.sun.xml.internal.xsom.XSAttributeDecl;
import com.sun.xml.internal.xsom.XSAttributeUse;
import com.sun.xml.internal.xsom.XSComplexType;
import com.sun.xml.internal.xsom.XSComponent;
import com.sun.xml.internal.xsom.XSContentType;
import com.sun.xml.internal.xsom.XSDeclaration;
import com.sun.xml.internal.xsom.XSElementDecl;
import com.sun.xml.internal.xsom.XSFacet;
import com.sun.xml.internal.xsom.XSIdentityConstraint;
import com.sun.xml.internal.xsom.XSModelGroup;
import com.sun.xml.internal.xsom.XSModelGroupDecl;
import com.sun.xml.internal.xsom.XSNotation;
import com.sun.xml.internal.xsom.XSParticle;
import com.sun.xml.internal.xsom.XSSchema;
import com.sun.xml.internal.xsom.XSSchemaSet;
import com.sun.xml.internal.xsom.XSSimpleType;
import com.sun.xml.internal.xsom.XSType;
import com.sun.xml.internal.xsom.XSWildcard;
import com.sun.xml.internal.xsom.XSXPath;
import org.xml.sax.Locator;
/**
* Default classBinder implementation. Honors &lt;jaxb:class> customizations
* and default bindings.
*/
final class DefaultClassBinder implements ClassBinder
{
private final SimpleTypeBuilder stb = Ring.get(SimpleTypeBuilder.class);
private final Model model = Ring.get(Model.class);
protected final BGMBuilder builder = Ring.get(BGMBuilder.class);
protected final ClassSelector selector = Ring.get(ClassSelector.class);
protected final XSSchemaSet schemas = Ring.get(XSSchemaSet.class);
public CElement attGroupDecl(XSAttGroupDecl decl) {
return allow(decl,decl.getName());
}
public CElement attributeDecl(XSAttributeDecl decl) {
return allow(decl,decl.getName());
}
public CElement modelGroup(XSModelGroup mgroup) {
return never();
}
public CElement modelGroupDecl(XSModelGroupDecl decl) {
return never();
}
public CElement complexType(XSComplexType type) {
CElement ci = allow(type,type.getName());
if(ci!=null) return ci;
// no customization is given -- do as the default binding.
BindInfo bi = builder.getBindInfo(type);
if(type.isGlobal()) {
QName tagName = null;
String className = deriveName(type);
Locator loc = type.getLocator();
if(getGlobalBinding().isSimpleMode()) {
// in the simple mode, we may optimize it away
XSElementDecl referer = getSoleElementReferer(type);
if(referer!=null && isCollapsable(referer)) {
// if a global element contains
// a collpsable complex type, we bind this element to a named one
// and collapses element and complex type.
tagName = getName(referer);
className = deriveName(referer);
loc = referer.getLocator();
}
}
// by default, global ones get their own classes.
JPackage pkg = selector.getPackage(type.getTargetNamespace());
return new CClassInfo(model,pkg,className, loc,getTypeName(type),tagName,type,bi.toCustomizationList());
} else {
XSElementDecl element = type.getScope();
if( element.isGlobal() && isCollapsable(element)) {
if(builder.getBindInfo(element).get(BIClass.class)!=null)
// the parent element was bound to a class. Don't bind this again to
// cause unnecessary wrapping
return null;
// generate one class from element and complex type together.
// this needs to be done before selector.isBound to avoid infinite recursion.
// but avoid doing so when the element is mapped to a class,
// which creates unnecessary classes
return new CClassInfo( model, selector.getClassScope(),
deriveName(element), element.getLocator(), null,
getName(element), element, bi.toCustomizationList() );
}
CElement parentType = selector.isBound(element,type);
String className;
CClassInfoParent scope;
if( parentType!=null
&& parentType instanceof CElementInfo
&& ((CElementInfo)parentType).hasClass() ) {
// special case where we put a nested 'Type' element
scope = (CElementInfo)parentType;
className = "Type";
} else {
// since the parent element isn't bound to a type, merge the customizations associated to it, too.
// custs = CCustomizations.merge( custs, builder.getBindInfo(type.getScope()).toCustomizationList());
className = builder.getNameConverter().toClassName(element.getName());
BISchemaBinding sb = builder.getBindInfo(
type.getOwnerSchema() ).get(BISchemaBinding.class);
if(sb!=null) className = sb.mangleAnonymousTypeClassName(className);
scope = selector.getClassScope();
}
return new CClassInfo(model, scope, className, type.getLocator(), null, null, type, bi.toCustomizationList() );
}
}
private QName getTypeName(XSComplexType type) {
if(type.getRedefinedBy()!=null)
return null;
else
return getName(type);
}
/**
* Returns true if the complex type of the given element can be "optimized away"
* and unified with its parent element decl to form a single class.
*/
private boolean isCollapsable(XSElementDecl decl) {
XSType type = decl.getType();
if(!type.isComplexType())
return false; // not a complex type
if(decl.getSubstitutables().size()>1 || decl.getSubstAffiliation()!=null)
// because element substitution calls for a proper JAXBElement hierarchy
return false;
if(decl.isNillable())
// because nillable needs JAXBElement to represent correctly
return false;
BIXSubstitutable bixSubstitutable = builder.getBindInfo(decl).get(BIXSubstitutable.class);
if(bixSubstitutable !=null) {
// see https://jaxb.dev.java.net/issues/show_bug.cgi?id=289
// this customization forces non-collapsing behavior.
bixSubstitutable.markAsAcknowledged();
return false;
}
if( getGlobalBinding().isSimpleMode() && decl.isGlobal()) {
// in the simple mode, we do more aggressive optimization, and get rid of
// a complex type class if it's only used once from a global element
XSElementDecl referer = getSoleElementReferer(decl.getType());
if(referer!=null) {
assert referer==decl; // I must be the sole referer
return true;
}
}
if(!type.isLocal() || !type.isComplexType())
return false;
return true;
}
/**
* If only one global {@link XSElementDecl} is refering to {@link XSType},
* return that element, otherwise null.
*/
private @Nullable XSElementDecl getSoleElementReferer(@NotNull XSType t) {
Set<XSComponent> referer = builder.getReferer(t);
XSElementDecl sole = null;
for (XSComponent r : referer) {
if(r instanceof XSElementDecl) {
XSElementDecl x = (XSElementDecl) r;
if(!x.isGlobal())
// local element references can be ignored, as their names are either given
// by the property, or by the JAXBElement (for things like mixed contents)
continue;
if(sole==null) sole=x;
else return null; // more than one
} else {
// if another type refers to this type, that means
// this type has a sub-type, so type substitution is possible now.
return null;
}
}
return sole;
}
public CElement elementDecl(XSElementDecl decl) {
CElement r = allow(decl,decl.getName());
if(r==null) {
QName tagName = getName(decl);
CCustomizations custs = builder.getBindInfo(decl).toCustomizationList();
if(decl.isGlobal()) {
if(isCollapsable(decl)) {
// we want the returned type to be built as a complex type,
// so the binding cannot be delayed.
return selector.bindToType(decl.getType().asComplexType(),decl,true);
} else {
String className = null;
if(getGlobalBinding().isGenerateElementClass())
className = deriveName(decl);
// otherwise map global elements to JAXBElement
CElementInfo cei = new CElementInfo(
model, tagName, selector.getClassScope(), className, custs, decl.getLocator());
selector.boundElements.put(decl,cei);
stb.refererStack.push(decl); // referer is element
cei.initContentType( selector.bindToType(decl.getType(),decl), decl, decl.getDefaultValue() );
stb.refererStack.pop();
r = cei;
}
}
}
// have the substitution member derive from the substitution head
XSElementDecl top = decl.getSubstAffiliation();
if(top!=null) {
CElement topci = selector.bindToType(top,decl);
if(r instanceof CClassInfo && topci instanceof CClassInfo)
((CClassInfo)r).setBaseClass((CClassInfo)topci);
if (r instanceof CElementInfo && topci instanceof CElementInfo)
((CElementInfo)r).setSubstitutionHead((CElementInfo)topci);
}
return r;
}
public CClassInfo empty( XSContentType ct ) { return null; }
public CClassInfo identityConstraint(XSIdentityConstraint xsIdentityConstraint) {
return never();
}
public CClassInfo xpath(XSXPath xsxPath) {
return never();
}
public CClassInfo attributeUse(XSAttributeUse use) {
return never();
}
public CElement simpleType(XSSimpleType type) {
CElement c = allow(type,type.getName());
if(c!=null) return c;
if(getGlobalBinding().isSimpleTypeSubstitution() && type.isGlobal()) {
return new CClassInfo(model,selector.getClassScope(),
deriveName(type), type.getLocator(), getName(type), null, type, null );
}
return never();
}
public CClassInfo particle(XSParticle particle) {
return never();
}
public CClassInfo wildcard(XSWildcard wc) {
return never();
}
// these methods won't be used
public CClassInfo annotation(XSAnnotation annon) {
assert false;
return null;
}
public CClassInfo notation(XSNotation not) {
assert false;
return null;
}
public CClassInfo facet(XSFacet decl) {
assert false;
return null;
}
public CClassInfo schema(XSSchema schema) {
assert false;
return null;
}
/**
* Makes sure that the component doesn't carry a {@link BIClass}
* customization.
*
* @return
* return value is unused. Since most of the caller needs to
* return null, to make the code a little bit shorter, this
* method always return null (so that the caller can always
* say <code>return never(sc);</code>.
*/
private CClassInfo never() {
// all we need to do here is just not to acknowledge
// any class customization. Then this class customization
// will be reported as an error later when we check all
// unacknowledged customizations.
// BIDeclaration cust=owner.getBindInfo(component).get(BIClass.NAME);
// if(cust!=null) {
// // error
// owner.errorReporter.error(
// cust.getLocation(),
// "test {0}", NameGetter.get(component) );
// }
return null;
}
/**
* Checks if a component carries a customization to map it to a class.
* If so, make it a class.
*
* @param defaultBaseName
* The token which will be used as the basis of the class name
* if the class name is not specified in the customization.
* This is usually the name of an element declaration, and so on.
*
* This parameter can be null, in that case it would be an error
* if a name is not given by the customization.
*/
private CElement allow( XSComponent component, String defaultBaseName ) {
BIClass decl = null;
if(component instanceof XSComplexType) {
XSType complexType = (XSType)component;
BIClass lastFoundRecursiveBiClass = null;
if(complexType.getName() != null) {
while( ! schemas.getAnyType().equals(complexType)) {
BindInfo bindInfo = builder.getBindInfo(complexType);
BIClass biClass = bindInfo.get(BIClass.class);
if(biClass != null && "true".equals(biClass.getRecursive()))
lastFoundRecursiveBiClass = biClass;
complexType = complexType.getBaseType();
}
}
// use this as biclass for current component
decl = lastFoundRecursiveBiClass;
}
BindInfo bindInfo = builder.getBindInfo(component);
if(decl == null) {
decl = bindInfo.get(BIClass.class);
if(decl==null) return null;
}
decl.markAsAcknowledged();
// first consider binding to the class reference.
String ref = decl.getExistingClassRef();
if(ref!=null) {
if(!JJavaName.isFullyQualifiedClassName(ref)) {
Ring.get(ErrorReceiver.class).error( decl.getLocation(),
Messages.format(Messages.ERR_INCORRECT_CLASS_NAME,ref) );
// recover by ignoring @ref
} else {
if(component instanceof XSComplexType) {
// UGLY UGLY UGLY
// since we are not going to bind this complex type, we need to figure out
// its binding mode without actually binding it (and also expose this otherwise
// hidden mechanism into this part of the code.)
//
// this code is potentially dangerous as the base class might have been bound
// in different ways. To be correct, we need to figure out how the content type
// would have been bound, from the schema.
Ring.get(ComplexTypeFieldBuilder.class).recordBindingMode(
(XSComplexType)component, ComplexTypeBindingMode.NORMAL
);
}
return new CClassRef(model, component, decl, bindInfo.toCustomizationList() );
}
}
String clsName = decl.getClassName();
if(clsName==null) {
// if the customiztion doesn't give us a name, derive one
// from the current component.
if( defaultBaseName==null ) {
Ring.get(ErrorReceiver.class).error( decl.getLocation(),
Messages.format(Messages.ERR_CLASS_NAME_IS_REQUIRED) );
// recover by generating a pseudo-random name
defaultBaseName = "undefined"+component.hashCode();
}
clsName = builder.deriveName( defaultBaseName, component );
} else {
if( !JJavaName.isJavaIdentifier(clsName) ) {
// not a valid Java class name
Ring.get(ErrorReceiver.class).error( decl.getLocation(),
Messages.format( Messages.ERR_INCORRECT_CLASS_NAME, clsName ));
// recover by a dummy name
clsName = "Undefined"+component.hashCode();
}
}
QName typeName = null;
QName elementName = null;
if(component instanceof XSType) {
XSType t = (XSType) component;
typeName = getName(t);
}
if (component instanceof XSElementDecl) {
XSElementDecl e = (XSElementDecl) component;
elementName = getName(e);
}
if (component instanceof XSElementDecl && !isCollapsable((XSElementDecl)component)) {
XSElementDecl e = ((XSElementDecl)component);
CElementInfo cei = new CElementInfo(model, elementName,
selector.getClassScope(), clsName,
bindInfo.toCustomizationList(), decl.getLocation() );
selector.boundElements.put(e,cei);
stb.refererStack.push(component); // referer is element
cei.initContentType(
selector.bindToType(e.getType(),e),
e,e.getDefaultValue());
stb.refererStack.pop();
return cei;
// TODO: support javadoc and userSpecifiedImplClass
} else {
CClassInfo bt = new CClassInfo(model,selector.getClassScope(),
clsName, decl.getLocation(), typeName, elementName, component, bindInfo.toCustomizationList() );
// set javadoc class comment.
if(decl.getJavadoc()!=null )
bt.javadoc = decl.getJavadoc()+"\n\n";
// add extra blank lines so that the schema fragment
// and user-specified javadoc would be separated
// if the implClass is given, set it to ClassItem
String implClass = decl.getUserSpecifiedImplClass();
if( implClass!=null )
bt.setUserSpecifiedImplClass( implClass );
return bt;
}
}
private BIGlobalBinding getGlobalBinding() {
return builder.getGlobalBinding();
}
/**
* Derives a name from a schema component.
* Use the name of the schema component as the default name.
*/
private String deriveName( XSDeclaration comp ) {
return builder.deriveName( comp.getName(), comp );
}
/**
* Derives a name from a schema component.
* For complex types, we take redefinition into account when
* deriving a default name.
*/
private String deriveName( XSComplexType comp ) {
String seed = builder.deriveName( comp.getName(), comp );
int cnt = comp.getRedefinedCount();
for( ; cnt>0; cnt-- )
seed = "Original"+seed;
return seed;
}
}

View File

@@ -0,0 +1,392 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.xmlschema;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import com.sun.tools.internal.xjc.model.CClassInfo;
import com.sun.tools.internal.xjc.model.CPropertyInfo;
import com.sun.tools.internal.xjc.model.CReferencePropertyInfo;
import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIProperty;
import com.sun.xml.internal.xsom.XSElementDecl;
import com.sun.xml.internal.xsom.XSModelGroup;
import com.sun.xml.internal.xsom.XSModelGroupDecl;
import com.sun.xml.internal.xsom.XSParticle;
import com.sun.xml.internal.xsom.XSTerm;
import com.sun.xml.internal.xsom.XSWildcard;
import com.sun.xml.internal.xsom.visitor.XSTermVisitor;
import java.math.BigInteger;
/**
* {@link ParticleBinder} that follows the JAXB spec.
*
* @author Kohsuke Kawaguchi
*/
final class DefaultParticleBinder extends ParticleBinder {
@Override
public void build( XSParticle p, Collection<XSParticle> forcedProps ) {
Checker checker = checkCollision(p,forcedProps);
if(checker.hasNameCollision()) {
CReferencePropertyInfo prop = new CReferencePropertyInfo(
getCurrentBean().getBaseClass()==null?"Content":"Rest",
true, false, false, p,
builder.getBindInfo(p).toCustomizationList(),
p.getLocator(), false, false, false);
RawTypeSetBuilder.build(p,false).addTo(prop);
prop.javadoc = Messages.format( Messages.MSG_FALLBACK_JAVADOC,
checker.getCollisionInfo().toString() );
getCurrentBean().addProperty(prop);
} else {
new Builder(checker.markedParticles).particle(p);
}
}
@Override
public boolean checkFallback( XSParticle p ) {
return checkCollision(p,Collections.<XSParticle>emptyList()).hasNameCollision();
}
private Checker checkCollision( XSParticle p, Collection<XSParticle> forcedProps ) {
// scan the tree by a checker.
Checker checker = new Checker(forcedProps);
CClassInfo superClass = getCurrentBean().getBaseClass();
if(superClass!=null)
checker.readSuperClass(superClass);
checker.particle(p);
return checker;
}
/**
* Marks particles that need to be mapped to properties,
* by reading customization info.
*/
private final class Checker implements XSTermVisitor {
Checker(Collection<XSParticle> forcedProps) {
this.forcedProps = forcedProps;
}
boolean hasNameCollision() {
return collisionInfo!=null;
}
CollisionInfo getCollisionInfo() {
return collisionInfo;
}
/**
* If a collision is found, this field will be non-null.
*/
private CollisionInfo collisionInfo = null;
/** Used to check name collision. */
private final NameCollisionChecker cchecker = new NameCollisionChecker();
/**
* @see DefaultParticleBinder#build(XSParticle, Collection<com.sun.xml.internal.xsom.XSParticle>)
*/
private final Collection<XSParticle> forcedProps;
public void particle( XSParticle p ) {
if(getLocalPropCustomization(p)!=null
|| builder.getLocalDomCustomization(p)!=null) {
// if a property customization is specfied,
// check that value and turn around.
check(p);
mark(p);
return;
}
XSTerm t = p.getTerm();
if(p.isRepeated() && (t.isModelGroup() || t.isModelGroupDecl())) {
// a repeated model group gets its own property
mark(p);
return;
}
if(forcedProps.contains(p)) {
// this particle must become a property
mark(p);
return;
}
outerParticle = p;
t.visit(this);
}
/**
* This field points to the parent XSParticle.
* The value is only valid when we are processing XSTerm.
*/
private XSParticle outerParticle;
public void elementDecl(XSElementDecl decl) {
check(outerParticle);
mark(outerParticle);
}
public void modelGroup(XSModelGroup mg) {
// choice gets mapped to a property
if(mg.getCompositor()== XSModelGroup.Compositor.CHOICE && builder.getGlobalBinding().isChoiceContentPropertyEnabled()) {
mark(outerParticle);
return;
}
for( XSParticle child : mg.getChildren() )
particle(child);
}
public void modelGroupDecl(XSModelGroupDecl decl) {
modelGroup(decl.getModelGroup());
}
public void wildcard(XSWildcard wc) {
mark(outerParticle);
}
void readSuperClass( CClassInfo ci ) {
cchecker.readSuperClass(ci);
}
/**
* Checks the name collision of a newly found particle.
*/
private void check( XSParticle p ) {
if( collisionInfo==null )
collisionInfo = cchecker.check(p);
}
/**
* Marks a particle that it's going to be mapped to a property.
*/
private void mark( XSParticle p ) {
markedParticles.put(p,computeLabel(p));
}
/**
* Marked particles.
*
* A map from XSParticle to its label.
*/
public final Map<XSParticle,String> markedParticles = new HashMap<XSParticle,String>();
/**
* Checks name collisions among particles that belong to sequences.
*/
private final class NameCollisionChecker {
/**
* Checks the label conflict of a particle.
* This method shall be called for each marked particle.
*
* @return
* a description of a collision if a name collision is
* found. Otherwise null.
*/
CollisionInfo check( XSParticle p ) {
// this can be used for particles with a property customization,
// which may not have element declaration as its term.
// // we only check particles with element declarations.
// _assert( p.getTerm().isElementDecl() );
String label = computeLabel(p);
if( occupiedLabels.containsKey(label) ) {
// collide with occupied labels
return new CollisionInfo(label,p.getLocator(),
occupiedLabels.get(label).locator);
}
for( XSParticle jp : particles ) {
if(!check( p, jp )) {
// problem was found. no need to check further
return new CollisionInfo( label, p.getLocator(), jp.getLocator() );
}
}
particles.add(p);
return null;
}
/** List of particles reported through the check method. */
private final List<XSParticle> particles = new ArrayList<XSParticle>();
/**
* Label names already used in the base type.
*/
private final Map<String,CPropertyInfo> occupiedLabels = new HashMap<String,CPropertyInfo>();
/**
* Checks the conflict of two particles.
* @return
* true if the check was successful.
*/
private boolean check( XSParticle p1, XSParticle p2 ) {
return !computeLabel(p1).equals(computeLabel(p2));
}
/**
* Reads fields of the super class and includes them
* to name collision tests.
*/
void readSuperClass( CClassInfo base ) {
for( ; base!=null; base=base.getBaseClass() ) {
for( CPropertyInfo p : base.getProperties() )
occupiedLabels.put(p.getName(true),p);
}
}
}
/** Keep the computed label names for particles. */
private final Map<XSParticle,String> labelCache = new Hashtable<XSParticle,String>();
/**
* Hides the computeLabel method of the outer class
* and adds caching.
*/
private String computeLabel( XSParticle p ) {
String label = labelCache.get(p);
if(label==null)
labelCache.put( p, label=DefaultParticleBinder.this.computeLabel(p) );
return label;
}
}
/**
* Builds properties by using the result computed by Checker
*/
private final class Builder implements XSTermVisitor {
Builder( Map<XSParticle,String> markedParticles ) {
this.markedParticles = markedParticles;
}
/** All marked particles. */
private final Map<XSParticle,String/*label*/> markedParticles;
/**
* When we are visiting inside an optional particle, this flag
* is set to true.
*
* <p>
* This allows us to correctly generate primitive/boxed types.
*/
private boolean insideOptionalParticle;
/** Returns true if a particle is marked. */
private boolean marked( XSParticle p ) {
return markedParticles.containsKey(p);
}
/** Gets a label of a particle. */
private String getLabel( XSParticle p ) {
return markedParticles.get(p);
}
public void particle( XSParticle p ) {
XSTerm t = p.getTerm();
if(marked(p)) {
BIProperty cust = BIProperty.getCustomization(p);
CPropertyInfo prop = cust.createElementOrReferenceProperty(
getLabel(p), false, p, RawTypeSetBuilder.build(p,insideOptionalParticle));
getCurrentBean().addProperty(prop);
} else {
// repeated model groups should have been marked already
assert !p.isRepeated();
boolean oldIOP = insideOptionalParticle;
insideOptionalParticle |= BigInteger.ZERO.equals(p.getMinOccurs());
// this is an unmarked particle
t.visit(this);
insideOptionalParticle = oldIOP;
}
}
public void elementDecl( XSElementDecl e ) {
// because the corresponding particle must be marked.
assert false;
}
public void wildcard( XSWildcard wc ) {
// because the corresponding particle must be marked.
assert false;
}
public void modelGroupDecl( XSModelGroupDecl decl ) {
modelGroup(decl.getModelGroup());
}
public void modelGroup( XSModelGroup mg ) {
boolean oldIOP = insideOptionalParticle;
insideOptionalParticle |= mg.getCompositor()==XSModelGroup.CHOICE;
for( XSParticle p : mg.getChildren())
particle(p);
insideOptionalParticle = oldIOP;
}
}
}

View File

@@ -0,0 +1,109 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.xmlschema;
import com.sun.tools.internal.xjc.ErrorReceiver;
import com.sun.tools.internal.xjc.reader.Ring;
import org.xml.sax.ErrorHandler;
import org.xml.sax.Locator;
import org.xml.sax.SAXParseException;
/**
* Provides error report capability to other owner components
* by encapsulating user-specified {@link ErrorHandler}
* and exposing utlity methods.
*
* <p>
* This class also wraps SAXException to a RuntimeException
* so that the exception thrown inside the error handler
* can abort the process.
*
* <p>
* At the end of the day, we need to know if there was any error.
* So it is important that all the error messages go through this
* object. This is done by hiding the errorHandler from the rest
* of the components.
*
* @author
* Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
*/
public final class ErrorReporter extends BindingComponent {
/**
* Error handler to report any binding error to.
* To report errors, use the error method.
*/
private final ErrorReceiver errorReceiver = Ring.get(ErrorReceiver.class);
//
// helper methods for classes in this package.
// properties are localized through the Messages.properties file
// in this package
//
void error( Locator loc, String prop, Object... args ) {
errorReceiver.error( loc, Messages.format(prop,args) );
}
void warning( Locator loc, String prop, Object... args ) {
errorReceiver.warning( new SAXParseException(
Messages.format(prop,args), loc ));
}
/*
private String format( String prop, Object[] args ) {
// use a bit verbose code to make it portable.
String className = this.getClass().getName();
int idx = className.lastIndexOf('.');
String packageName = className.substring(0,idx);
String fmt = ResourceBundle.getBundle(packageName+".Messages").getString(prop);
return MessageFormat.format(fmt,args);
}
*/
////
////
//// ErrorHandler implementation
////
////
// public void error(SAXParseException exception) {
// errorReceiver.error(exception);
// }
//
// public void fatalError(SAXParseException exception) {
// errorReceiver.fatalError(exception);
// }
//
// public void warning(SAXParseException exception) {
// errorReceiver.warning(exception);
// }
}

View File

@@ -0,0 +1,134 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.xmlschema;
import java.util.HashMap;
import java.util.Map;
import javax.xml.bind.annotation.XmlAnyElement;
import javax.xml.namespace.QName;
import com.sun.tools.internal.xjc.reader.gbind.Choice;
import com.sun.tools.internal.xjc.reader.gbind.Element;
import com.sun.tools.internal.xjc.reader.gbind.Expression;
import com.sun.tools.internal.xjc.reader.gbind.OneOrMore;
import com.sun.tools.internal.xjc.reader.gbind.Sequence;
import com.sun.xml.internal.xsom.XSElementDecl;
import com.sun.xml.internal.xsom.XSModelGroup;
import com.sun.xml.internal.xsom.XSModelGroupDecl;
import com.sun.xml.internal.xsom.XSParticle;
import com.sun.xml.internal.xsom.XSWildcard;
import com.sun.xml.internal.xsom.visitor.XSTermFunction;
import java.math.BigInteger;
/**
* Visits {@link XSParticle} and creates a corresponding {@link Expression} tree.
* @author Kohsuke Kawaguchi
*/
public final class ExpressionBuilder implements XSTermFunction<Expression> {
public static Expression createTree(XSParticle p) {
return new ExpressionBuilder().particle(p);
}
private ExpressionBuilder() {}
/**
* Wildcard instance needs to be consolidated to one,
* and this is such instance (if any.)
*/
private GWildcardElement wildcard = null;
private final Map<QName,GElementImpl> decls = new HashMap<QName,GElementImpl>();
private XSParticle current;
/**
* We can only have one {@link XmlAnyElement} property,
* so all the wildcards need to be treated as one node.
*/
public Expression wildcard(XSWildcard wc) {
if(wildcard==null)
wildcard = new GWildcardElement();
wildcard.merge(wc);
wildcard.particles.add(current);
return wildcard;
}
public Expression modelGroupDecl(XSModelGroupDecl decl) {
return modelGroup(decl.getModelGroup());
}
public Expression modelGroup(XSModelGroup group) {
XSModelGroup.Compositor comp = group.getCompositor();
if(comp==XSModelGroup.CHOICE) {
// empty choice is not epsilon, but empty set,
// so this initial value is incorrect. But this
// kinda works.
// properly handling empty set requires more work.
Expression e = Expression.EPSILON;
for (XSParticle p : group.getChildren()) {
if(e==null) e = particle(p);
else e = new Choice(e,particle(p));
}
return e;
} else {
Expression e = Expression.EPSILON;
for (XSParticle p : group.getChildren()) {
if(e==null) e = particle(p);
else e = new Sequence(e,particle(p));
}
return e;
}
}
public Element elementDecl(XSElementDecl decl) {
QName n = BGMBuilder.getName(decl);
GElementImpl e = decls.get(n);
if(e==null)
decls.put(n,e=new GElementImpl(n,decl));
e.particles.add(current);
assert current.getTerm()==decl;
return e;
}
public Expression particle(XSParticle p) {
current = p;
Expression e = p.getTerm().apply(this);
if(p.isRepeated())
e = new OneOrMore(e);
if (BigInteger.ZERO.equals(p.getMinOccurs()))
e = new Choice(e,Expression.EPSILON);
return e;
}
}

View File

@@ -0,0 +1,143 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.xmlschema;
import java.util.Collection;
import com.sun.tools.internal.xjc.model.CPropertyInfo;
import com.sun.tools.internal.xjc.model.Multiplicity;
import com.sun.tools.internal.xjc.reader.RawTypeSet;
import com.sun.tools.internal.xjc.reader.gbind.ConnectedComponent;
import com.sun.tools.internal.xjc.reader.gbind.Element;
import com.sun.tools.internal.xjc.reader.gbind.Expression;
import com.sun.tools.internal.xjc.reader.gbind.Graph;
import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIProperty;
import com.sun.xml.internal.bind.v2.model.core.WildcardMode;
import com.sun.xml.internal.xsom.XSParticle;
/**
* {@link ParticleBinder} that uses {@link ExpressionBuilder} et al
* for better, more intuitive (but non spec-conforming) binding.
*
* @author Kohsuke Kawaguchi
*/
final class ExpressionParticleBinder extends ParticleBinder {
public void build(XSParticle p, Collection<XSParticle> forcedProps) {
// this class isn't about spec conformance, but
// for the ease of use.
// so we don't give a damn about 'forcedProps'.
// although, for a future note, it's conceivable to expand
// the binding algorithm to cover this notion.
Expression tree = ExpressionBuilder.createTree(p);
Graph g = new Graph(tree);
for (ConnectedComponent cc : g) {
buildProperty(cc);
}
}
/**
* Builds a property ouf ot a connected component.
*/
private void buildProperty(ConnectedComponent cc) {
StringBuilder propName = new StringBuilder(); // property name
int nameTokenCount = 0; // combine only up to 3
RawTypeSetBuilder rtsb = new RawTypeSetBuilder();
for (Element e : cc) {
GElement ge = (GElement)e;
if(nameTokenCount<3) {
if(nameTokenCount!=0)
propName.append("And");
propName.append(makeJavaName(cc.isCollection(),ge.getPropertyNameSeed()));
nameTokenCount++;
}
if(e instanceof GElementImpl) {
GElementImpl ei = (GElementImpl) e;
rtsb.elementDecl(ei.decl);
continue;
}
if(e instanceof GWildcardElement) {
GWildcardElement w = (GWildcardElement)e;
rtsb.getRefs().add(new RawTypeSetBuilder.WildcardRef(
w.isStrict() ? WildcardMode.STRICT : WildcardMode.SKIP));
continue;
}
assert false : e; // no other kind should be here
}
Multiplicity m = Multiplicity.ONE;
if(cc.isCollection())
m = m.makeRepeated();
if(!cc.isRequired())
m = m.makeOptional();
RawTypeSet rts = new RawTypeSet(rtsb.getRefs(),m);
XSParticle p = findSourceParticle(cc);
BIProperty cust = BIProperty.getCustomization(p);
CPropertyInfo prop = cust.createElementOrReferenceProperty(
propName.toString(), false, p, rts );
getCurrentBean().addProperty(prop);
}
/**
* Finds a {@link XSParticle} that can serve as the representative property of
* the given {@link ConnectedComponent}.
*
* The representative property is used for reporting an error location and
* taking {@link BIProperty} customization. Right now, the algorithm is just pick
* the first one with {@link BIProperty}, but one can think of a better algorithm,
* such as taking a choice of (A|B) if CC={A,B}.
*/
private XSParticle findSourceParticle(ConnectedComponent cc) {
XSParticle first = null;
for (Element e : cc) {
GElement ge = (GElement)e;
for (XSParticle p : ge.particles) {
if(first==null)
first = p;
if(getLocalPropCustomization(p)!=null)
return p;
}
// if there are multiple property customizations,
// all but one will be left unused, which will be detected as an error
// later, so no need to check that now.
}
// if no customization was found, just use the first one.
return first;
}
public boolean checkFallback(XSParticle p) {
// this algorithm never falls back to 'getContent'.
return false;
}
}

View File

@@ -0,0 +1,49 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.xmlschema;
import java.util.HashSet;
import java.util.Set;
import com.sun.tools.internal.xjc.reader.gbind.Element;
import com.sun.xml.internal.xsom.XSElementDecl;
import com.sun.xml.internal.xsom.XSParticle;
/**
* @author Kohsuke Kawaguchi
*/
abstract class GElement extends Element {
/**
* All the {@link XSParticle}s (whose term is {@link XSElementDecl})
* that are coereced into a single {@link Element}.
*/
final Set<XSParticle> particles = new HashSet<XSParticle>();
/**
* Gets the seed (raw XML name) to be used to generate a property name.
*/
abstract String getPropertyNameSeed();
}

View File

@@ -0,0 +1,67 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.xmlschema;
import javax.xml.namespace.QName;
import com.sun.tools.internal.xjc.reader.gbind.Element;
import com.sun.xml.internal.xsom.XSElementDecl;
/**
* {@link Element} that wraps {@link XSElementDecl}.
*
* @author Kohsuke Kawaguchi
*/
final class GElementImpl extends GElement {
public final QName tagName;
/**
* The representative {@link XSElementDecl}.
*
* Even though multiple {@link XSElementDecl}s maybe represented by
* a single {@link GElementImpl} (especially when they are local),
* the schema spec requires that they share the same type and other
* characteristic.
*
* (To be really precise, you may have different default values,
* nillability, all that, so if that becomes a real issue we have
* to reconsider this design.)
*/
public final XSElementDecl decl;
public GElementImpl(QName tagName, XSElementDecl decl) {
this.tagName = tagName;
this.decl = decl;
}
public String toString() {
return tagName.toString();
}
String getPropertyNameSeed() {
return tagName.getLocalPart();
}
}

View File

@@ -0,0 +1,64 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.xmlschema;
import com.sun.tools.internal.xjc.reader.gbind.Element;
import com.sun.xml.internal.xsom.XSWildcard;
/**
* {@link Element} that represents a wildcard,
* for the "ease of binding" we always just bind this to DOM elements.
* @author Kohsuke Kawaguchi
*/
final class GWildcardElement extends GElement {
/**
* If true, bind to <tt>Object</tt> for eager JAXB unmarshalling.
* Otherwise bind to DOM (I hate "you can put both" semantics,
* so I'm not going to do that in this binding mode.)
*/
private boolean strict = true;
public String toString() {
return "#any";
}
String getPropertyNameSeed() {
return "any";
}
public void merge(XSWildcard wc) {
switch(wc.getMode()) {
case XSWildcard.LAX:
case XSWildcard.SKIP:
strict = false;
}
}
public boolean isStrict() {
return strict;
}
}

View File

@@ -0,0 +1,157 @@
/*
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.xmlschema;
import java.text.MessageFormat;
import java.util.ResourceBundle;
/**
* Formats error messages.
*/
public class Messages
{
/** Loads a string resource and formats it with specified arguments. */
public static String format( String property, Object... args ) {
String text = ResourceBundle.getBundle(Messages.class.getPackage().getName() +".MessageBundle").getString(property);
return MessageFormat.format(text,args);
}
static final String WARN_NO_GLOBAL_ELEMENT =
"BGMBuilder.NoGlobalElement";
public static final String WARN_UNUSED_EXPECTED_CONTENT_TYPES =
"UnusedCustomizationChecker.WarnUnusedExpectedContentTypes";
static final String ERR_MULTIPLE_SCHEMA_BINDINGS =
"BGMBuilder.MultipleSchemaBindings"; // arg:1
static final String ERR_MULTIPLE_SCHEMA_BINDINGS_LOCATION =
"BGMBuilder.MultipleSchemaBindings.Location"; // arg:0
static final String JAVADOC_HEADING = // 1 arg
"ClassSelector.JavadocHeading";
static final String ERR_RESERVED_CLASS_NAME = // 1 arg
"ClassSelector.ReservedClassName";
static final String ERR_CLASS_NAME_IS_REQUIRED =
"ClassSelector.ClassNameIsRequired"; // arg:0
static final String ERR_INCORRECT_CLASS_NAME =
"ClassSelector.IncorrectClassName"; // arg:1
static final String ERR_INCORRECT_PACKAGE_NAME =
"ClassSelector.IncorrectPackageName"; // arg:2
static final String ERR_CANNOT_BE_TYPE_SAFE_ENUM =
"ConversionFinder.CannotBeTypeSafeEnum"; // arg:0
static final String ERR_CANNOT_BE_TYPE_SAFE_ENUM_LOCATION =
"ConversionFinder.CannotBeTypeSafeEnum.Location"; // arg:0
static final String ERR_NO_ENUM_NAME_AVAILABLE =
"ConversionFinder.NoEnumNameAvailable"; // arg:0
static final String ERR_NO_ENUM_FACET =
"ConversionFinder.NoEnumFacet"; // arg:0
static final String ERR_ILLEGAL_EXPECTED_MIME_TYPE =
"ERR_ILLEGAL_EXPECTED_MIME_TYPE"; // args:2
static final String ERR_DATATYPE_ERROR =
"DatatypeBuilder.DatatypeError"; // arg:1
static final String ERR_UNABLE_TO_GENERATE_NAME_FROM_MODELGROUP =
"DefaultParticleBinder.UnableToGenerateNameFromModelGroup"; // arg:0
static final String ERR_INCORRECT_FIXED_VALUE =
"FieldBuilder.IncorrectFixedValue"; // arg:1
static final String ERR_INCORRECT_DEFAULT_VALUE =
"FieldBuilder.IncorrectDefaultValue"; // arg:1
static final String ERR_CONFLICT_BETWEEN_USERTYPE_AND_ACTUALTYPE_ATTUSE =
"FieldBuilder.ConflictBetweenUserTypeAndActualType.AttUse"; // arg:2
static final String ERR_CONFLICT_BETWEEN_USERTYPE_AND_ACTUALTYPE_ATTUSE_SOURCE =
"FieldBuilder.ConflictBetweenUserTypeAndActualType.AttUse.Source"; // arg:0
static final String ERR_UNNESTED_JAVATYPE_CUSTOMIZATION_ON_SIMPLETYPE =
"SimpleTypeBuilder.UnnestedJavaTypeCustomization"; // arg:0
static final String JAVADOC_NIL_PROPERTY =
"FieldBuilder.Javadoc.NilProperty"; // arg:1
static final String JAVADOC_LINE_UNKNOWN = // 0 args
"ClassSelector.JavadocLineUnknown";
static final String JAVADOC_VALUEOBJECT_PROPERTY =
"FieldBuilder.Javadoc.ValueObject"; // args:2
static final String MSG_COLLISION_INFO =
"CollisionInfo.CollisionInfo"; // args:3
static final String MSG_UNKNOWN_FILE =
"CollisionInfo.UnknownFile"; // arg:1
static final String MSG_LINE_X_OF_Y =
"CollisionInfo.LineXOfY"; // args:2
static final String MSG_FALLBACK_JAVADOC =
"DefaultParticleBinder.FallbackJavadoc"; // arg:1
static final String ERR_ENUM_MEMBER_NAME_COLLISION =
"ERR_ENUM_MEMBER_NAME_COLLISION";
static final String ERR_ENUM_MEMBER_NAME_COLLISION_RELATED =
"ERR_ENUM_MEMBER_NAME_COLLISION_RELATED";
static final String ERR_CANNOT_GENERATE_ENUM_NAME =
"ERR_CANNOT_GENERATE_ENUM_NAME";
static final String WARN_ENUM_MEMBER_SIZE_CAP =
"WARN_ENUM_MEMBER_SIZE_CAP"; // args: 3
// they are shared from the model
public static final String ERR_UNACKNOWLEDGED_CUSTOMIZATION =
"UnusedCustomizationChecker.UnacknolwedgedCustomization"; // arg:1
public static final String ERR_UNACKNOWLEDGED_CUSTOMIZATION_LOCATION =
"UnusedCustomizationChecker.UnacknolwedgedCustomization.Relevant"; // arg:0
public static final String ERR_MULTIPLE_GLOBAL_BINDINGS =
"ERR_MULTIPLE_GLOBAL_BINDINGS";
public static final String ERR_MULTIPLE_GLOBAL_BINDINGS_OTHER =
"ERR_MULTIPLE_GLOBAL_BINDINGS_OTHER";
public static final String ERR_REFERENCE_TO_NONEXPORTED_CLASS =
"ERR_REFERENCE_TO_NONEXPORTED_CLASS";
public static final String ERR_REFERENCE_TO_NONEXPORTED_CLASS_MAP_FALSE =
"ERR_REFERENCE_TO_NONEXPORTED_CLASS_MAP_FALSE";
public static final String ERR_REFERENCE_TO_NONEXPORTED_CLASS_REFERER =
"ERR_REFERENCE_TO_NONEXPORTED_CLASS_REFERER";
static final String WARN_DEFAULT_VALUE_PRIMITIVE_TYPE =
"WARN_DEFAULT_VALUE_PRIMITIVE_TYPE";
}

View File

@@ -0,0 +1,95 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.xmlschema;
import java.math.BigInteger;
import com.sun.tools.internal.xjc.model.Multiplicity;
import com.sun.xml.internal.xsom.XSElementDecl;
import com.sun.xml.internal.xsom.XSModelGroup;
import com.sun.xml.internal.xsom.XSModelGroupDecl;
import com.sun.xml.internal.xsom.XSParticle;
import com.sun.xml.internal.xsom.XSWildcard;
import com.sun.xml.internal.xsom.visitor.XSTermFunction;
import static com.sun.tools.internal.xjc.model.Multiplicity.ONE;
import static com.sun.tools.internal.xjc.model.Multiplicity.ZERO;
/**
* Counts {@link Multiplicity} for a particle/term.
*
* @author Kohsuke Kawaguchi
*/
public final class MultiplicityCounter implements XSTermFunction<Multiplicity> {
public static final MultiplicityCounter theInstance = new MultiplicityCounter();
private MultiplicityCounter() {}
public Multiplicity particle( XSParticle p ) {
Multiplicity m = p.getTerm().apply(this);
BigInteger max;
if (m.max==null || (BigInteger.valueOf(XSParticle.UNBOUNDED).equals(p.getMaxOccurs())))
max=null;
else
max=p.getMaxOccurs();
return Multiplicity.multiply( m, Multiplicity.create(p.getMinOccurs(),max) );
}
public Multiplicity wildcard(XSWildcard wc) {
return ONE;
}
public Multiplicity modelGroupDecl(XSModelGroupDecl decl) {
return modelGroup(decl.getModelGroup());
}
public Multiplicity modelGroup(XSModelGroup group) {
boolean isChoice = group.getCompositor() == XSModelGroup.CHOICE;
Multiplicity r = ZERO;
for( XSParticle p : group.getChildren()) {
Multiplicity m = particle(p);
if(r==null) {
r=m;
continue;
}
if(isChoice) {
r = Multiplicity.choice(r,m);
} else {
r = Multiplicity.group(r,m);
}
}
return r;
}
public Multiplicity elementDecl(XSElementDecl decl) {
return ONE;
}
}

View File

@@ -0,0 +1,255 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.xmlschema;
import java.text.ParseException;
import java.util.Collection;
import java.util.Collections;
import com.sun.codemodel.internal.JJavaName;
import com.sun.tools.internal.xjc.model.CClassInfo;
import com.sun.tools.internal.xjc.model.CPropertyInfo;
import com.sun.tools.internal.xjc.reader.Ring;
import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIDeclaration;
import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIProperty;
import com.sun.xml.internal.xsom.XSElementDecl;
import com.sun.xml.internal.xsom.XSModelGroup;
import com.sun.xml.internal.xsom.XSModelGroupDecl;
import com.sun.xml.internal.xsom.XSParticle;
import com.sun.xml.internal.xsom.XSTerm;
import com.sun.xml.internal.xsom.XSWildcard;
import com.sun.xml.internal.xsom.visitor.XSTermVisitor;
/**
* Binds the content models of {@link XSParticle} as properties of the class that's being built.
*
* @author
* Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
*/
public abstract class ParticleBinder {
protected final BGMBuilder builder = Ring.get(BGMBuilder.class);
protected ParticleBinder() {
// make sure that this object is available as ParticleBinder, not as their actual implementation classes
Ring.add(ParticleBinder.class,this);
}
/**
* Builds the {@link CPropertyInfo}s from the given particle
* (and its descendants), and set them to the class returned by
* {@link ClassSelector#getCurrentBean()}.
*/
public final void build( XSParticle p ) {
build(p, Collections.<XSParticle>emptySet());
}
/**
* The version of the build method that forces a specified set of particles
* to become a property.
*/
public abstract void build( XSParticle p, Collection<XSParticle> forcedProps );
/**
* Similar to the build method but this method only checks if
* the BGM that will be built by the build method will
* do the fallback (map all the properties into one list) or not.
*
* @return
* false if the fallback will not happen.
*/
public abstract boolean checkFallback( XSParticle p );
//
//
// convenient utility methods
//
//
protected final CClassInfo getCurrentBean() {
return getClassSelector().getCurrentBean();
}
/**
* Gets the BIProperty object that applies to the given particle.
*/
protected final BIProperty getLocalPropCustomization( XSParticle p ) {
return getLocalCustomization(p,BIProperty.class);
}
protected final <T extends BIDeclaration> T getLocalCustomization( XSParticle p, Class<T> type ) {
// check the property customization of this component first
T cust = builder.getBindInfo(p).get(type);
if(cust!=null) return cust;
// if not, the term might have one.
cust = builder.getBindInfo(p.getTerm()).get(type);
if(cust!=null) return cust;
return null;
}
/**
* Computes the label of a given particle.
* Usually, the getLabel method should be used instead.
*/
protected final String computeLabel( XSParticle p ) {
// if the particle carries a customization, use that value.
// since we are binding content models, it's always non-constant properties.
BIProperty cust = getLocalPropCustomization(p);
if(cust!=null && cust.getPropertyName(false)!=null)
return cust.getPropertyName(false);
// no explicit property name is given. Compute one.
XSTerm t = p.getTerm();
// // first, check if a term is going to be a class, if so, use that name.
// ClassItem ci = owner.selector.select(t);
// if(ci!=null) {
// return makeJavaName(ci.getTypeAsDefined().name());
// }
// if it fails, compute the default name according to the spec.
if(t.isElementDecl())
// for element, take the element name.
return makeJavaName(p,t.asElementDecl().getName());
if(t.isModelGroupDecl())
// for named model groups, take that name
return makeJavaName(p,t.asModelGroupDecl().getName());
if(t.isWildcard())
// the spec says it will map to "any" by default.
return makeJavaName(p,"Any");
if(t.isModelGroup()) {
try {
return getSpecDefaultName(t.asModelGroup(),p.isRepeated());
} catch( ParseException e ) {
// unable to generate a name.
getErrorReporter().error(t.getLocator(),
Messages.ERR_UNABLE_TO_GENERATE_NAME_FROM_MODELGROUP);
return "undefined"; // recover from error by assuming something
}
}
// there are only four types of XSTerm.
throw new AssertionError();
}
/** Converts an XML name to the corresponding Java name. */
protected final String makeJavaName( boolean isRepeated, String xmlName ) {
String name = builder.getNameConverter().toPropertyName(xmlName);
if(builder.getGlobalBinding().isSimpleMode() && isRepeated )
name = JJavaName.getPluralForm(name);
return name;
}
protected final String makeJavaName( XSParticle p, String xmlName ) {
return makeJavaName(p.isRepeated(),xmlName);
}
/**
* Computes a name from unnamed model group by following the spec.
*
* Taking first three elements and combine them.
*
* @param repeated
* if the said model group is repeated more than once
*
* @exception ParseException
* If the method cannot generate a name. For example, when
* a model group doesn't contain any element reference/declaration
* at all.
*/
protected final String getSpecDefaultName( XSModelGroup mg, final boolean repeated ) throws ParseException {
final StringBuilder name = new StringBuilder();
mg.visit(new XSTermVisitor() {
/**
* Count the number of tokens we combined.
* We will concat up to 3.
*/
private int count=0;
/**
* Is the current particple/term repeated?
*/
private boolean rep = repeated;
public void wildcard(XSWildcard wc) {
append("any");
}
public void modelGroupDecl(XSModelGroupDecl mgd) {
modelGroup(mgd.getModelGroup());
}
public void modelGroup(XSModelGroup mg) {
String operator;
if(mg.getCompositor()==XSModelGroup.CHOICE) operator = "Or";
else operator = "And";
int size = mg.getSize();
for( int i=0; i<size; i++ ) {
XSParticle p = mg.getChild(i);
boolean oldRep = rep;
rep |= p.isRepeated();
p.getTerm().visit(this);
rep = oldRep;
if(count==3) return; // we have enough
if(i!=size-1) name.append(operator);
}
}
public void elementDecl(XSElementDecl ed) {
append(ed.getName());
}
private void append(String token) {
if( count<3 ) {
name.append(makeJavaName(rep,token));
count++;
}
}
});
if(name.length()==0) throw new ParseException("no element",-1);
return name.toString();
}
protected final ErrorReporter getErrorReporter() {
return Ring.get(ErrorReporter.class);
}
protected final ClassSelector getClassSelector() {
return Ring.get(ClassSelector.class);
}
}

View File

@@ -0,0 +1,379 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.xmlschema;
import java.util.LinkedHashSet;
import java.util.Set;
import javax.activation.MimeType;
import javax.xml.namespace.QName;
import com.sun.tools.internal.xjc.model.CAdapter;
import com.sun.tools.internal.xjc.model.CClass;
import com.sun.tools.internal.xjc.model.CClassInfo;
import com.sun.tools.internal.xjc.model.CCustomizations;
import com.sun.tools.internal.xjc.model.CElement;
import com.sun.tools.internal.xjc.model.CElementInfo;
import com.sun.tools.internal.xjc.model.CElementPropertyInfo;
import com.sun.tools.internal.xjc.model.CReferencePropertyInfo;
import com.sun.tools.internal.xjc.model.CTypeRef;
import com.sun.tools.internal.xjc.model.Model;
import com.sun.tools.internal.xjc.model.Multiplicity;
import com.sun.tools.internal.xjc.model.TypeUse;
import com.sun.tools.internal.xjc.reader.RawTypeSet;
import com.sun.tools.internal.xjc.reader.Ring;
import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIDom;
import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIGlobalBinding;
import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIXSubstitutable;
import com.sun.xml.internal.bind.v2.model.core.ID;
import com.sun.xml.internal.bind.v2.model.core.WildcardMode;
import com.sun.xml.internal.xsom.XSElementDecl;
import com.sun.xml.internal.xsom.XSModelGroup;
import com.sun.xml.internal.xsom.XSModelGroupDecl;
import com.sun.xml.internal.xsom.XSParticle;
import com.sun.xml.internal.xsom.XSWildcard;
import com.sun.xml.internal.xsom.visitor.XSTermVisitor;
/**
* Builds {@link RawTypeSet} for XML Schema.
*
* @author Kohsuke Kawaguchi
*/
public class RawTypeSetBuilder implements XSTermVisitor {
/**
* @param optional
* if this whole property is optional due to the
* occurrence constraints on ancestors, set this to true.
* this will prevent the primitive types to be generated.
*/
public static RawTypeSet build( XSParticle p, boolean optional ) {
RawTypeSetBuilder rtsb = new RawTypeSetBuilder();
rtsb.particle(p);
Multiplicity mul = MultiplicityCounter.theInstance.particle(p);
if(optional)
mul = mul.makeOptional();
return new RawTypeSet(rtsb.refs,mul);
}
/**
* To avoid declaring the same element twice for a content model like
* (A,A), we keep track of element names here while we are building up
* this instance.
*/
private final Set<QName> elementNames = new LinkedHashSet<QName>();
private final Set<RawTypeSet.Ref> refs = new LinkedHashSet<RawTypeSet.Ref>();
protected final BGMBuilder builder = Ring.get(BGMBuilder.class);
public RawTypeSetBuilder() {}
/**
* Gets the {@link RawTypeSet.Ref}s that were built.
*/
public Set<RawTypeSet.Ref> getRefs() {
return refs;
}
/**
* Build up {@link #refs} and compute the total multiplicity of this {@link RawTypeSet.Ref} set.
*/
private void particle( XSParticle p ) {
// if the DOM customization is present, bind it like a wildcard
BIDom dom = builder.getLocalDomCustomization(p);
if(dom!=null) {
dom.markAsAcknowledged();
refs.add(new WildcardRef(WildcardMode.SKIP));
} else {
p.getTerm().visit(this);
}
}
public void wildcard(XSWildcard wc) {
refs.add(new WildcardRef(wc));
}
public void modelGroupDecl(XSModelGroupDecl decl) {
modelGroup(decl.getModelGroup());
}
public void modelGroup(XSModelGroup group) {
for( XSParticle p : group.getChildren())
particle(p);
}
public void elementDecl(XSElementDecl decl) {
QName n = BGMBuilder.getName(decl);
if(elementNames.add(n)) {
CElement elementBean = Ring.get(ClassSelector.class).bindToType(decl,null);
if(elementBean==null)
refs.add(new XmlTypeRef(decl));
else {
// yikes!
if(elementBean instanceof CClass)
refs.add(new CClassRef(decl,(CClass)elementBean));
else
refs.add(new CElementInfoRef(decl,(CElementInfo)elementBean));
}
}
}
/**
* Reference to a wildcard.
*/
public static final class WildcardRef extends RawTypeSet.Ref {
private final WildcardMode mode;
WildcardRef(XSWildcard wildcard) {
this.mode = getMode(wildcard);
}
WildcardRef(WildcardMode mode) {
this.mode = mode;
}
private static WildcardMode getMode(XSWildcard wildcard) {
switch(wildcard.getMode()) {
case XSWildcard.LAX:
return WildcardMode.LAX;
case XSWildcard.STRTICT:
return WildcardMode.STRICT;
case XSWildcard.SKIP:
return WildcardMode.SKIP;
default:
throw new IllegalStateException();
}
}
protected CTypeRef toTypeRef(CElementPropertyInfo ep) {
// we don't allow a mapping to typeRef if the wildcard is present
throw new IllegalStateException();
}
protected void toElementRef(CReferencePropertyInfo prop) {
prop.setWildcard(mode);
}
protected RawTypeSet.Mode canBeType(RawTypeSet parent) {
return RawTypeSet.Mode.MUST_BE_REFERENCE;
}
protected boolean isListOfValues() {
return false;
}
protected ID id() {
return ID.NONE;
}
}
/**
* Reference to a class that maps from an element.
*/
public static final class CClassRef extends RawTypeSet.Ref {
public final CClass target;
public final XSElementDecl decl;
CClassRef(XSElementDecl decl, CClass target) {
this.decl = decl;
this.target = target;
}
protected CTypeRef toTypeRef(CElementPropertyInfo ep) {
return new CTypeRef(target,decl);
}
protected void toElementRef(CReferencePropertyInfo prop) {
prop.getElements().add(target);
}
protected RawTypeSet.Mode canBeType(RawTypeSet parent) {
// if element substitution can occur, no way it can be mapped to a list of types
if(decl.getSubstitutables().size()>1)
return RawTypeSet.Mode.MUST_BE_REFERENCE;
return RawTypeSet.Mode.SHOULD_BE_TYPEREF;
}
protected boolean isListOfValues() {
return false;
}
protected ID id() {
return ID.NONE;
}
}
/**
* Reference to a class that maps from an element.
*/
public final class CElementInfoRef extends RawTypeSet.Ref {
public final CElementInfo target;
public final XSElementDecl decl;
CElementInfoRef(XSElementDecl decl, CElementInfo target) {
this.decl = decl;
this.target = target;
}
protected CTypeRef toTypeRef(CElementPropertyInfo ep) {
assert !target.isCollection();
CAdapter a = target.getProperty().getAdapter();
if(a!=null && ep!=null) ep.setAdapter(a);
return new CTypeRef(target.getContentType(),decl);
}
protected void toElementRef(CReferencePropertyInfo prop) {
prop.getElements().add(target);
}
protected RawTypeSet.Mode canBeType(RawTypeSet parent) {
// if element substitution can occur, no way it can be mapped to a list of types
if(decl.getSubstitutables().size()>1)
return RawTypeSet.Mode.MUST_BE_REFERENCE;
// BIXSubstitutable also simulates this effect. Useful for separate compilation
BIXSubstitutable subst = builder.getBindInfo(decl).get(BIXSubstitutable.class);
if(subst!=null) {
subst.markAsAcknowledged();
return RawTypeSet.Mode.MUST_BE_REFERENCE;
}
// we have no place to put an adater if this thing maps to a type
CElementPropertyInfo p = target.getProperty();
// if we have an adapter or IDness, which requires special
// annotation, and there's more than one element,
// we have no place to put the special annotation, so we need JAXBElement.
if((parent.refs.size()>1 || !parent.mul.isAtMostOnce()) && p.id()!=ID.NONE)
return RawTypeSet.Mode.MUST_BE_REFERENCE;
if(parent.refs.size() > 1 && p.getAdapter() != null)
return RawTypeSet.Mode.MUST_BE_REFERENCE;
if(target.hasClass())
// if the CElementInfo was explicitly bound to a class (which happen if and only if
// the user requested so, then map that to reference property so that the user sees a class
return RawTypeSet.Mode.CAN_BE_TYPEREF;
else
return RawTypeSet.Mode.SHOULD_BE_TYPEREF;
}
protected boolean isListOfValues() {
return target.getProperty().isValueList();
}
protected ID id() {
return target.getProperty().id();
}
@Override
protected MimeType getExpectedMimeType() {
return target.getProperty().getExpectedMimeType();
}
}
/**
* References to a type. Could be global or local.
*/
public static final class XmlTypeRef extends RawTypeSet.Ref {
private final XSElementDecl decl;
private final TypeUse target;
public XmlTypeRef(XSElementDecl decl) {
this.decl = decl;
SimpleTypeBuilder stb = Ring.get(SimpleTypeBuilder.class);
stb.refererStack.push(decl);
TypeUse r = Ring.get(ClassSelector.class).bindToType(decl.getType(),decl);
stb.refererStack.pop();
target = r;
}
protected CTypeRef toTypeRef(CElementPropertyInfo ep) {
if(ep!=null && target.getAdapterUse()!=null)
ep.setAdapter(target.getAdapterUse());
return new CTypeRef(target.getInfo(),decl);
}
/**
* The whole type set can be later bound to a reference property,
* in which case we need to generate additional code to wrap this
* type reference into an element class.
*
* This method generates such an element class and returns it.
*/
protected void toElementRef(CReferencePropertyInfo prop) {
CClassInfo scope = Ring.get(ClassSelector.class).getCurrentBean();
Model model = Ring.get(Model.class);
CCustomizations custs = Ring.get(BGMBuilder.class).getBindInfo(decl).toCustomizationList();
if(target instanceof CClassInfo && Ring.get(BIGlobalBinding.class).isSimpleMode()) {
CClassInfo bean = new CClassInfo(model,scope,
model.getNameConverter().toClassName(decl.getName()),
decl.getLocator(), null, BGMBuilder.getName(decl), decl,
custs);
bean.setBaseClass((CClassInfo)target);
prop.getElements().add(bean);
} else {
CElementInfo e = new CElementInfo(model,BGMBuilder.getName(decl),scope,target,
decl.getDefaultValue(), decl, custs, decl.getLocator());
prop.getElements().add(e);
}
}
protected RawTypeSet.Mode canBeType(RawTypeSet parent) {
// if we have an adapter or IDness, which requires special
// annotation, and there's more than one element,
// we have no place to put the special annotation, so we need JAXBElement.
if((parent.refs.size()>1 || !parent.mul.isAtMostOnce()) && target.idUse()!=ID.NONE)
return RawTypeSet.Mode.MUST_BE_REFERENCE;
if(parent.refs.size() > 1 && target.getAdapterUse() != null)
return RawTypeSet.Mode.MUST_BE_REFERENCE;
// nillable and optional at the same time. needs an element wrapper to distinguish those
// two states. But this is not a hard requirement.
if(decl.isNillable() && parent.mul.isOptional())
return RawTypeSet.Mode.CAN_BE_TYPEREF;
return RawTypeSet.Mode.SHOULD_BE_TYPEREF;
}
protected boolean isListOfValues() {
return target.isCollection();
}
protected ID id() {
return target.idUse();
}
@Override
protected MimeType getExpectedMimeType() {
return target.getExpectedMimeType();
}
}
}

View File

@@ -0,0 +1,154 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.xmlschema;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.Collections;
import com.sun.xml.internal.xsom.XSAnnotation;
import com.sun.xml.internal.xsom.XSAttGroupDecl;
import com.sun.xml.internal.xsom.XSAttributeDecl;
import com.sun.xml.internal.xsom.XSAttributeUse;
import com.sun.xml.internal.xsom.XSComplexType;
import com.sun.xml.internal.xsom.XSComponent;
import com.sun.xml.internal.xsom.XSContentType;
import com.sun.xml.internal.xsom.XSElementDecl;
import com.sun.xml.internal.xsom.XSFacet;
import com.sun.xml.internal.xsom.XSIdentityConstraint;
import com.sun.xml.internal.xsom.XSModelGroup;
import com.sun.xml.internal.xsom.XSModelGroupDecl;
import com.sun.xml.internal.xsom.XSNotation;
import com.sun.xml.internal.xsom.XSParticle;
import com.sun.xml.internal.xsom.XSSchema;
import com.sun.xml.internal.xsom.XSSchemaSet;
import com.sun.xml.internal.xsom.XSSimpleType;
import com.sun.xml.internal.xsom.XSType;
import com.sun.xml.internal.xsom.XSWildcard;
import com.sun.xml.internal.xsom.XSXPath;
import com.sun.xml.internal.xsom.visitor.XSVisitor;
/**
* Finds which {@link XSComponent}s refer to which {@link XSComplexType}s.
*
* @author Kohsuke Kawaguchi
*/
final class RefererFinder implements XSVisitor {
private final Set<Object> visited = new HashSet<Object>();
private final Map<XSComponent,Set<XSComponent>> referers = new HashMap<XSComponent,Set<XSComponent>>();
public Set<XSComponent> getReferer(XSComponent src) {
Set<XSComponent> r = referers.get(src);
if(r==null) return Collections.emptySet();
return r;
}
public void schemaSet(XSSchemaSet xss) {
if(!visited.add(xss)) return;
for (XSSchema xs : xss.getSchemas()) {
schema(xs);
}
}
public void schema(XSSchema xs) {
if(!visited.add(xs)) return;
for (XSComplexType ct : xs.getComplexTypes().values()) {
complexType(ct);
}
for (XSElementDecl e : xs.getElementDecls().values()) {
elementDecl(e);
}
}
public void elementDecl(XSElementDecl e) {
if(!visited.add(e)) return;
refer(e,e.getType());
e.getType().visit(this);
}
public void complexType(XSComplexType ct) {
if(!visited.add(ct)) return;
refer(ct,ct.getBaseType());
ct.getBaseType().visit(this);
ct.getContentType().visit(this);
}
public void modelGroupDecl(XSModelGroupDecl decl) {
if(!visited.add(decl)) return;
modelGroup(decl.getModelGroup());
}
public void modelGroup(XSModelGroup group) {
if(!visited.add(group)) return;
for (XSParticle p : group.getChildren()) {
particle(p);
}
}
public void particle(XSParticle particle) {
// since the particle method is side-effect free, no need to check for double-visit.
particle.getTerm().visit(this);
}
// things we don't care
public void simpleType(XSSimpleType simpleType) {}
public void annotation(XSAnnotation ann) {}
public void attGroupDecl(XSAttGroupDecl decl) {}
public void attributeDecl(XSAttributeDecl decl) {}
public void attributeUse(XSAttributeUse use) {}
public void facet(XSFacet facet) {}
public void notation(XSNotation notation) {}
public void identityConstraint(XSIdentityConstraint decl) {}
public void xpath(XSXPath xp) {}
public void wildcard(XSWildcard wc) {}
public void empty(XSContentType empty) {}
/**
* Called for each reference to record the fact.
*
* So far we only care about references to types.
*/
private void refer(XSComponent source, XSType target) {
Set<XSComponent> r = referers.get(target);
if(r==null) {
r = new HashSet<XSComponent>();
referers.put(target,r);
}
r.add(source);
}
}

View File

@@ -0,0 +1,918 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.xmlschema;
import java.io.StringWriter;
import java.math.BigInteger;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Stack;
import javax.activation.MimeTypeParseException;
import javax.xml.bind.DatatypeConverter;
import com.sun.codemodel.internal.JJavaName;
import com.sun.codemodel.internal.util.JavadocEscapeWriter;
import com.sun.xml.internal.bind.v2.WellKnownNamespace;
import com.sun.tools.internal.xjc.ErrorReceiver;
import com.sun.tools.internal.xjc.model.CBuiltinLeafInfo;
import com.sun.tools.internal.xjc.model.CClassInfo;
import com.sun.tools.internal.xjc.model.CClassInfoParent;
import com.sun.tools.internal.xjc.model.CClassRef;
import com.sun.tools.internal.xjc.model.CEnumConstant;
import com.sun.tools.internal.xjc.model.CEnumLeafInfo;
import com.sun.tools.internal.xjc.model.CNonElement;
import com.sun.tools.internal.xjc.model.Model;
import com.sun.tools.internal.xjc.model.TypeUse;
import com.sun.tools.internal.xjc.model.TypeUseFactory;
import com.sun.tools.internal.xjc.reader.Const;
import com.sun.tools.internal.xjc.reader.Ring;
import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIConversion;
import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIEnum;
import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIEnumMember;
import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIProperty;
import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BindInfo;
import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.EnumMemberMode;
import com.sun.tools.internal.xjc.util.MimeTypeRange;
import static com.sun.xml.internal.bind.v2.WellKnownNamespace.XML_MIME_URI;
import com.sun.xml.internal.bind.v2.runtime.SwaRefAdapterMarker;
import com.sun.xml.internal.xsom.XSAttributeDecl;
import com.sun.xml.internal.xsom.XSComplexType;
import com.sun.xml.internal.xsom.XSComponent;
import com.sun.xml.internal.xsom.XSElementDecl;
import com.sun.xml.internal.xsom.XSFacet;
import com.sun.xml.internal.xsom.XSListSimpleType;
import com.sun.xml.internal.xsom.XSRestrictionSimpleType;
import com.sun.xml.internal.xsom.XSSimpleType;
import com.sun.xml.internal.xsom.XSUnionSimpleType;
import com.sun.xml.internal.xsom.XSVariety;
import com.sun.xml.internal.xsom.impl.util.SchemaWriter;
import com.sun.xml.internal.xsom.visitor.XSSimpleTypeFunction;
import com.sun.xml.internal.xsom.visitor.XSVisitor;
import org.xml.sax.Locator;
/**
* Builds {@link TypeUse} from simple types.
*
* <p>
* This code consists of two main portions. The {@link #compose(XSSimpleType)} method
* and {@link #composer} forms an outer cycle, which gradually ascends the type
* inheritance chain until it finds the suitable binding. When it does this
* {@link #initiatingType} is set to the type which started binding, so that we can refer
* to the actual constraint facets and such that are applicable on the type.
*
* <p>
* For each intermediate type in the chain, the {@link #find(XSSimpleType)} method
* is used to find the binding on that type, sine the outer loop is doing the ascending,
* this method only sees if the current type has some binding available.
*
* <p>
* There is at least one ugly code that you need to aware of
* when you are modifying the code. See the documentation
* about <a href="package.html#stref_cust">
* "simple type customization at the point of reference."</a>
*
*
* @author
* Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
*/
public final class SimpleTypeBuilder extends BindingComponent {
protected final BGMBuilder builder = Ring.get(BGMBuilder.class);
private final Model model = Ring.get(Model.class);
/**
* The component that is refering to the simple type
* which we are building. This is ugly but necessary
* to support the customization of simple types at
* its point of reference. See my comment at the header
* of this class for details.
*
* UGLY: Implemented as a Stack of XSComponent to fix a bug
*/
public final Stack<XSComponent> refererStack = new Stack<XSComponent>();
/**
* Records what xmime:expectedContentTypes annotations we honored and processed,
* so that we can later check if the user had these annotations in the places
* where we didn't anticipate them.
*/
private final Set<XSComponent> acknowledgedXmimeContentTypes = new HashSet<XSComponent>();
/**
* The type that was originally passed to this {@link SimpleTypeBuilder#build(XSSimpleType)}.
* Never null.
*/
private XSSimpleType initiatingType;
/** {@link TypeUse}s for the built-in types. Read-only. */
public static final Map<String,TypeUse> builtinConversions = new HashMap<String,TypeUse>();
/**
* Entry point from outside. Builds a BGM type expression
* from a simple type schema component.
*
* @param type
* the simple type to be bound.
*/
public TypeUse build( XSSimpleType type ) {
XSSimpleType oldi = initiatingType;
this.initiatingType = type;
TypeUse e = checkRefererCustomization(type);
if(e==null)
e = compose(type);
initiatingType = oldi;
return e;
}
/**
* A version of the {@link #build(XSSimpleType)} method
* used to bind the definition of a class generated from
* the given simple type.
*/
public TypeUse buildDef( XSSimpleType type ) {
XSSimpleType oldi = initiatingType;
this.initiatingType = type;
TypeUse e = type.apply(composer);
initiatingType = oldi;
return e;
}
/**
* Returns a javaType customization specified to the referer, if present.
* @return can be null.
*/
private BIConversion getRefererCustomization() {
BindInfo info = builder.getBindInfo(getReferer());
BIProperty prop = info.get(BIProperty.class);
if(prop==null) return null;
return prop.getConv();
}
public XSComponent getReferer() {
return refererStack.peek();
}
/**
* Checks if the referer has a conversion customization or not.
* If it does, use it to bind this simple type. Otherwise
* return null;
*/
private TypeUse checkRefererCustomization( XSSimpleType type ) {
// assertion check. referer must be set properly
// before the build method is called.
// since the handling of the simple type point-of-reference
// customization is very error prone, it deserves a strict
// assertion check.
// UGLY CODE WARNING
XSComponent top = getReferer();
if( top instanceof XSElementDecl ) {
// if the parent is element type, its content type must be us.
XSElementDecl eref = (XSElementDecl)top;
assert eref.getType()==type;
// for elements, you can't use <property>,
// so we allow javaType to appear directly.
BindInfo info = builder.getBindInfo(top);
BIConversion conv = info.get(BIConversion.class);
if(conv!=null) {
conv.markAsAcknowledged();
// the conversion is given.
return conv.getTypeUse(type);
}
detectJavaTypeCustomization();
} else
if( top instanceof XSAttributeDecl ) {
XSAttributeDecl aref = (XSAttributeDecl)top;
assert aref.getType()==type;
detectJavaTypeCustomization();
} else
if( top instanceof XSComplexType ) {
XSComplexType tref = (XSComplexType)top;
assert tref.getBaseType()==type || tref.getContentType()==type;
detectJavaTypeCustomization();
} else
if( top == type ) {
// this means the simple type is built by itself and
// not because it's referenced by something.
} else
// unexpected referer type.
assert false;
// now we are certain that the referer is OK.
// see if it has a conversion customization.
BIConversion conv = getRefererCustomization();
if(conv!=null) {
conv.markAsAcknowledged();
// the conversion is given.
return conv.getTypeUse(type);
} else
// not found
return null;
}
/**
* Detect "javaType" customizations placed directly on simple types, rather
* than being enclosed by "property" and "baseType" customizations (see
* sec 6.8.1 of the spec).
*
* Report an error if any exist.
*/
private void detectJavaTypeCustomization() {
BindInfo info = builder.getBindInfo(getReferer());
BIConversion conv = info.get(BIConversion.class);
if( conv != null ) {
// ack this conversion to prevent further error messages
conv.markAsAcknowledged();
// report the error
getErrorReporter().error( conv.getLocation(),
Messages.ERR_UNNESTED_JAVATYPE_CUSTOMIZATION_ON_SIMPLETYPE );
}
}
/**
* Recursively decend the type inheritance chain to find a binding.
*/
TypeUse compose( XSSimpleType t ) {
TypeUse e = find(t);
if(e!=null) return e;
return t.apply(composer);
}
public final XSSimpleTypeFunction<TypeUse> composer = new XSSimpleTypeFunction<TypeUse>() {
public TypeUse listSimpleType(XSListSimpleType type) {
// bind item type individually and then compose them into a list
// facets on the list shouldn't be taken account when binding item types,
// so weed to call build(), not compose().
XSSimpleType itemType = type.getItemType();
refererStack.push(itemType);
TypeUse tu = TypeUseFactory.makeCollection(build(type.getItemType()));
refererStack.pop();
return tu;
}
public TypeUse unionSimpleType(XSUnionSimpleType type) {
boolean isCollection = false;
for( int i=0; i<type.getMemberSize(); i++ )
if(type.getMember(i).getVariety()==XSVariety.LIST || type.getMember(i).getVariety()==XSVariety.UNION) {
isCollection = true;
break;
}
TypeUse r = CBuiltinLeafInfo.STRING;
if(isCollection)
r = TypeUseFactory.makeCollection(r);
return r;
}
public TypeUse restrictionSimpleType(XSRestrictionSimpleType type) {
// just process the base type.
return compose(type.getSimpleBaseType());
}
};
/**
* Checks if there's any binding available on the given type.
*
* @return
* null if not (which causes the {@link #compose(XSSimpleType)} method
* to do ascending.
*/
private TypeUse find( XSSimpleType type ) {
TypeUse r;
boolean noAutoEnum = false;
// check for user specified conversion
BindInfo info = builder.getBindInfo(type);
BIConversion conv = info.get(BIConversion.class);
if( conv!=null ) {
// a conversion was found
conv.markAsAcknowledged();
return conv.getTypeUse(type);
}
// look for enum customization, which is another user specified conversion
BIEnum en = info.get(BIEnum.class);
if( en!=null ) {
en.markAsAcknowledged();
if(!en.isMapped()) {
noAutoEnum = true;
} else {
// if an enum customization is specified, make sure
// the type is OK
if( !canBeMappedToTypeSafeEnum(type) ) {
getErrorReporter().error( en.getLocation(),
Messages.ERR_CANNOT_BE_TYPE_SAFE_ENUM );
getErrorReporter().error( type.getLocator(),
Messages.ERR_CANNOT_BE_TYPE_SAFE_ENUM_LOCATION );
// recover by ignoring this customization
return null;
}
// reference?
if(en.ref!=null) {
if(!JJavaName.isFullyQualifiedClassName(en.ref)) {
Ring.get(ErrorReceiver.class).error( en.getLocation(),
Messages.format(Messages.ERR_INCORRECT_CLASS_NAME, en.ref) );
// recover by ignoring @ref
return null;
}
return new CClassRef(model, type, en, info.toCustomizationList() );
}
// list and union cannot be mapped to a type-safe enum,
// so in this stage we can safely cast it to XSRestrictionSimpleType
return bindToTypeSafeEnum( (XSRestrictionSimpleType)type,
en.className, en.javadoc, en.members,
getEnumMemberMode().getModeWithEnum(),
en.getLocation() );
}
}
// if the type is built in, look for the default binding
if(type.getTargetNamespace().equals(WellKnownNamespace.XML_SCHEMA)) {
String name = type.getName();
if(name!=null) {
r = lookupBuiltin(name);
if(r!=null)
return r;
}
}
// also check for swaRef
if(type.getTargetNamespace().equals(WellKnownNamespace.SWA_URI)) {
String name = type.getName();
if(name!=null && name.equals("swaRef"))
return CBuiltinLeafInfo.STRING.makeAdapted(SwaRefAdapterMarker.class,false);
}
// see if this type should be mapped to a type-safe enumeration by default.
// if so, built a EnumXDucer from it and return it.
if(type.isRestriction() && !noAutoEnum) {
XSRestrictionSimpleType rst = type.asRestriction();
if(shouldBeMappedToTypeSafeEnumByDefault(rst)) {
r = bindToTypeSafeEnum(rst,null,null, Collections.<String, BIEnumMember>emptyMap(),
getEnumMemberMode(),null);
if(r!=null)
return r;
}
}
return (CNonElement)getClassSelector()._bindToClass(type,null,false);
}
private static Set<XSRestrictionSimpleType> reportedEnumMemberSizeWarnings;
/**
* Returns true if a type-safe enum should be created from
* the given simple type by default without an explicit &lt;jaxb:enum> customization.
*/
private boolean shouldBeMappedToTypeSafeEnumByDefault( XSRestrictionSimpleType type ) {
// if not, there will be a problem wrt the class name of this type safe enum type.
if( type.isLocal() ) return false;
// if redefined, we should map the new definition, not the old one.
if( type.getRedefinedBy()!=null ) return false;
List<XSFacet> facets = type.getDeclaredFacets(XSFacet.FACET_ENUMERATION);
if( facets.isEmpty() )
// if the type itself doesn't have the enumeration facet,
// it won't be mapped to a type-safe enum.
return false;
if(facets.size() > builder.getGlobalBinding().getDefaultEnumMemberSizeCap()) {
// if there are too many facets, it's not very useful
// produce warning when simple type is not mapped to enum
// see issue https://jaxb.dev.java.net/issues/show_bug.cgi?id=711
if(reportedEnumMemberSizeWarnings == null)
reportedEnumMemberSizeWarnings = new HashSet<XSRestrictionSimpleType>();
if(!reportedEnumMemberSizeWarnings.contains(type)) {
getErrorReporter().warning(type.getLocator(), Messages.WARN_ENUM_MEMBER_SIZE_CAP,
type.getName(), facets.size(), builder.getGlobalBinding().getDefaultEnumMemberSizeCap());
reportedEnumMemberSizeWarnings.add(type);
}
return false;
}
if( !canBeMappedToTypeSafeEnum(type) )
// we simply can't map this to an enumeration
return false;
// check for collisions among constant names. if a collision will happen,
// don't try to bind it to an enum.
// return true only when this type is derived from one of the "enum base type".
for( XSSimpleType t = type; t!=null; t=t.getSimpleBaseType() )
if( t.isGlobal() && builder.getGlobalBinding().canBeMappedToTypeSafeEnum(t) )
return true;
return false;
}
private static final Set<String> builtinTypeSafeEnumCapableTypes;
static {
Set<String> s = new HashSet<String>();
// see a bullet of 6.5.1 of the spec.
String[] typeNames = new String[] {
"string", "boolean", "float", "decimal", "double", "anyURI"
};
s.addAll(Arrays.asList(typeNames));
builtinTypeSafeEnumCapableTypes = Collections.unmodifiableSet(s);
}
/**
* Returns true if the given simple type can be mapped to a
* type-safe enum class.
*
* <p>
* JAXB spec places a restrictrion as to what type can be
* mapped to a type-safe enum. This method enforces this
* constraint.
*/
public static boolean canBeMappedToTypeSafeEnum( XSSimpleType type ) {
do {
if( WellKnownNamespace.XML_SCHEMA.equals(type.getTargetNamespace()) ) {
// type must be derived from one of these types
String localName = type.getName();
if( localName!=null ) {
if( localName.equals("anySimpleType") )
return false; // catch all case
if( localName.equals("ID") || localName.equals("IDREF") )
return false; // not ID/IDREF
// other allowed list
if( builtinTypeSafeEnumCapableTypes.contains(localName) )
return true;
}
}
type = type.getSimpleBaseType();
} while( type!=null );
return false;
}
/**
* Builds a type-safe enum conversion from a simple type
* with enumeration facets.
*
* @param className
* The class name of the type-safe enum. Or null to
* create a default name.
* @param javadoc
* Additional javadoc that will be added at the beginning of the
* class, or null if none is necessary.
* @param members
* A map from enumeration values (as String) to BIEnumMember objects.
* if some of the value names need to be overrided.
* Cannot be null, but the map may not contain entries
* for all enumeration values.
* @param loc
* The source location where the above customizations are
* specified, or null if none is available.
*/
private TypeUse bindToTypeSafeEnum( XSRestrictionSimpleType type,
String className, String javadoc, Map<String,BIEnumMember> members,
EnumMemberMode mode, Locator loc ) {
if( loc==null ) // use the location of the simple type as the default
loc = type.getLocator();
if( className==null ) {
// infer the class name. For this to be possible,
// the simple type must be a global one.
if( !type.isGlobal() ) {
getErrorReporter().error( loc, Messages.ERR_NO_ENUM_NAME_AVAILABLE );
// recover by returning a meaningless conversion
return CBuiltinLeafInfo.STRING;
}
className = type.getName();
}
// we apply name conversion in any case
className = builder.deriveName(className,type);
{// compute Javadoc
StringWriter out = new StringWriter();
SchemaWriter sw = new SchemaWriter(new JavadocEscapeWriter(out));
type.visit((XSVisitor)sw);
if(javadoc!=null) javadoc += "\n\n";
else javadoc = "";
javadoc += Messages.format( Messages.JAVADOC_HEADING, type.getName() )
+"\n<p>\n<pre>\n"+out.getBuffer()+"</pre>";
}
// build base type
refererStack.push(type.getSimpleBaseType());
TypeUse use = build(type.getSimpleBaseType());
refererStack.pop();
if(use.isCollection())
return null; // can't bind a list to enum constant
CNonElement baseDt = use.getInfo(); // for now just ignore that case
if(baseDt instanceof CClassInfo)
return null; // can't bind to an enum if the base is a class, since we don't have the value constrctor
// if the member names collide, re-generate numbered constant names.
XSFacet[] errorRef = new XSFacet[1];
List<CEnumConstant> memberList = buildCEnumConstants(type, false, members, errorRef);
if(memberList==null || checkMemberNameCollision(memberList)!=null) {
switch(mode) {
case SKIP:
// abort
return null;
case ERROR:
// error
if(memberList==null) {
getErrorReporter().error( errorRef[0].getLocator(),
Messages.ERR_CANNOT_GENERATE_ENUM_NAME,
errorRef[0].getValue() );
} else {
CEnumConstant[] collision = checkMemberNameCollision(memberList);
getErrorReporter().error( collision[0].getLocator(),
Messages.ERR_ENUM_MEMBER_NAME_COLLISION,
collision[0].getName() );
getErrorReporter().error( collision[1].getLocator(),
Messages.ERR_ENUM_MEMBER_NAME_COLLISION_RELATED );
}
return null; // recover from error
case GENERATE:
// generate
memberList = buildCEnumConstants(type,true,members,null);
break;
}
}
if(memberList.isEmpty()) {
getErrorReporter().error( loc, Messages.ERR_NO_ENUM_FACET );
return null;
}
// use the name of the simple type as the name of the class.
CClassInfoParent scope;
if(type.isGlobal())
scope = new CClassInfoParent.Package(getClassSelector().getPackage(type.getTargetNamespace()));
else
scope = getClassSelector().getClassScope();
CEnumLeafInfo xducer = new CEnumLeafInfo( model, BGMBuilder.getName(type), scope,
className, baseDt, memberList, type,
builder.getBindInfo(type).toCustomizationList(), loc );
xducer.javadoc = javadoc;
BIConversion conv = new BIConversion.Static( type.getLocator(),xducer);
conv.markAsAcknowledged();
// attach this new conversion object to this simple type
// so that successive look up will use the same object.
builder.getOrCreateBindInfo(type).addDecl(conv);
return conv.getTypeUse(type);
}
/**
*
* @param errorRef
* if constant names couldn't be generated, return a reference to that enum facet.
* @return
* null if unable to generate names for some of the constants.
*/
private List<CEnumConstant> buildCEnumConstants(XSRestrictionSimpleType type, boolean needsToGenerateMemberName, Map<String, BIEnumMember> members, XSFacet[] errorRef) {
List<CEnumConstant> memberList = new ArrayList<CEnumConstant>();
int idx=1;
Set<String> enums = new HashSet<String>(); // to avoid duplicates. See issue #366
for( XSFacet facet : type.getDeclaredFacets(XSFacet.FACET_ENUMERATION)) {
String name=null;
String mdoc=builder.getBindInfo(facet).getDocumentation();
if(!enums.add(facet.getValue().value))
continue; // ignore the 2nd occasion
if( needsToGenerateMemberName ) {
// generate names for all member names.
// this will even override names specified by the user. that's crazy.
name = "VALUE_"+(idx++);
} else {
String facetValue = facet.getValue().value;
BIEnumMember mem = members.get(facetValue);
if( mem==null )
// look at the one attached to the facet object
mem = builder.getBindInfo(facet).get(BIEnumMember.class);
if (mem!=null) {
name = mem.name;
if (mdoc == null) {
mdoc = mem.javadoc;
}
}
if(name==null) {
StringBuilder sb = new StringBuilder();
for( int i=0; i<facetValue.length(); i++) {
char ch = facetValue.charAt(i);
if(Character.isJavaIdentifierPart(ch))
sb.append(ch);
else
sb.append('_');
}
name = model.getNameConverter().toConstantName(sb.toString());
}
}
if(!JJavaName.isJavaIdentifier(name)) {
if(errorRef!=null) errorRef[0] = facet;
return null; // unable to generate a name
}
memberList.add(new CEnumConstant(name,mdoc,facet.getValue().value,facet,builder.getBindInfo(facet).toCustomizationList(),facet.getLocator()));
}
return memberList;
}
/**
* Returns non-null if {@link CEnumConstant}s have name collisions among them.
*
* @return
* if there's a collision, return two {@link CEnumConstant}s that collided.
* otherwise return null.
*/
private CEnumConstant[] checkMemberNameCollision( List<CEnumConstant> memberList ) {
Map<String,CEnumConstant> names = new HashMap<String,CEnumConstant>();
for (CEnumConstant c : memberList) {
CEnumConstant old = names.put(c.getName(),c);
if(old!=null)
// collision detected
return new CEnumConstant[]{old,c};
}
return null;
}
private EnumMemberMode getEnumMemberMode() {
return builder.getGlobalBinding().getEnumMemberMode();
}
private TypeUse lookupBuiltin( String typeLocalName ) {
if(typeLocalName.equals("integer") || typeLocalName.equals("long")) {
/*
attempt an optimization so that we can
improve the binding for types like this:
<simpleType>
<restriciton baseType="integer">
<maxInclusive value="100" />
</
</
... to int, not BigInteger.
*/
BigInteger xe = readFacet(XSFacet.FACET_MAXEXCLUSIVE,-1);
BigInteger xi = readFacet(XSFacet.FACET_MAXINCLUSIVE,0);
BigInteger max = min(xe,xi); // most restrictive one takes precedence
if(max!=null) {
BigInteger ne = readFacet(XSFacet.FACET_MINEXCLUSIVE,+1);
BigInteger ni = readFacet(XSFacet.FACET_MININCLUSIVE,0);
BigInteger min = max(ne,ni);
if(min!=null) {
if(min.compareTo(INT_MIN )>=0 && max.compareTo(INT_MAX )<=0)
typeLocalName = "int";
else
if(min.compareTo(LONG_MIN)>=0 && max.compareTo(LONG_MAX)<=0)
typeLocalName = "long";
}
}
} else
if(typeLocalName.equals("boolean") && isRestrictedTo0And1()) {
// this is seen in the SOAP schema and too common to ignore
return CBuiltinLeafInfo.BOOLEAN_ZERO_OR_ONE;
} else
if(typeLocalName.equals("base64Binary")) {
return lookupBinaryTypeBinding();
} else
if(typeLocalName.equals("anySimpleType")) {
if(getReferer() instanceof XSAttributeDecl || getReferer() instanceof XSSimpleType)
return CBuiltinLeafInfo.STRING;
else
return CBuiltinLeafInfo.ANYTYPE;
}
return builtinConversions.get(typeLocalName);
}
/**
* Decides the way xs:base64Binary binds.
*
* This method checks the expected media type.
*/
private TypeUse lookupBinaryTypeBinding() {
XSComponent referer = getReferer();
String emt = referer.getForeignAttribute(XML_MIME_URI, Const.EXPECTED_CONTENT_TYPES);
if(emt!=null) {
acknowledgedXmimeContentTypes.add(referer);
try {
// see http://www.xml.com/lpt/a/2004/07/21/dive.html
List<MimeTypeRange> types = MimeTypeRange.parseRanges(emt);
MimeTypeRange mt = MimeTypeRange.merge(types);
// see spec table I-1 in appendix I section 2.1.1 for bindings
if(mt.majorType.equalsIgnoreCase("image"))
return CBuiltinLeafInfo.IMAGE.makeMimeTyped(mt.toMimeType());
if(( mt.majorType.equalsIgnoreCase("application") || mt.majorType.equalsIgnoreCase("text"))
&& isXml(mt.subType))
return CBuiltinLeafInfo.XML_SOURCE.makeMimeTyped(mt.toMimeType());
if((mt.majorType.equalsIgnoreCase("text") && (mt.subType.equalsIgnoreCase("plain")) )) {
return CBuiltinLeafInfo.STRING.makeMimeTyped(mt.toMimeType());
}
return CBuiltinLeafInfo.DATA_HANDLER.makeMimeTyped(mt.toMimeType());
} catch (ParseException e) {
getErrorReporter().error( referer.getLocator(),
Messages.format(Messages.ERR_ILLEGAL_EXPECTED_MIME_TYPE,emt, e.getMessage()) );
// recover by using the default
} catch (MimeTypeParseException e) {
getErrorReporter().error( referer.getLocator(),
Messages.format(Messages.ERR_ILLEGAL_EXPECTED_MIME_TYPE,emt, e.getMessage()) );
}
}
// default
return CBuiltinLeafInfo.BASE64_BYTE_ARRAY;
}
public boolean isAcknowledgedXmimeContentTypes(XSComponent c) {
return acknowledgedXmimeContentTypes.contains(c);
}
/**
* Returns true if the specified sub-type is an XML type.
*/
private boolean isXml(String subType) {
return subType.equals("xml") || subType.endsWith("+xml");
}
/**
* Returns true if the {@link #initiatingType} is restricted
* to '0' and '1'. This logic is not complete, but it at least
* finds the such definition in SOAP @mustUnderstand.
*/
private boolean isRestrictedTo0And1() {
XSFacet pattern = initiatingType.getFacet(XSFacet.FACET_PATTERN);
if(pattern!=null) {
String v = pattern.getValue().value;
if(v.equals("0|1") || v.equals("1|0") || v.equals("\\d"))
return true;
}
XSFacet enumf = initiatingType.getFacet(XSFacet.FACET_ENUMERATION);
if(enumf!=null) {
String v = enumf.getValue().value;
if(v.equals("0") || v.equals("1"))
return true;
}
return false;
}
private BigInteger readFacet(String facetName,int offset) {
XSFacet me = initiatingType.getFacet(facetName);
if(me==null)
return null;
BigInteger bi = DatatypeConverter.parseInteger(me.getValue().value);
if(offset!=0)
bi = bi.add(BigInteger.valueOf(offset));
return bi;
}
private BigInteger min(BigInteger a, BigInteger b) {
if(a==null) return b;
if(b==null) return a;
return a.min(b);
}
private BigInteger max(BigInteger a, BigInteger b) {
if(a==null) return b;
if(b==null) return a;
return a.max(b);
}
private static final BigInteger LONG_MIN = BigInteger.valueOf(Long.MIN_VALUE);
private static final BigInteger LONG_MAX = BigInteger.valueOf(Long.MAX_VALUE);
private static final BigInteger INT_MIN = BigInteger.valueOf(Integer.MIN_VALUE);
private static final BigInteger INT_MAX = BigInteger.valueOf(Integer.MAX_VALUE);
static {
// list of datatypes which have built-in conversions.
// note that although xs:token and xs:normalizedString are not
// specified in the spec, they need to be here because they
// have different whitespace normalization semantics.
Map<String,TypeUse> m = builtinConversions;
// TODO: this is so dumb
m.put("string", CBuiltinLeafInfo.STRING);
m.put("anyURI", CBuiltinLeafInfo.STRING);
m.put("boolean", CBuiltinLeafInfo.BOOLEAN);
// we'll also look at the expected media type, so don't just add this to the map
// m.put("base64Binary", CBuiltinLeafInfo.BASE64_BYTE_ARRAY);
m.put("hexBinary", CBuiltinLeafInfo.HEXBIN_BYTE_ARRAY);
m.put("float", CBuiltinLeafInfo.FLOAT);
m.put("decimal", CBuiltinLeafInfo.BIG_DECIMAL);
m.put("integer", CBuiltinLeafInfo.BIG_INTEGER);
m.put("long", CBuiltinLeafInfo.LONG);
m.put("unsignedInt", CBuiltinLeafInfo.LONG);
m.put("int", CBuiltinLeafInfo.INT);
m.put("unsignedShort", CBuiltinLeafInfo.INT);
m.put("short", CBuiltinLeafInfo.SHORT);
m.put("unsignedByte", CBuiltinLeafInfo.SHORT);
m.put("byte", CBuiltinLeafInfo.BYTE);
m.put("double", CBuiltinLeafInfo.DOUBLE);
m.put("QName", CBuiltinLeafInfo.QNAME);
m.put("NOTATION", CBuiltinLeafInfo.QNAME);
m.put("dateTime", CBuiltinLeafInfo.CALENDAR);
m.put("date", CBuiltinLeafInfo.CALENDAR);
m.put("time", CBuiltinLeafInfo.CALENDAR);
m.put("gYearMonth", CBuiltinLeafInfo.CALENDAR);
m.put("gYear", CBuiltinLeafInfo.CALENDAR);
m.put("gMonthDay", CBuiltinLeafInfo.CALENDAR);
m.put("gDay", CBuiltinLeafInfo.CALENDAR);
m.put("gMonth", CBuiltinLeafInfo.CALENDAR);
m.put("duration", CBuiltinLeafInfo.DURATION);
m.put("token", CBuiltinLeafInfo.TOKEN);
m.put("normalizedString",CBuiltinLeafInfo.NORMALIZED_STRING);
m.put("ID", CBuiltinLeafInfo.ID);
m.put("IDREF", CBuiltinLeafInfo.IDREF);
// TODO: handling dateTime, time, and date type
// String[] names = {
// "date", "dateTime", "time", "hexBinary" };
}
}

View File

@@ -0,0 +1,267 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.xmlschema;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import com.sun.tools.internal.xjc.reader.Const;
import com.sun.tools.internal.xjc.reader.Ring;
import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIDeclaration;
import com.sun.xml.internal.bind.v2.WellKnownNamespace;
import com.sun.xml.internal.xsom.XSAnnotation;
import com.sun.xml.internal.xsom.XSAttContainer;
import com.sun.xml.internal.xsom.XSAttGroupDecl;
import com.sun.xml.internal.xsom.XSAttributeDecl;
import com.sun.xml.internal.xsom.XSAttributeUse;
import com.sun.xml.internal.xsom.XSComplexType;
import com.sun.xml.internal.xsom.XSComponent;
import com.sun.xml.internal.xsom.XSContentType;
import com.sun.xml.internal.xsom.XSElementDecl;
import com.sun.xml.internal.xsom.XSFacet;
import com.sun.xml.internal.xsom.XSIdentityConstraint;
import com.sun.xml.internal.xsom.XSListSimpleType;
import com.sun.xml.internal.xsom.XSModelGroup;
import com.sun.xml.internal.xsom.XSModelGroupDecl;
import com.sun.xml.internal.xsom.XSNotation;
import com.sun.xml.internal.xsom.XSParticle;
import com.sun.xml.internal.xsom.XSRestrictionSimpleType;
import com.sun.xml.internal.xsom.XSSchema;
import com.sun.xml.internal.xsom.XSSchemaSet;
import com.sun.xml.internal.xsom.XSSimpleType;
import com.sun.xml.internal.xsom.XSUnionSimpleType;
import com.sun.xml.internal.xsom.XSWildcard;
import com.sun.xml.internal.xsom.XSXPath;
import com.sun.xml.internal.xsom.visitor.XSSimpleTypeVisitor;
import com.sun.xml.internal.xsom.visitor.XSVisitor;
/**
* Reports all unacknowledged customizations as errors.
*
* <p>
* Since we scan the whole content tree, we use this to check for unused
* <tt>xmime:expectedContentTypes</tt> attributes. TODO: if we find this kind of error checks more
* common, use the visitors so that we don't have to mix everything in one class.
*
* @author
* Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
*/
class UnusedCustomizationChecker extends BindingComponent implements XSVisitor, XSSimpleTypeVisitor {
private final BGMBuilder builder = Ring.get(BGMBuilder.class);
private final SimpleTypeBuilder stb = Ring.get(SimpleTypeBuilder.class);
private final Set<XSComponent> visitedComponents = new HashSet<XSComponent>();
/**
* Runs the check.
*/
void run() {
for( XSSchema s : Ring.get(XSSchemaSet.class).getSchemas() ) {
schema(s);
run( s.getAttGroupDecls() );
run( s.getAttributeDecls() );
run( s.getComplexTypes() );
run( s.getElementDecls() );
run( s.getModelGroupDecls() );
run( s.getNotations() );
run( s.getSimpleTypes() );
}
}
private void run( Map<String,? extends XSComponent> col ) {
for( XSComponent c : col.values() )
c.visit(this);
}
/**
* Checks unused customizations on this component
* and returns true if this is the first time this
* component is checked.
*/
private boolean check( XSComponent c ) {
if( !visitedComponents.add(c) )
return false; // already processed
for( BIDeclaration decl : builder.getBindInfo(c).getDecls() )
check(decl, c);
checkExpectedContentTypes(c);
return true;
}
private void checkExpectedContentTypes(XSComponent c) {
if(c.getForeignAttribute(WellKnownNamespace.XML_MIME_URI, Const.EXPECTED_CONTENT_TYPES)==null)
return; // no such attribute
if(c instanceof XSParticle)
return; // particles get the same foreign attributes as local element decls,
// so we need to skip them
if(!stb.isAcknowledgedXmimeContentTypes(c)) {
// this is not used
getErrorReporter().warning(c.getLocator(),Messages.WARN_UNUSED_EXPECTED_CONTENT_TYPES);
}
}
private void check(BIDeclaration decl, XSComponent c) {
if( !decl.isAcknowledged() ) {
getErrorReporter().error(
decl.getLocation(),
Messages.ERR_UNACKNOWLEDGED_CUSTOMIZATION,
decl.getName().getLocalPart()
);
getErrorReporter().error(
c.getLocator(),
Messages.ERR_UNACKNOWLEDGED_CUSTOMIZATION_LOCATION);
// mark it as acknowledged to avoid
// duplicated error messages.
decl.markAsAcknowledged();
}
for (BIDeclaration d : decl.getChildren())
check(d,c);
}
public void annotation(XSAnnotation ann) {}
public void attGroupDecl(XSAttGroupDecl decl) {
if(check(decl))
attContainer(decl);
}
public void attributeDecl(XSAttributeDecl decl) {
if(check(decl))
decl.getType().visit((XSSimpleTypeVisitor)this);
}
public void attributeUse(XSAttributeUse use) {
if(check(use))
use.getDecl().visit(this);
}
public void complexType(XSComplexType type) {
if(check(type)) {
// don't need to check the base type -- it must be global, thus
// it is covered already
type.getContentType().visit(this);
attContainer(type);
}
}
private void attContainer( XSAttContainer cont ) {
for( Iterator itr = cont.iterateAttGroups(); itr.hasNext(); )
((XSAttGroupDecl)itr.next()).visit(this);
for( Iterator itr = cont.iterateDeclaredAttributeUses(); itr.hasNext(); )
((XSAttributeUse)itr.next()).visit(this);
XSWildcard wc = cont.getAttributeWildcard();
if(wc!=null) wc.visit(this);
}
public void schema(XSSchema schema) {
check(schema);
}
public void facet(XSFacet facet) {
check(facet);
}
public void notation(XSNotation notation) {
check(notation);
}
public void wildcard(XSWildcard wc) {
check(wc);
}
public void modelGroupDecl(XSModelGroupDecl decl) {
if(check(decl))
decl.getModelGroup().visit(this);
}
public void modelGroup(XSModelGroup group) {
if(check(group)) {
for( int i=0; i<group.getSize(); i++ )
group.getChild(i).visit(this);
}
}
public void elementDecl(XSElementDecl decl) {
if(check(decl)) {
decl.getType().visit(this);
for( XSIdentityConstraint id : decl.getIdentityConstraints() )
id.visit(this);
}
}
public void simpleType(XSSimpleType simpleType) {
if(check(simpleType))
simpleType.visit( (XSSimpleTypeVisitor)this );
}
public void particle(XSParticle particle) {
if(check(particle))
particle.getTerm().visit(this);
}
public void empty(XSContentType empty) {
check(empty);
}
public void listSimpleType(XSListSimpleType type) {
if(check(type))
type.getItemType().visit((XSSimpleTypeVisitor)this);
}
public void restrictionSimpleType(XSRestrictionSimpleType type) {
if(check(type))
type.getBaseType().visit(this);
}
public void unionSimpleType(XSUnionSimpleType type) {
if(check(type)) {
for( int i=0; i<type.getMemberSize(); i++ )
type.getMember(i).visit((XSSimpleTypeVisitor)this);
}
}
public void identityConstraint(XSIdentityConstraint id) {
if(check(id)) {
id.getSelector().visit(this);
for( XSXPath xp : id.getFields() )
xp.visit(this);
}
}
public void xpath(XSXPath xp) {
check(xp);
}
}

View File

@@ -0,0 +1,84 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.xmlschema;
import java.util.Iterator;
import com.sun.xml.internal.xsom.XSWildcard;
import com.sun.xml.internal.xsom.visitor.XSWildcardFunction;
import com.sun.xml.internal.rngom.nc.AnyNameExceptNameClass;
import com.sun.xml.internal.rngom.nc.ChoiceNameClass;
import com.sun.xml.internal.rngom.nc.NameClass;
import com.sun.xml.internal.rngom.nc.NsNameClass;
/**
* Builds a name class representation of a wildcard.
*
* <p>
* Singleton. Use the build method to create a NameClass.
*
* @author
* Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
*/
public final class WildcardNameClassBuilder implements XSWildcardFunction<NameClass> {
private WildcardNameClassBuilder() {}
private static final XSWildcardFunction<NameClass> theInstance =
new WildcardNameClassBuilder();
public static NameClass build( XSWildcard wc ) {
return wc.apply(theInstance);
}
public NameClass any(XSWildcard.Any wc) {
return NameClass.ANY;
}
public NameClass other(XSWildcard.Other wc) {
return new AnyNameExceptNameClass(
new ChoiceNameClass(
new NsNameClass(""),
new NsNameClass(wc.getOtherNamespace())));
}
public NameClass union(XSWildcard.Union wc) {
NameClass nc = null;
for (Iterator itr = wc.iterateNamespaces(); itr.hasNext();) {
String ns = (String) itr.next();
if(nc==null) nc = new NsNameClass(ns);
else
nc = new ChoiceNameClass(nc,new NsNameClass(ns));
}
// there should be at least one.
assert nc!=null;
return nc;
}
}

View File

@@ -0,0 +1,87 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.xmlschema.bindinfo;
import java.util.Collection;
import java.util.Collections;
import com.sun.codemodel.internal.JCodeModel;
import com.sun.tools.internal.xjc.reader.Ring;
import com.sun.tools.internal.xjc.reader.xmlschema.BGMBuilder;
import com.sun.xml.internal.bind.annotation.XmlLocation;
import com.sun.xml.internal.xsom.XSComponent;
import org.xml.sax.Locator;
/**
* Abstract partial implementation of {@link BIDeclaration}
*
* @author
* Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
*/
abstract class AbstractDeclarationImpl implements BIDeclaration {
@Deprecated // eventually delete this in favor of using JAXB
protected AbstractDeclarationImpl(Locator loc) {
this.loc = loc;
}
protected AbstractDeclarationImpl() {}
@XmlLocation
Locator loc; // set by JAXB
public Locator getLocation() { return loc; }
protected BindInfo parent;
public void setParent(BindInfo p) { this.parent=p; }
protected final XSComponent getOwner() {
return parent.getOwner();
}
protected final BGMBuilder getBuilder() {
return parent.getBuilder();
}
protected final JCodeModel getCodeModel() {
return Ring.get(JCodeModel.class);
}
private boolean isAcknowledged = false;
public final boolean isAcknowledged() { return isAcknowledged; }
public void onSetOwner() {
}
public Collection<BIDeclaration> getChildren() {
return Collections.emptyList();
}
public void markAsAcknowledged() {
isAcknowledged = true;
}
}

View File

@@ -0,0 +1,159 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.xmlschema.bindinfo;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.UnmarshallerHandler;
import javax.xml.bind.helpers.DefaultValidationEventHandler;
import javax.xml.validation.ValidatorHandler;
import com.sun.tools.internal.xjc.Options;
import com.sun.tools.internal.xjc.reader.Const;
import com.sun.xml.internal.xsom.parser.AnnotationContext;
import com.sun.xml.internal.xsom.parser.AnnotationParser;
import com.sun.xml.internal.xsom.parser.AnnotationParserFactory;
import com.sun.xml.internal.bind.v2.WellKnownNamespace;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.EntityResolver;
import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.helpers.XMLFilterImpl;
/**
* Implementation of XSOM {@link AnnotationParserFactory} that
* parses JAXB customization declarations.
*
* @author
* Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
*/
public class AnnotationParserFactoryImpl implements AnnotationParserFactory {
public AnnotationParserFactoryImpl(Options opts) {
this.options=opts;
}
private final Options options;
/**
* Lazily created validator, so that the schema for binding won't be
* prepared unless absolutely necessary.
*/
private ValidatorHandler validator;
public AnnotationParser create() {
return new AnnotationParser() {
private Unmarshaller u = BindInfo.getCustomizationUnmarshaller();
private UnmarshallerHandler handler;
public ContentHandler getContentHandler(
AnnotationContext context, String parentElementName,
final ErrorHandler errorHandler, EntityResolver entityResolver ) {
// return a ContentHandler that validates the customization and also
// parses them into the internal structure.
if(handler!=null)
// interface contract violation.
// this method will be called only once.
throw new AssertionError();
if(options.debugMode)
try {
u.setEventHandler(new DefaultValidationEventHandler());
} catch (JAXBException e) {
throw new AssertionError(e); // ridiculous!
}
handler = u.getUnmarshallerHandler();
// configure so that the validator will receive events for JAXB islands
return new ForkingFilter(handler) {
@Override
public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {
super.startElement(uri, localName, qName, atts);
if((uri.equals(Const.JAXB_NSURI) || uri.equals(Const.XJC_EXTENSION_URI))
&& getSideHandler()==null) {
// set up validator
if(validator==null)
validator = BindInfo.bindingFileSchema.newValidator();
validator.setErrorHandler(errorHandler);
startForking(uri,localName,qName,atts,new ValidatorProtecter(validator));
}
// check for xmime:expectedContentTypes attributes in annotations and report them
for( int i=atts.getLength()-1; i>=0; i-- ) {
if(atts.getURI(i).equals(WellKnownNamespace.XML_MIME_URI)
&& atts.getLocalName(i).equals(Const.EXPECTED_CONTENT_TYPES))
errorHandler.warning(new SAXParseException(
com.sun.tools.internal.xjc.reader.xmlschema.Messages.format(
com.sun.tools.internal.xjc.reader.xmlschema.Messages.WARN_UNUSED_EXPECTED_CONTENT_TYPES),
getDocumentLocator()
));
}
}
};
}
public BindInfo getResult( Object existing ) {
if(handler==null)
// interface contract violation.
// the getContentHandler method must have been called.
throw new AssertionError();
try {
BindInfo result = (BindInfo)handler.getResult();
if(existing!=null) {
BindInfo bie = (BindInfo)existing;
bie.absorb(result);
return bie;
} else {
if(!result.isPointless())
return result; // just annotation. no meaningful customization
else
return null;
}
} catch (JAXBException e) {
throw new AssertionError(e);
}
}
};
}
private static final class ValidatorProtecter extends XMLFilterImpl {
public ValidatorProtecter(ContentHandler h) {
setContentHandler(h);
}
@Override
public void startPrefixMapping(String prefix, String uri) throws SAXException {
// work around a bug in the validator implementation in Tiger
super.startPrefixMapping(prefix.intern(),uri);
}
}
}

View File

@@ -0,0 +1,131 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.xmlschema.bindinfo;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.namespace.QName;
import com.sun.tools.internal.xjc.reader.Const;
import com.sun.xml.internal.bind.api.impl.NameConverter;
import com.sun.istack.internal.Nullable;
/**
* Class declaration.
*
* This customization turns arbitrary schema component into a Java
* content interface.
*
* <p>
* This customization is acknowledged by the ClassSelector.
*
* @author
* Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
*/
@XmlRootElement(name="class")
public final class BIClass extends AbstractDeclarationImpl {
protected BIClass() {
}
@XmlAttribute(name="name")
private String className;
/**
* Gets the specified class name, or null if not specified.
* (Not a fully qualified name.)
*
* @return
* Returns a class name. The caller should <em>NOT</em>
* apply XML-to-Java name conversion to the name
* returned from this method.
*/
public @Nullable String getClassName() {
if( className==null ) return null;
BIGlobalBinding gb = getBuilder().getGlobalBinding();
NameConverter nc = getBuilder().model.getNameConverter();
if(gb.isJavaNamingConventionEnabled()) return nc.toClassName(className);
else
// don't change it
return className;
}
@XmlAttribute(name="implClass")
private String userSpecifiedImplClass;
/**
* Gets the fully qualified name of the
* user-specified implementation class, if any.
* Or null.
*/
public String getUserSpecifiedImplClass() {
return userSpecifiedImplClass;
}
@XmlAttribute(name="ref")
private String ref;
@XmlAttribute(name="recursive", namespace=Const.XJC_EXTENSION_URI)
private String recursive;
/**
* Reference to the existing class, or null.
* Fully qualified name.
*
* <p>
* Caller needs to perform error check on this.
*/
public String getExistingClassRef() {
return ref;
}
public String getRecursive() {
return recursive;
}
@XmlElement
private String javadoc;
/**
* Gets the javadoc comment specified in the customization.
* Can be null if none is specified.
*/
public String getJavadoc() { return javadoc; }
public QName getName() { return NAME; }
public void setParent(BindInfo p) {
super.setParent(p);
// if this specifies a reference to external class,
// then it's OK even if noone actually refers this class.
if(ref!=null)
markAsAcknowledged();
}
/** Name of this declaration. */
public static final QName NAME = new QName( Const.JAXB_NSURI, "class" );
}

View File

@@ -0,0 +1,349 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.xmlschema.bindinfo;
import javax.xml.bind.DatatypeConverter;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import javax.xml.namespace.QName;
import com.sun.codemodel.internal.JClass;
import com.sun.codemodel.internal.JClassAlreadyExistsException;
import com.sun.codemodel.internal.JCodeModel;
import com.sun.codemodel.internal.JDefinedClass;
import com.sun.codemodel.internal.JExpr;
import com.sun.codemodel.internal.JExpression;
import com.sun.codemodel.internal.JMethod;
import com.sun.codemodel.internal.JMod;
import com.sun.codemodel.internal.JPackage;
import com.sun.codemodel.internal.JType;
import com.sun.codemodel.internal.JVar;
import com.sun.codemodel.internal.JConditional;
import com.sun.tools.internal.xjc.ErrorReceiver;
import com.sun.tools.internal.xjc.model.CAdapter;
import com.sun.tools.internal.xjc.model.CBuiltinLeafInfo;
import com.sun.tools.internal.xjc.model.TypeUse;
import com.sun.tools.internal.xjc.model.TypeUseFactory;
import com.sun.tools.internal.xjc.reader.Const;
import com.sun.tools.internal.xjc.reader.Ring;
import com.sun.tools.internal.xjc.reader.TypeUtil;
import com.sun.tools.internal.xjc.reader.xmlschema.ClassSelector;
import com.sun.xml.internal.bind.v2.WellKnownNamespace;
import com.sun.xml.internal.xsom.XSSimpleType;
import org.xml.sax.Locator;
/**
* Conversion declaration.
*
* <p>
* A conversion declaration specifies how an XML type gets mapped
* to a Java type.
*
* @author
* Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
*/
public abstract class BIConversion extends AbstractDeclarationImpl {
@Deprecated
public BIConversion( Locator loc ) {
super(loc);
}
protected BIConversion() {
}
/**
* Gets the {@link TypeUse} object that this conversion represents.
* <p>
* The returned {@link TypeUse} object is properly adapted.
*
* @param owner
* A {@link BIConversion} is always associated with one
* {@link XSSimpleType}, but that's not always available
* when a {@link BIConversion} is built. So we pass this
* as a parameter to this method.
*/
public abstract TypeUse getTypeUse( XSSimpleType owner );
public QName getName() { return NAME; }
/** Name of the conversion declaration. */
public static final QName NAME = new QName(
Const.JAXB_NSURI, "conversion" );
/**
* Implementation that returns a statically-determined constant {@link TypeUse}.
*/
public static final class Static extends BIConversion {
/**
* Always non-null.
*/
private final TypeUse transducer;
public Static(Locator loc, TypeUse transducer) {
super(loc);
this.transducer = transducer;
}
public TypeUse getTypeUse(XSSimpleType owner) {
return transducer;
}
}
/**
* User-specified &lt;javaType> customization.
*
* The parse/print methods are allowed to be null,
* and their default values are determined based on the
* owner of the token.
*/
@XmlRootElement(name="javaType")
public static class User extends BIConversion {
@XmlAttribute
private String parseMethod;
@XmlAttribute
private String printMethod;
@XmlAttribute(name="name")
private String type = "java.lang.String";
/**
* If null, computed from {@link #type}.
* Sometimes this can be set instead of {@link #type}.
*/
private JType inMemoryType;
public User(Locator loc, String parseMethod, String printMethod, JType inMemoryType) {
super(loc);
this.parseMethod = parseMethod;
this.printMethod = printMethod;
this.inMemoryType = inMemoryType;
}
public User() {
}
/**
* Cache used by {@link #getTypeUse(XSSimpleType)} to improve the performance.
*/
private TypeUse typeUse;
public TypeUse getTypeUse(XSSimpleType owner) {
if(typeUse!=null)
return typeUse;
JCodeModel cm = getCodeModel();
if(inMemoryType==null)
inMemoryType = TypeUtil.getType(cm,type,Ring.get(ErrorReceiver.class),getLocation());
JDefinedClass adapter = generateAdapter(parseMethodFor(owner),printMethodFor(owner),owner);
// XmlJavaType customization always converts between string and an user-defined type.
typeUse = TypeUseFactory.adapt(CBuiltinLeafInfo.STRING,new CAdapter(adapter));
return typeUse;
}
/**
* generate the adapter class.
*/
private JDefinedClass generateAdapter(String parseMethod, String printMethod,XSSimpleType owner) {
JDefinedClass adapter = null;
int id = 1;
while(adapter==null) {
try {
JPackage pkg = Ring.get(ClassSelector.class).getClassScope().getOwnerPackage();
adapter = pkg._class("Adapter"+id);
} catch (JClassAlreadyExistsException e) {
// try another name in search for an unique name.
// this isn't too efficient, but we expect people to usually use
// a very small number of adapters.
id++;
}
}
JClass bim = inMemoryType.boxify();
adapter._extends(getCodeModel().ref(XmlAdapter.class).narrow(String.class).narrow(bim));
JMethod unmarshal = adapter.method(JMod.PUBLIC, bim, "unmarshal");
JVar $value = unmarshal.param(String.class, "value");
JExpression inv;
if( parseMethod.equals("new") ) {
// "new" indicates that the constructor of the target type
// will do the unmarshalling.
// RESULT: new <type>()
inv = JExpr._new(bim).arg($value);
} else {
int idx = parseMethod.lastIndexOf('.');
if(idx<0) {
// parseMethod specifies the static method of the target type
// which will do the unmarshalling.
// because of an error check at the constructor,
// we can safely assume that this cast works.
inv = bim.staticInvoke(parseMethod).arg($value);
} else {
inv = JExpr.direct(parseMethod+"(value)");
}
}
unmarshal.body()._return(inv);
JMethod marshal = adapter.method(JMod.PUBLIC, String.class, "marshal");
$value = marshal.param(bim,"value");
if(printMethod.startsWith("javax.xml.bind.DatatypeConverter.")) {
// UGLY: if this conversion is the system-driven conversion,
// check for null
marshal.body()._if($value.eq(JExpr._null()))._then()._return(JExpr._null());
}
int idx = printMethod.lastIndexOf('.');
if(idx<0) {
// printMethod specifies a method in the target type
// which performs the serialization.
// RESULT: <value>.<method>()
inv = $value.invoke(printMethod);
// check value is not null ... if(value == null) return null;
JConditional jcon = marshal.body()._if($value.eq(JExpr._null()));
jcon._then()._return(JExpr._null());
} else {
// RESULT: <className>.<method>(<value>)
if(this.printMethod==null) {
// HACK HACK HACK
JType t = inMemoryType.unboxify();
inv = JExpr.direct(printMethod+"(("+findBaseConversion(owner).toLowerCase()+")("+t.fullName()+")value)");
} else
inv = JExpr.direct(printMethod+"(value)");
}
marshal.body()._return(inv);
return adapter;
}
private String printMethodFor(XSSimpleType owner) {
if(printMethod!=null) return printMethod;
if(inMemoryType.unboxify().isPrimitive()) {
String method = getConversionMethod("print",owner);
if(method!=null)
return method;
}
return "toString";
}
private String parseMethodFor(XSSimpleType owner) {
if(parseMethod!=null) return parseMethod;
if(inMemoryType.unboxify().isPrimitive()) {
String method = getConversionMethod("parse", owner);
if(method!=null) {
// this cast is necessary for conversion between primitive Java types
return '('+inMemoryType.unboxify().fullName()+')'+method;
}
}
return "new";
}
private static final String[] knownBases = new String[]{
"Float", "Double", "Byte", "Short", "Int", "Long", "Boolean"
};
private String getConversionMethod(String methodPrefix, XSSimpleType owner) {
String bc = findBaseConversion(owner);
if(bc==null) return null;
return DatatypeConverter.class.getName()+'.'+methodPrefix+bc;
}
private String findBaseConversion(XSSimpleType owner) {
// find the base simple type mapping.
for( XSSimpleType st=owner; st!=null; st = st.getSimpleBaseType() ) {
if( !WellKnownNamespace.XML_SCHEMA.equals(st.getTargetNamespace()) )
continue; // user-defined type
String name = st.getName().intern();
for( String s : knownBases )
if(name.equalsIgnoreCase(s))
return s;
}
return null;
}
public QName getName() { return NAME; }
/** Name of the conversion declaration. */
public static final QName NAME = new QName(
Const.JAXB_NSURI, "javaType" );
}
@XmlRootElement(name="javaType",namespace=Const.XJC_EXTENSION_URI)
public static class UserAdapter extends BIConversion {
@XmlAttribute(name="name")
private String type = null;
@XmlAttribute
private String adapter = null;
private TypeUse typeUse;
public TypeUse getTypeUse(XSSimpleType owner) {
if(typeUse!=null)
return typeUse;
JCodeModel cm = getCodeModel();
JDefinedClass a;
try {
a = cm._class(adapter);
a.hide(); // we assume this is given by the user
a._extends(cm.ref(XmlAdapter.class).narrow(String.class).narrow(
cm.ref(type)));
} catch (JClassAlreadyExistsException e) {
a = e.getExistingClass();
}
// TODO: it's not correct to say that it adapts from String,
// but OTOH I don't think we can compute that.
typeUse = TypeUseFactory.adapt(
CBuiltinLeafInfo.STRING,
new CAdapter(a));
return typeUse;
}
}
}

View File

@@ -0,0 +1,105 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.internal.xjc.reader.xmlschema.bindinfo;
import java.util.Collection;
import javax.xml.namespace.QName;
import com.sun.tools.internal.xjc.reader.xmlschema.BGMBuilder;
import org.xml.sax.Locator;
/**
* Base interface for all binding customization declarations.
*
* <p>
* Because of the setParent method, one customization declaration
* can be attached to one component alone.
*
* @author
* Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
*/
public interface BIDeclaration {
/**
* Sets the parent BindInfo object of this declaration.
* A declaration object can use this pointer to access
* context information, such as other customizations.
*
* <p>
* This method can be only called from {@link BindInfo},
* and only once. This is a good opportunity to do some
* follow-up initialization after JAXB unmarshalling
* populated {@link BIDeclaration}.
*/
void setParent( BindInfo parent );
/**
* Gets the name of this binding declaration,
* which is the same as the tag name of the binding element.
*/
QName getName();
/**
* Gets the source location where this declaration was written.
* For declarations that are generated by XJC itself,
* this method returns null.
*/
Locator getLocation();
/**
* Marks this declaration to be acknowledged -- either actually
* used or the existence is admitted (for example when
* a property customization is given at the point of definition.)
*
* <p>
* Declarations that are not acknowledged will be considered
* as an error.
*/
void markAsAcknowledged();
/**
* Checks if this declaration was acknowledged.
*/
boolean isAcknowledged();
/**
* Called when the parent {@link BindInfo} got its owner set.
*
* This is when declarations are connected to {@link BGMBuilder} and
* its sibling components.
*/
void onSetOwner();
/**
* Gets child {@link BIDeclaration}s if any.
*
* @return
* can be empty but always non-null. read-only.
*/
Collection<BIDeclaration> getChildren();
}

Some files were not shown because too many files have changed in this diff Show More