Mercurial > hg > release > icedtea7-forest-2.5 > jaxws
changeset 84:eec5a3bbff72
6813167: Missing files
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/istack/internal/Builder.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,33 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.istack.internal; + +/** + * + * @author Martin Grebac + */ +public interface Builder<T> { + T build(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/istack/internal/localization/Localizable.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,63 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.istack.internal.localization; + +/** + * Localizable message. + * + * @author WS Development Team + */ +public interface Localizable { + /** + * Gets the key in the resource bundle. + * + * @return + * if this method returns {@link #NOT_LOCALIZABLE}, + * that means the message is not localizable, and + * the first item of {@link #getArguments()} array + * holds a String. + */ + public String getKey(); + + /** + * Returns the arguments for message formatting. + * + * @return + * can be an array of length 0 but never be null. + */ + public Object[] getArguments(); + public String getResourceBundleName(); + + + /** + * Special constant that represents a message that + * is not localizable. + * + * <p> + * Use of "new" is to create an unique instance. + */ + public static final String NOT_LOCALIZABLE = new String("\u0000"); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/istack/internal/localization/LocalizableMessage.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,56 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.istack.internal.localization; + +/** + * @author WS Development Team + */ +public final class LocalizableMessage implements Localizable { + + private final String _bundlename; + private final String _key; + private final Object[] _args; + + public LocalizableMessage(String bundlename, String key, Object... args) { + _bundlename = bundlename; + _key = key; + if(args==null) + args = new Object[0]; + _args = args; + } + + public String getKey() { + return _key; + } + + public Object[] getArguments() { + return _args; + } + + public String getResourceBundleName() { + return _bundlename; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/istack/internal/localization/LocalizableMessageFactory.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,43 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.istack.internal.localization; + +/** + * @author WS Development Team + */ +public class LocalizableMessageFactory { + + private final String _bundlename; + + public LocalizableMessageFactory(String bundlename) { + _bundlename = bundlename; + } + + public Localizable getMessage(String key, Object... args) { + return new LocalizableMessage(_bundlename, key, args); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/istack/internal/localization/Localizer.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,149 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.istack.internal.localization; + +import java.text.MessageFormat; +import java.util.HashMap; +import java.util.Locale; +import java.util.MissingResourceException; +import java.util.ResourceBundle; + +/** + * Localizes the {@link Localizable} into a message + * by using a configured {@link Locale}. + * + * @author WS Development Team + */ +public class Localizer { + + private final Locale _locale; + private final HashMap _resourceBundles; + + public Localizer() { + this(Locale.getDefault()); + } + + public Localizer(Locale l) { + _locale = l; + _resourceBundles = new HashMap(); + } + + public Locale getLocale() { + return _locale; + } + + public String localize(Localizable l) { + String key = l.getKey(); + if (key == Localizable.NOT_LOCALIZABLE) { + // this message is not localizable + return (String) l.getArguments()[0]; + } + String bundlename = l.getResourceBundleName(); + + try { + ResourceBundle bundle = + (ResourceBundle) _resourceBundles.get(bundlename); + + if (bundle == null) { + try { + bundle = ResourceBundle.getBundle(bundlename, _locale); + } catch (MissingResourceException e) { + // work around a bug in the com.sun.enterprise.deployment.WebBundleArchivist: + // all files with an extension different from .class (hence all the .properties files) + // get copied to the top level directory instead of being in the package where they + // are defined + // so, since we can't find the bundle under its proper name, we look for it under + // the top-level package + + int i = bundlename.lastIndexOf('.'); + if (i != -1) { + String alternateBundleName = + bundlename.substring(i + 1); + try { + bundle = + ResourceBundle.getBundle( + alternateBundleName, + _locale); + } catch (MissingResourceException e2) { + // give up + return getDefaultMessage(l); + } + } + } + + _resourceBundles.put(bundlename, bundle); + } + + if (bundle == null) { + return getDefaultMessage(l); + } + + if (key == null) + key = "undefined"; + + String msg; + try { + msg = bundle.getString(key); + } catch (MissingResourceException e) { + // notice that this may throw a MissingResourceException of its own (caught below) + msg = bundle.getString("undefined"); + } + + // localize all arguments to the given localizable object + Object[] args = l.getArguments(); + for (int i = 0; i < args.length; ++i) { + if (args[i] instanceof Localizable) + args[i] = localize((Localizable) args[i]); + } + + String message = MessageFormat.format(msg, args); + return message; + + } catch (MissingResourceException e) { + return getDefaultMessage(l); + } + + } + + private String getDefaultMessage(Localizable l) { + String key = l.getKey(); + Object[] args = l.getArguments(); + StringBuilder sb = new StringBuilder(); + sb.append("[failed to localize] "); + sb.append(key); + if (args != null) { + sb.append('('); + for (int i = 0; i < args.length; ++i) { + if (i != 0) + sb.append(", "); + sb.append(String.valueOf(args[i])); + } + sb.append(')'); + } + return sb.toString(); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/tools/internal/jxc/SchemaGeneratorFacade.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,56 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.tools.internal.jxc; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +/** + * CLI entry point to schemagen that checks for JDK 5.0 + * @author Kohsuke Kawaguchi + */ +public class SchemaGeneratorFacade { + + public static void main(String[] args) throws Throwable { + try { + ClassLoader cl = SchemaGeneratorFacade.class.getClassLoader(); + if(cl==null) cl = ClassLoader.getSystemClassLoader(); + + Class driver = cl.loadClass("com.sun.tools.internal.jxc.SchemaGenerator"); + Method mainMethod = driver.getDeclaredMethod("main", new Class[]{String[].class}); + try { + mainMethod.invoke(null,new Object[]{args}); + } catch (IllegalAccessException e) { + throw e; + } catch (InvocationTargetException e) { + if(e.getTargetException()!=null) + throw e.getTargetException(); + } + } catch (UnsupportedClassVersionError e) { + System.err.println("schemagen requires JDK 5.0 or later. Please download it from http://java.sun.com/j2se/1.5/"); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/tools/internal/ws/api/WsgenExtension.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,43 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.tools.internal.ws.api; + +/** + * Allows to customize wsgen behaviour using this extension. + * The extension implementations are found using service + * discovery mechanism i.e. JAX-WS tooltime locates + * {@link WsgenExtension}s through the + * <tt>META-INF/services/com.sun.tools.internal.ws.api.WsgenExtension</tt> + * files. + * + * {@link WsgenProtocol} annotation can be specified on the + * extensions to extend -wsdl[:protocol] behaviour. + * + * @author Jitendra Kotamraju + * @since JAX-WS RI 2.1.6 + * @see WsgenProtocol + */ +public abstract class WsgenExtension { +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/tools/internal/ws/api/WsgenProtocol.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,52 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.tools.internal.ws.api; + +import java.lang.annotation.*; + +/** + * Allows to extend protocol for wsgen's wsdl[:protocol] switch. + * This annotation must be specified on {@link WsgenExtension} + * implementations. + * + * @author Jitendra Kotamraju + * @since JAX-WS RI 2.1.6 + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface WsgenProtocol { + /** + * Token for wsgen -wsdl[:protocol] + * @return + */ + String token(); + + /** + * The corresponding lexical string used to create BindingID + * @return + */ + String lexical(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/tools/internal/ws/wscompile/AuthInfo.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,64 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.tools.internal.ws.wscompile; + +import com.sun.istack.internal.NotNull; + +import java.net.URL; + +/** + * Represents authorization information needed by {@link com.sun.tools.internal.ws.wscompile.DefaultAuthenticator} to + * authenticate wsimport to access the wsdl. + * + * @author Vivek Pandey + */ + +public final class AuthInfo { + private final String user; + private final String password; + private final URL url; + + public AuthInfo(@NotNull URL url, @NotNull String user, @NotNull String password){ + this.url = url; + this.user = user; + this.password = password; + } + + public String getUser() { + return user; + } + + public String getPassword() { + return password; + } + + /** + * Returns if the requesting host and port are associated with this {@link AuthInfo} + */ + public boolean matchingHost(@NotNull URL requestingURL) { + return requestingURL.equals(url); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/tools/internal/ws/wscompile/DefaultAuthTester.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,66 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.tools.internal.ws.wscompile; + +import com.sun.istack.internal.NotNull; +import com.sun.tools.internal.ws.processor.modeler.wsdl.ConsoleErrorReporter; + +import java.io.File; +import java.net.MalformedURLException; +import java.net.PasswordAuthentication; +import java.net.URL; +import java.util.Arrays; + +/** + * @author Vivek Pandey + */ +public class DefaultAuthTester { + public static void main(String[] args) throws BadCommandLineException { + DefaultAuthenticator da = new MyAuthenticator(new ConsoleErrorReporter(System.out), new File("c:\\Users\\vivekp\\.metro\\auth")); + + PasswordAuthentication pa = da.getPasswordAuthentication(); + if(pa!= null && pa.getUserName().equals("vivek") && Arrays.equals(pa.getPassword(), "test".toCharArray())) + System.out.println("Success!"); + else + System.out.println("Failiure!"); + + } + + private static class MyAuthenticator extends DefaultAuthenticator{ + + public MyAuthenticator(@NotNull ErrorReceiver receiver, @NotNull File authfile) throws BadCommandLineException { + super(receiver, authfile); + } + + protected URL getRequestingURL() { + try { + return new URL("http://foo.com/myservice?wsdl"); + } catch (MalformedURLException e) { + e.printStackTrace(); + } + return null; + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/tools/internal/ws/wscompile/DefaultAuthenticator.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,154 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.tools.internal.ws.wscompile; + +import com.sun.istack.internal.NotNull; +import com.sun.tools.internal.ws.resources.WscompileMessages; +import org.xml.sax.SAXParseException; +import org.xml.sax.helpers.LocatorImpl; + +import java.io.*; +import java.net.Authenticator; +import java.net.PasswordAuthentication; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; + +/** + * @author Vivek Pandey + */ +public class DefaultAuthenticator extends Authenticator { + + private final List<AuthInfo> authInfo = new ArrayList<AuthInfo>(); + private final ErrorReceiver errReceiver; + private final String proxyUser; + private final String proxyPasswd; + + //can user.home value be null? + public static final String defaultAuthfile = System.getProperty("user.home")+ System.getProperty("file.separator")+".metro"+System.getProperty("file.separator")+"auth"; + private File authFile = new File(defaultAuthfile); + private boolean giveError; + + public DefaultAuthenticator(@NotNull ErrorReceiver receiver, @NotNull File authfile) throws BadCommandLineException { + this.errReceiver = receiver; + this.proxyUser = System.getProperty("http.proxyUser"); + this.proxyPasswd = System.getProperty("http.proxyPassword"); + + if(authfile != null){ + this.authFile = authfile; + this.giveError = true; + } + + if(!authFile.exists()){ + try { + error(new SAXParseException(WscompileMessages.WSIMPORT_AUTH_FILE_NOT_FOUND(authFile.getCanonicalPath(), defaultAuthfile), null)); + } catch (IOException e) { + error(new SAXParseException(WscompileMessages.WSIMPORT_FAILED_TO_PARSE(authFile,e.getMessage()), null)); + } + return; + } + + if(!authFile.canRead()){ + error(new SAXParseException("Authorization file: "+authFile + " does not have read permission!", null)); + return; + } + parseAuth(); + } + + protected PasswordAuthentication getPasswordAuthentication() { + //If user sets proxy user and passwd and the RequestType is from proxy server then create + // PasswordAuthentication using proxyUser and proxyClass; + if((getRequestorType() == RequestorType.PROXY) && proxyUser != null && proxyPasswd != null){ + return new PasswordAuthentication(proxyUser, proxyPasswd.toCharArray()); + } + for(AuthInfo auth:authInfo){ + if(auth.matchingHost(getRequestingURL())){ + return new PasswordAuthentication(auth.getUser(), auth.getPassword().toCharArray()); + } + } + return null; + } + + private void parseAuth() { + errReceiver.info(new SAXParseException(WscompileMessages.WSIMPORT_READING_AUTH_FILE(authFile), null)); + + BufferedReader in; + try { + in = new BufferedReader(new InputStreamReader(new FileInputStream(authFile), "UTF-8")); + } catch (UnsupportedEncodingException e) { + error(new SAXParseException(e.getMessage(), null)); + return; + } catch (FileNotFoundException e) { + error(new SAXParseException(WscompileMessages.WSIMPORT_AUTH_FILE_NOT_FOUND(authFile, defaultAuthfile), null, e)); + return; + } + String text; + LocatorImpl locator = new LocatorImpl(); + try { + int lineno = 1; + + locator.setSystemId(authFile.getCanonicalPath()); + + while ((text = in.readLine()) != null) { + locator.setLineNumber(lineno++); + try { + URL url = new URL(text); + String authinfo = url.getUserInfo(); + + if (authinfo != null) { + int i = authinfo.indexOf(':'); + + if (i >= 0) { + String user = authinfo.substring(0, i); + String password = authinfo.substring(i + 1); + authInfo.add(new AuthInfo(new URL(text), user, password)); + } else { + error(new SAXParseException(WscompileMessages.WSIMPORT_ILLEGAL_AUTH_INFO(url), locator)); + } + } else { + error(new SAXParseException(WscompileMessages.WSIMPORT_ILLEGAL_AUTH_INFO(url), locator)); + } + + } catch (NumberFormatException e) { + error(new SAXParseException(WscompileMessages.WSIMPORT_ILLEGAL_AUTH_INFO(text), locator)); + } + } + in.close(); + } catch (IOException e) { + error(new SAXParseException(WscompileMessages.WSIMPORT_FAILED_TO_PARSE(authFile,e.getMessage()), locator)); + } + } + + /** + * When user provides authfile explicitly using -Xauthfile we throw error otherwise show the mesage by default with -Xdebug flag + */ + private void error(SAXParseException e){ + if(giveError){ + errReceiver.error(e); + } else{ + errReceiver.debug(e); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/tools/internal/ws/wsdl/parser/DOMForestParser.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,94 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.tools.internal.ws.wsdl.parser; + +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; + +import java.io.IOException; + +import com.sun.xml.internal.xsom.parser.XMLParser; + +/** + * {@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) + * @author Vivek Pandey + */ +public 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. + */ + public DOMForestParser(DOMForest forest, XMLParser fallbackParser) { + this.forest = forest; + this.scanner = new DOMForestScanner(forest); + this.fallbackParser = fallbackParser; + } + + + public void parse(InputSource source, ContentHandler handler, EntityResolver entityResolver, ErrorHandler errHandler) throws SAXException, IOException { + + } + + public void parse(InputSource source, ContentHandler handler, 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, handler, errorHandler, entityResolver); + return; + } + + scanner.scan(dom, handler); + + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/tools/internal/xjc/ClassLoaderBuilder.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,122 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.tools.internal.xjc; + +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import javax.xml.bind.JAXBContext; + +import com.sun.istack.internal.tools.MaskingClassLoader; +import com.sun.istack.internal.tools.ParallelWorldClassLoader; + +/** + * Creates a class loader configured to run XJC 1.0/2.0 safely without + * interference with JAXB 2.0 API in Mustang. + * + * @author Kohsuke Kawaguchi + */ +class ClassLoaderBuilder { + + /** + * Creates a new class loader that eventually delegates to the given {@link ClassLoader} + * such that XJC can be loaded by using this classloader. + * + * @param v + * Either "1.0" or "2.0", indicating the version of the -source value. + */ + protected static ClassLoader createProtectiveClassLoader(ClassLoader cl, String v) throws ClassNotFoundException, MalformedURLException { + if(noHack) return cl; // provide an escape hatch + + boolean mustang = false; + + if(JAXBContext.class.getClassLoader()==null) { + // JAXB API is loaded from the bootstrap. We need to override one with ours + mustang = true; + + List mask = new ArrayList(Arrays.asList(maskedPackages)); + mask.add("javax.xml.bind."); + + cl = new MaskingClassLoader(cl,mask); + + URL apiUrl = cl.getResource("javax/xml/bind/annotation/XmlSeeAlso.class"); + if(apiUrl==null) + throw new ClassNotFoundException("There's no JAXB 2.1 API in the classpath"); + + cl = new URLClassLoader(new URL[]{ParallelWorldClassLoader.toJarUrl(apiUrl)},cl); + } + + //Leave XJC2 in the publicly visible place + // and then isolate XJC1 in a child class loader, + // then use a MaskingClassLoader + // so that the XJC2 classes in the parent class loader + // won't interfere with loading XJC1 classes in a child class loader + + if (v.equals("1.0")) { + if(!mustang) + // if we haven't used Masking ClassLoader, do so now. + cl = new MaskingClassLoader(cl,toolPackages); + cl = new ParallelWorldClassLoader(cl,"1.0/"); + } else { + if(mustang) + // the whole RI needs to be loaded in a separate class loader + cl = new ParallelWorldClassLoader(cl,""); + } + + return cl; + } + + + /** + * The list of package prefixes we want the + * {@link MaskingClassLoader} to prevent the parent + * classLoader from loading + */ + private static String[] maskedPackages = new String[]{ + // toolPackages + alpha + "com.sun.tools.", + "com.sun.codemodel.internal.", + "com.sun.relaxng.", + "com.sun.xml.internal.xsom.", + "com.sun.xml.internal.bind.", + }; + + private static String[] toolPackages = new String[]{ + "com.sun.tools.", + "com.sun.codemodel.internal.", + "com.sun.relaxng.", + "com.sun.xml.internal.xsom." + }; + + /** + * Escape hatch in case this class loader hack breaks. + */ + public static final boolean noHack = Boolean.getBoolean(XJCFacade.class.getName()+".nohack"); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/tools/internal/xjc/XJCFacade.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,79 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.tools.internal.xjc; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +/** + * A shabby driver to invoke XJC1 or XJC2 depending on the command line switch. + * + * <p> + * This class is compiled with -source 1.2 so that we can report a nice user-friendly + * "you require Tiger" error message. + * + * @author Kohsuke Kawaguchi + */ +public class XJCFacade { + + public static void main(String[] args) throws Throwable { + String v = "2.0"; // by default, we go 2.0 + + for( int i=0; i<args.length; i++ ) { + if(args[i].equals("-source")) { + if(i+1<args.length) { + v = parseVersion(args[i+1]); + } + } + } + + try { + ClassLoader cl = ClassLoaderBuilder.createProtectiveClassLoader(XJCFacade.class.getClassLoader(), v); + + Class driver = cl.loadClass("com.sun.tools.internal.xjc.Driver"); + Method mainMethod = driver.getDeclaredMethod("main", new Class[]{String[].class}); + try { + mainMethod.invoke(null,new Object[]{args}); + } catch (IllegalAccessException e) { + throw e; + } catch (InvocationTargetException e) { + if(e.getTargetException()!=null) + throw e.getTargetException(); + } + } catch (UnsupportedClassVersionError e) { + System.err.println("XJC requires JDK 5.0 or later. Please download it from http://java.sun.com/j2se/1.5/"); + } + } + + private static String parseVersion(String version) { + if(version.equals("1.0")) + return version; + // if we don't recognize the version number, we'll go to 2.0 RI + // anyway. It's easier to report an error message there, + // than in here. + return "2.0"; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/tools/internal/xjc/generator/annotation/ri/OverrideAnnotationOfWriter.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,37 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.tools.internal.xjc.generator.annotation.ri; + +import com.sun.codemodel.internal.JAnnotationWriter; +import com.sun.xml.internal.bind.annotation.OverrideAnnotationOf; + +public interface OverrideAnnotationOfWriter + extends JAnnotationWriter<OverrideAnnotationOf> +{ + + + OverrideAnnotationOfWriter value(String value); + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/tools/internal/xjc/generator/bean/field/ContentListField.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,176 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.tools.internal.xjc.generator.bean.field; + +import java.util.ArrayList; +import java.util.List; + +import com.sun.codemodel.internal.JBlock; +import com.sun.codemodel.internal.JClass; +import com.sun.codemodel.internal.JExpr; +import com.sun.codemodel.internal.JExpression; +import com.sun.codemodel.internal.JMethod; +import com.sun.codemodel.internal.JType; +import com.sun.codemodel.internal.JVar; +import com.sun.tools.internal.xjc.generator.bean.ClassOutlineImpl; +import com.sun.tools.internal.xjc.generator.bean.MethodWriter; +import com.sun.tools.internal.xjc.model.CPropertyInfo; +import com.sun.tools.internal.xjc.outline.Aspect; +import com.sun.xml.internal.bind.api.impl.NameConverter; +import java.io.Serializable; + +/** + * Realizes a property as an untyped {@link List}. + * + * <pre> + * List getXXX(); + * </pre> + * + * <h2>Default value handling</h2> + * <p> + * Since unmarshaller just adds new values into the storage, + * we can't fill the storage by default values at the time of + * instanciation. (or oherwise values found in the document will + * be appended to default values, where it should overwrite them.) + * <p> + * Therefore, when the object is created, the storage will be empty. + * When the getXXX method is called, we'll check if the storage is + * modified in anyway. If it is modified, it must mean that the values + * are found in the document, so we just return it. + * + * Otherwise we will fill in default values and return it to the user. + * + * <p> + * When a list has default values, its dirty flag is set to true. + * Marshaller will check this and treat it appropriately. + * + * + * @author + * Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com) + */ +public class ContentListField extends AbstractListField { + + /** + * A concrete class that implements the List interface. + * An instance of this class will be used to store data + * for this field. + */ + private final JClass coreList; + + /** List getFIELD() method. */ + private JMethod $get; + + /** + * @param coreList + * A concrete class that implements the List interface. + * An instance of this class will be used to store data + * for this field. + */ + protected ContentListField(ClassOutlineImpl context, CPropertyInfo prop, JClass coreList) { + // the JAXB runtime picks ArrayList if the signature is List, + // so don't do eager allocation if it's ArrayList. + // otherwise we need to do eager allocation so that the collection type specified by the user + // will be used. + super(context, prop, false); + this.coreList = coreList; + generate(); + } + + protected final JClass getCoreListType() { + return coreList; + } + + @Override + public void generateAccessors() { + final MethodWriter writer = outline.createMethodWriter(); + final Accessor acc = create(JExpr._this()); + + // [RESULT] + // List getXXX() { + // return <ref>; + // } + $get = writer.declareMethod(listT,"get"+prop.getName(true)); + writer.javadoc().append(prop.javadoc); + JBlock block = $get.body(); + fixNullRef(block); // avoid using an internal getter + block._return(acc.ref(true)); + + String pname = NameConverter.standard.toVariableName(prop.getName(true)); + writer.javadoc().append( + "Gets the value of the "+pname+" property.\n\n"+ + "<p>\n" + + "This accessor method returns a reference to the live list,\n" + + "not a snapshot. Therefore any modification you make to the\n" + + "returned list will be present inside the JAXB object.\n" + + "This is why there is not a <CODE>set</CODE> method for the " +pname+ " property.\n" + + "\n"+ + "<p>\n" + + "For example, to add a new item, do as follows:\n"+ + "<pre>\n"+ + " get"+prop.getName(true)+"().add(newItem);\n"+ + "</pre>\n"+ + "\n\n" + ); + + writer.javadoc().append( + "<p>\n" + + "Objects of the following type(s) are allowed in the list\n") + .append(listPossibleTypes(prop)); + } + + public Accessor create(JExpression targetObject) { + return new Accessor(targetObject); + } + + class Accessor extends AbstractListField.Accessor { + protected Accessor( JExpression $target ) { + super($target); + } + + public void toRawValue(JBlock block, JVar $var) { + // [RESULT] + // $<var>.addAll(bean.getLIST()); + // list.toArray( array ); + block.assign($var,JExpr._new(codeModel.ref(ArrayList.class).narrow(exposedType.boxify())).arg( + $target.invoke($get) + )); + } + + public void fromRawValue(JBlock block, String uniqueName, JExpression $var) { + // [RESULT] + // bean.getLIST().addAll($<var>); + JVar $list = block.decl(listT,uniqueName+'l',$target.invoke($get)); + block.invoke($list,"addAll").arg($var); + } + } + + @Override + protected JType getType(final Aspect aspect) { + if (Aspect.IMPLEMENTATION.equals(aspect)) { + return super.getType(aspect); + } + return codeModel.ref(Serializable.class); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/tools/internal/xjc/generator/bean/field/DummyListField.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,152 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.tools.internal.xjc.generator.bean.field; + +import com.sun.codemodel.internal.JAnnotatable; +import java.util.ArrayList; +import java.util.List; + +import com.sun.codemodel.internal.JBlock; +import com.sun.codemodel.internal.JClass; +import com.sun.codemodel.internal.JExpr; +import com.sun.codemodel.internal.JExpression; +import com.sun.codemodel.internal.JMethod; +import com.sun.codemodel.internal.JVar; +import com.sun.tools.internal.xjc.generator.bean.ClassOutlineImpl; +import com.sun.tools.internal.xjc.model.CPropertyInfo; +import com.sun.tools.internal.xjc.model.CReferencePropertyInfo; +import com.sun.xml.internal.bind.annotation.OverrideAnnotationOf; + +/** + * Realizes a property as an untyped {@link List}. + * + * <pre> + * List getXXX(); + * </pre> + * + * <h2>Default value handling</h2> + * <p> + * Since unmarshaller just adds new values into the storage, + * we can't fill the storage by default values at the time of + * instanciation. (or oherwise values found in the document will + * be appended to default values, where it should overwrite them.) + * <p> + * Therefore, when the object is created, the storage will be empty. + * When the getXXX method is called, we'll check if the storage is + * modified in anyway. If it is modified, it must mean that the values + * are found in the document, so we just return it. + * + * Otherwise we will fill in default values and return it to the user. + * + * <p> + * When a list has default values, its dirty flag is set to true. + * Marshaller will check this and treat it appropriately. + * + * + * @author + * Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com) + */ +public class DummyListField extends AbstractListField { + + /** + * A concrete class that imp lements the List interface. + * An instance of this class will be used to store data + * for this field. + */ + private final JClass coreList; + + + /** List getFIELD() method. */ + private JMethod $get; + + /** + * @param coreList + * A concrete class that implements the List interface. + * An instance of this class will be used to store data + * for this field. + */ + protected DummyListField(ClassOutlineImpl context, CPropertyInfo prop, JClass coreList) { + // the JAXB runtime picks ArrayList if the signature is List, + // so don't do eager allocation if it's ArrayList. + // otherwise we need to do eager allocation so that the collection type specified by the user + // will be used. + super(context, prop, !coreList.fullName().equals("java.util.ArrayList")); + this.coreList = coreList.narrow(exposedType.boxify()); + generate(); + } + + /** + * Annotate the field according to the recipes given as {@link CPropertyInfo}. + */ + @Override + protected void annotate( JAnnotatable field ) { + super.annotate(field); + + if (prop instanceof CReferencePropertyInfo) { + CReferencePropertyInfo pref = (CReferencePropertyInfo)prop; + if (pref.isDummy()) { + annotateDummy(field); + } + } + + } + + private void annotateDummy(JAnnotatable field) { + field.annotate(OverrideAnnotationOf.class); + } + + protected final JClass getCoreListType() { + return coreList; + } + + @Override + public void generateAccessors() { } + + public Accessor create(JExpression targetObject) { + return new Accessor(targetObject); + } + + class Accessor extends AbstractListField.Accessor { + protected Accessor( JExpression $target ) { + super($target); + } + + public void toRawValue(JBlock block, JVar $var) { + // [RESULT] + // $<var>.addAll(bean.getLIST()); + // list.toArray( array ); + block.assign($var,JExpr._new(codeModel.ref(ArrayList.class).narrow(exposedType.boxify())).arg( + $target.invoke($get) + )); + } + + public void fromRawValue(JBlock block, String uniqueName, JExpression $var) { + // [RESULT] + // bean.getLIST().addAll($<var>); + JVar $list = block.decl(listT,uniqueName+'l',$target.invoke($get)); + block.invoke($list,"addAll").arg($var); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/tools/internal/xjc/generator/bean/field/NoExtendedContentField.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,187 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.tools.internal.xjc.generator.bean.field; + +import java.util.ArrayList; +import java.util.List; + +import com.sun.codemodel.internal.JBlock; +import com.sun.codemodel.internal.JClass; +import com.sun.codemodel.internal.JExpr; +import com.sun.codemodel.internal.JExpression; +import com.sun.codemodel.internal.JMethod; +import com.sun.codemodel.internal.JType; +import com.sun.codemodel.internal.JVar; +import com.sun.tools.internal.xjc.generator.bean.ClassOutlineImpl; +import com.sun.tools.internal.xjc.generator.bean.MethodWriter; +import com.sun.tools.internal.xjc.model.CElement; +import com.sun.tools.internal.xjc.model.CPropertyInfo; +import com.sun.tools.internal.xjc.model.CReferencePropertyInfo; +import com.sun.tools.internal.xjc.outline.Aspect; +import com.sun.xml.internal.bind.api.impl.NameConverter; +import java.io.Serializable; +import java.util.Set; + +/** + * Realizes a property as an untyped {@link List}. + * + * <pre> + * List getXXX(); + * </pre> + * + * <h2>Default value handling</h2> + * <p> + * Since unmarshaller just adds new values into the storage, + * we can't fill the storage by default values at the time of + * instanciation. (or oherwise values found in the document will + * be appended to default values, where it should overwrite them.) + * <p> + * Therefore, when the object is created, the storage will be empty. + * When the getXXX method is called, we'll check if the storage is + * modified in anyway. If it is modified, it must mean that the values + * are found in the document, so we just return it. + * + * Otherwise we will fill in default values and return it to the user. + * + * <p> + * When a list has default values, its dirty flag is set to true. + * Marshaller will check this and treat it appropriately. + * + * + * @author + * Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com) + */ +public class NoExtendedContentField extends AbstractListField { + + /** + * A concrete class that implements the List interface. + * An instance of this class will be used to store data + * for this field. + */ + private final JClass coreList; + + /** List getFIELD() method. */ + private JMethod $get; + + /** + * @param coreList + * A concrete class that implements the List interface. + * An instance of this class will be used to store data + * for this field. + */ + protected NoExtendedContentField(ClassOutlineImpl context, CPropertyInfo prop, JClass coreList) { + // the JAXB runtime picks ArrayList if the signature is List, + // so don't do eager allocation if it's ArrayList. + // otherwise we need to do eager allocation so that the collection type specified by the user + // will be used. + super(context, prop, false); + this.coreList = coreList; + generate(); + } + + protected final JClass getCoreListType() { + return coreList; + } + + @Override + public void generateAccessors() { + final MethodWriter writer = outline.createMethodWriter(); + final Accessor acc = create(JExpr._this()); + + // [RESULT] + // List getXXX() { + // return <ref>; + // } + $get = writer.declareMethod(listT,"get"+prop.getName(true)); + writer.javadoc().append(prop.javadoc); + JBlock block = $get.body(); + fixNullRef(block); // avoid using an internal getter + block._return(acc.ref(true)); + + String pname = NameConverter.standard.toVariableName(prop.getName(true)); + writer.javadoc().append( + "Gets the value of the "+pname+" property.\n\n"+ + "<p>\n" + + "This accessor method returns a reference to the live list,\n" + + "not a snapshot. Therefore any modification you make to the\n" + + "returned list will be present inside the JAXB object.\n" + + "This is why there is not a <CODE>set</CODE> method for the " +pname+ " property.\n" + + "\n"+ + "<p>\n" + + "For example, to add a new item, do as follows:\n"+ + "<pre>\n"+ + " get"+prop.getName(true)+"().add(newItem);\n"+ + "</pre>\n"+ + "\n\n" + ); + + writer.javadoc().append( + "<p>\n" + + "Objects of the following type(s) are allowed in the list\n") + .append(listPossibleTypes(prop)); + } + + public Accessor create(JExpression targetObject) { + return new Accessor(targetObject); + } + + class Accessor extends AbstractListField.Accessor { + protected Accessor( JExpression $target ) { + super($target); + } + + public void toRawValue(JBlock block, JVar $var) { + // [RESULT] + // $<var>.addAll(bean.getLIST()); + // list.toArray( array ); + block.assign($var,JExpr._new(codeModel.ref(ArrayList.class).narrow(getType(Aspect.EXPOSED).boxify())).arg( + $target.invoke($get) + )); + } + + public void fromRawValue(JBlock block, String uniqueName, JExpression $var) { + // [RESULT] + // bean.getLIST().addAll($<var>); + JVar $list = block.decl(listT,uniqueName+'l',$target.invoke($get)); + block.invoke($list,"addAll").arg($var); + } + } + + @Override + protected JType getType(final Aspect aspect) { + if (Aspect.IMPLEMENTATION.equals(aspect)) { + return super.getType(aspect); + } + + if (prop instanceof CReferencePropertyInfo) { + Set<CElement> elements = ((CReferencePropertyInfo)prop).getElements(); + if ((elements != null) && (elements.size() > 0)) { + return codeModel.ref(Serializable.class); + } + } + + return codeModel.ref(String.class); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/tools/internal/xjc/reader/xmlschema/bindinfo/BIFactoryMethod.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,64 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.tools.internal.xjc.reader.xmlschema.bindinfo; + +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.namespace.QName; + +import com.sun.xml.internal.xsom.XSComponent; +import com.sun.tools.internal.xjc.model.CPropertyInfo; +import com.sun.tools.internal.xjc.reader.Ring; +import com.sun.tools.internal.xjc.reader.Const; +import com.sun.tools.internal.xjc.reader.xmlschema.BGMBuilder; + +/** + * Controls the <tt>ObjectFactory</tt> method name. + * + * @author Kohsuke Kawaguchi + */ +@XmlRootElement(name="factoryMethod") +public class BIFactoryMethod extends AbstractDeclarationImpl { + @XmlAttribute + public String name; + + /** + * If the given component has {@link BIInlineBinaryData} customization, + * reflect that to the specified property. + */ + public static void handle(XSComponent source, CPropertyInfo prop) { + BIInlineBinaryData inline = Ring.get(BGMBuilder.class).getBindInfo(source).get(BIInlineBinaryData.class); + if(inline!=null) { + prop.inlineBinaryData = true; + inline.markAsAcknowledged(); + } + } + + + public final QName getName() { return NAME; } + + /** Name of the declaration. */ + public static final QName NAME = new QName(Const.JAXB_NSURI,"factoryMethod"); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/tools/internal/xjc/reader/xmlschema/bindinfo/BIInlineBinaryData.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,62 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.tools.internal.xjc.reader.xmlschema.bindinfo; + +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlInlineBinaryData; +import javax.xml.namespace.QName; + +import com.sun.tools.internal.xjc.reader.Const; +import com.sun.tools.internal.xjc.reader.Ring; +import com.sun.tools.internal.xjc.reader.xmlschema.BGMBuilder; +import com.sun.tools.internal.xjc.model.CPropertyInfo; +import com.sun.xml.internal.xsom.XSComponent; + +/** + * Generates {@link @XmlInlineBinaryData}. + * + * @author Kohsuke Kawaguchi + */ +@XmlRootElement(name="inlineBinaryData") +public class BIInlineBinaryData extends AbstractDeclarationImpl { + + /** + * If the given component has {@link BIInlineBinaryData} customization, + * reflect that to the specified property. + */ + public static void handle(XSComponent source, CPropertyInfo prop) { + BIInlineBinaryData inline = Ring.get(BGMBuilder.class).getBindInfo(source).get(BIInlineBinaryData.class); + if(inline!=null) { + prop.inlineBinaryData = true; + inline.markAsAcknowledged(); + } + } + + + public final QName getName() { return NAME; } + + /** Name of the declaration. */ + public static final QName NAME = new QName(Const.JAXB_NSURI,"inlineBinaryData"); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/tools/internal/xjc/reader/xmlschema/ct/AbstractExtendedComplexTypeBuilder.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,221 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.tools.internal.xjc.reader.xmlschema.ct; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import com.sun.tools.internal.xjc.reader.xmlschema.WildcardNameClassBuilder; +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.XSDeclaration; +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.XSType; +import com.sun.xml.internal.xsom.XSWildcard; +import com.sun.xml.internal.xsom.visitor.XSTermFunction; + +import com.sun.xml.internal.rngom.nc.ChoiceNameClass; +import com.sun.xml.internal.rngom.nc.NameClass; +import com.sun.xml.internal.rngom.nc.SimpleNameClass; + +/** + * Binds a complex type derived from another complex type by extension. + * + * @author + * Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com) + */ +abstract class AbstractExtendedComplexTypeBuilder extends CTBuilder { + + /** + * Map from {@link XSComplexType} to {@link NameClass}[2] that + * represents the names used in its child elements [0] and + * attributes [1]. + */ + protected final Map<XSComplexType, NameClass[]> characteristicNameClasses = new HashMap<XSComplexType, NameClass[]>(); + + /** + * Computes a name class that represents everything in a given content model. + */ + protected final XSTermFunction<NameClass> contentModelNameClassBuilder = new XSTermFunction<NameClass>() { + public NameClass wildcard(XSWildcard wc) { + return WildcardNameClassBuilder.build(wc); + } + + public NameClass modelGroupDecl(XSModelGroupDecl decl) { + return modelGroup(decl.getModelGroup()); + } + + public NameClass modelGroup(XSModelGroup group) { + NameClass nc = NameClass.NULL; + for( int i=0; i<group.getSize(); i++ ) + nc = new ChoiceNameClass(nc, group.getChild(i).getTerm().apply(this)); + return nc; + } + + public NameClass elementDecl(XSElementDecl decl) { + return getNameClass(decl); + } + }; + + /** + * Checks if the particles/attributes defined in the type parameter + * collides with the name classes of anc/enc. + * + * @return true if there's a collision. + */ + protected boolean checkCollision(NameClass anc, NameClass enc, XSComplexType type) { + NameClass[] chnc = characteristicNameClasses.get(type); + if (chnc == null) { + chnc = new NameClass[2]; + chnc[0] = getNameClass(type.getContentType()); + + // build attribute name classes + NameClass nc = NameClass.NULL; + Iterator itr = type.iterateAttributeUses(); + while( itr.hasNext() ) + anc = new ChoiceNameClass(anc, getNameClass(((XSAttributeUse) itr.next()).getDecl())); + XSWildcard wc = type.getAttributeWildcard(); + if(wc!=null) + nc = new ChoiceNameClass(nc, WildcardNameClassBuilder.build(wc)); + chnc[1] = nc; + + characteristicNameClasses.put(type, chnc); + } + + return chnc[0].hasOverlapWith(enc) || chnc[1].hasOverlapWith(anc); + } + + /** + * Looks for the derivation chain t_1 > t_2 > ... > t + * and find t_i such that t_i derives by restriction but + * for every j>i, t_j derives by extension. + * + * @return null + * If there's no such t_i or if t_i is any type. + */ + protected XSComplexType getLastRestrictedType(XSComplexType t) { + if (t.getBaseType() == schemas.getAnyType()) { + return null; // we don't count the restriction from anyType + } + if (t.getDerivationMethod() == XSType.RESTRICTION) { + return t; + } + + XSComplexType baseType = t.getBaseType().asComplexType(); + if (baseType != null) { + return getLastRestrictedType(baseType); + } else { + return null; + } + } + + /** + * Checks if this new extension is safe. + * + * UGLY. + * <p> + * If you have ctA extending ctB and ctB restricting ctC, our + * Java classes will look like CtAImpl extending CtBImpl + * extending CtCImpl. + * + * <p> + * Since a derived class unmarshaller uses the base class unmarshaller, + * this could potentially result in incorrect unmarshalling. + * We used to just reject such a case, but then we found that + * there are schemas that are using it. + * + * <p> + * One generalized observation that we reached is that if the extension + * is only adding new elements/attributes which has never been used + * in any of its base class (IOW, if none of the particle / attribute use / + * attribute wildcard can match the name of newly added elements/attributes) + * then it is safe to add them. + * + * <p> + * This function checks if the derivation chain to this type is + * not using restriction, and if it is, then checks if it is safe + * according to the above condition. + * + * @return false + * If this complex type needs to be rejected. + */ + protected boolean checkIfExtensionSafe(XSComplexType baseType, XSComplexType thisType) { + XSComplexType lastType = getLastRestrictedType(baseType); + + if (lastType == null) { + return true; // no restriction in derivation chain + } + NameClass anc = NameClass.NULL; + // build name class for attributes in new complex type + Iterator itr = thisType.iterateDeclaredAttributeUses(); + while (itr.hasNext()) { + anc = new ChoiceNameClass(anc, getNameClass(((XSAttributeUse) itr.next()).getDecl())); + } + // TODO: attribute wildcard + + NameClass enc = getNameClass(thisType.getExplicitContent()); + + // check against every base type ... except the root anyType + while (lastType != lastType.getBaseType()) { + if (checkCollision(anc, enc, lastType)) { + return false; + } + + if (lastType.getBaseType().isSimpleType()) // if the base type is a simple type, there won't be + // any further name collision. + { + return true; + } + + lastType = lastType.getBaseType().asComplexType(); + } + + return true; // OK + } + + /** + * Gets a {@link NameClass} that represents all the terms in the given content type. + * If t is not a particle, just return an empty name class. + */ + private NameClass getNameClass(XSContentType t) { + if(t==null) return NameClass.NULL; + XSParticle p = t.asParticle(); + if(p==null) return NameClass.NULL; + else return p.getTerm().apply(contentModelNameClassBuilder); + } + + /** + * Gets a {@link SimpleNameClass} from the name of a {@link XSDeclaration}. + */ + private NameClass getNameClass(XSDeclaration decl) { + return new SimpleNameClass(decl.getTargetNamespace(), decl.getName()); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/tools/internal/xjc/reader/xmlschema/ct/MixedExtendedComplexTypeBuilder.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,92 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.tools.internal.xjc.reader.xmlschema.ct; + +import com.sun.tools.internal.xjc.model.CClass; +import com.sun.tools.internal.xjc.model.CPropertyInfo; +import com.sun.tools.internal.xjc.reader.RawTypeSet; +import com.sun.tools.internal.xjc.reader.xmlschema.RawTypeSetBuilder; +import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIGlobalBinding; +import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIProperty; +import com.sun.xml.internal.xsom.XSComplexType; +import com.sun.xml.internal.xsom.XSContentType; +import com.sun.xml.internal.xsom.XSType; + +/** + * @author Kohsuke Kawaguchi + */ +final class MixedExtendedComplexTypeBuilder extends AbstractExtendedComplexTypeBuilder { + + public boolean isApplicable(XSComplexType ct) { + + if (!bgmBuilder.isGenerateMixedExtensions()) return false; + + XSType bt = ct.getBaseType(); + if (bt.isComplexType() && + bt.asComplexType().isMixed() && + ct.isMixed() && + ct.getDerivationMethod()==XSType.EXTENSION && + ct.getContentType().asParticle() != null && + ct.getExplicitContent().asEmpty() == null + ) { + return true; + } + + return false; + } + + public void build(XSComplexType ct) { + XSComplexType baseType = ct.getBaseType().asComplexType(); + + // build the base class + CClass baseClass = selector.bindToType(baseType, ct, true); + assert baseClass != null; // global complex type must map to a class + + if (!checkIfExtensionSafe(baseType, ct)) { + // error. We can't handle any further extension + errorReceiver.error(ct.getLocator(), + Messages.ERR_NO_FURTHER_EXTENSION.format( + baseType.getName(), ct.getName() ) + ); + return; + } + + selector.getCurrentBean().setBaseClass(baseClass); + builder.recordBindingMode(ct, ComplexTypeBindingMode.FALLBACK_EXTENSION); + + BIProperty prop = BIProperty.getCustomization(ct); + CPropertyInfo p; + + RawTypeSet ts = RawTypeSetBuilder.build(ct.getContentType().asParticle(), false); + p = prop.createDummyExtendedMixedReferenceProperty("contentOverrideFor" + ct.getName(), ct, ts); + + selector.getCurrentBean().addProperty(p); + + // adds attributes and we are through. + green.attContainer(ct); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/bind/annotation/OverrideAnnotationOf.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,42 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.xml.internal.bind.annotation; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +/** + * Designates an annotation from base class which shall be overriden by annotation placed together with this. + * + * @author Martin Grebac + */ +@Retention(RUNTIME) +@Target({FIELD}) +public @interface OverrideAnnotationOf { + String value() default "content"; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/bind/api/Messages.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,53 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + + +package com.sun.xml.internal.bind.api; + +import java.text.MessageFormat; +import java.util.ResourceBundle; + +/** + * Formats error messages. + * + * @since JAXB2.1.10 + */ + +enum Messages { + // TypeReference + ARGUMENT_CANT_BE_NULL + ; + + private static final ResourceBundle rb = ResourceBundle.getBundle(Messages.class.getName()); + + @Override + public String toString() { + return format(); + } + + public String format( Object... args ) { + return MessageFormat.format( rb.getString(name()), args ); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/bind/api/Messages.properties Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,27 @@ +# +# Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this +# particular file as subject to the "Classpath" exception as provided +# by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, +# CA 95054 USA or visit www.sun.com if you need additional information or +# have any questions. +# + +ARGUMENT_CANT_BE_NULL = \ + Argument(s) "{0}" can''t be null.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/bind/v2/model/annotation/XmlSchemaTypeQuick.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,66 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.xml.internal.bind.v2.model.annotation; + +import java.lang.annotation.Annotation; +import javax.xml.bind.annotation.XmlSchemaType; + +final class XmlSchemaTypeQuick + extends Quick + implements XmlSchemaType +{ + + private final XmlSchemaType core; + + public XmlSchemaTypeQuick(Locatable upstream, XmlSchemaType core) { + super(upstream); + this.core = core; + } + + protected Annotation getAnnotation() { + return core; + } + + protected Quick newInstance(Locatable upstream, Annotation core) { + return new XmlSchemaTypeQuick(upstream, ((XmlSchemaType) core)); + } + + public Class<XmlSchemaType> annotationType() { + return XmlSchemaType.class; + } + + public String name() { + return core.name(); + } + + public Class type() { + return core.type(); + } + + public String namespace() { + return core.namespace(); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/bind/v2/model/impl/DummyPropertyInfo.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,35 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.xml.internal.bind.v2.model.impl; + +/** + * {@link PropertyInfo} that allows to add additional elements to the collection. + * + * @author Martin Grebac + */ +public interface DummyPropertyInfo<T, C, F, M> { + void addType(PropertyInfoImpl<T, C, F, M> info); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/bind/v2/runtime/AttributeAccessor.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,35 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.xml.internal.bind.v2.runtime; + +/** + * + * @author snajper + */ +public interface AttributeAccessor<BeanT> { + + public boolean isNilIncluded(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/bind/v2/runtime/output/StAXExStreamWriterOutput.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,59 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.xml.internal.bind.v2.runtime.output; + +import javax.xml.stream.XMLStreamException; + +import com.sun.xml.internal.bind.v2.runtime.unmarshaller.Base64Data; + +import com.sun.xml.internal.org.jvnet.staxex.XMLStreamWriterEx; + +/** + * {@link XmlOutput} for {@link XMLStreamWriterEx}. + * + * @author Paul Sandoz. + */ +public final class StAXExStreamWriterOutput extends XMLStreamWriterOutput { + private final XMLStreamWriterEx out; + + public StAXExStreamWriterOutput(XMLStreamWriterEx out) { + super(out); + this.out = out; + } + + public void text(Pcdata value, boolean needsSeparatingWhitespace) throws XMLStreamException { + if(needsSeparatingWhitespace) { + out.writeCharacters(" "); + } + + if (!(value instanceof Base64Data)) { + out.writeCharacters(value.toString()); + } else { + Base64Data v = (Base64Data)value; + out.writeBinary(v.getDataHandler()); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/bind/v2/runtime/unmarshaller/StAXExConnector.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,72 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.xml.internal.bind.v2.runtime.unmarshaller; + +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import com.sun.xml.internal.org.jvnet.staxex.XMLStreamReaderEx; +import org.xml.sax.SAXException; + +/** + * Reads XML from StAX {@link XMLStreamReader} and + * feeds events to {@link XmlVisitor}. + * + * @author Ryan.Shoemaker@Sun.COM + * @author Kohsuke Kawaguchi + * @version JAXB 2.0 + */ +final class StAXExConnector extends StAXStreamConnector { + + // StAX event source + private final XMLStreamReaderEx in; + + public StAXExConnector(XMLStreamReaderEx in, XmlVisitor visitor) { + super(in,visitor); + this.in = in; + } + + @Override + protected void handleCharacters() throws XMLStreamException, SAXException { + if( predictor.expectText() ) { + CharSequence pcdata = in.getPCDATA(); + if(pcdata instanceof com.sun.xml.internal.org.jvnet.staxex.Base64Data) { + com.sun.xml.internal.org.jvnet.staxex.Base64Data bd = (com.sun.xml.internal.org.jvnet.staxex.Base64Data) pcdata; + Base64Data binary = new Base64Data(); + if(!bd.hasData()) + binary.set(bd.getDataHandler()); + else + binary.set( bd.get(), bd.getDataLen(), bd.getMimeType() ); + // we make an assumption here that the binary data shows up on its own + // not adjacent to other text. So it's OK to fire it off right now. + visitor.text(binary); + textReported = true; + } else { + buffer.append(pcdata); + } + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/bind/v2/util/StackRecorder.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,33 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.xml.internal.bind.v2.util; + +/** + * Created to record the caller stack trace in logging. + * + * @author Kohsuke Kawaguchi + */ +public class StackRecorder extends Throwable { +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/org/jvnet/mimepull/Chunk.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,50 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.xml.internal.org.jvnet.mimepull; + +import java.nio.ByteBuffer; + +/** + * @author Kohsuke Kawaguchi + */ +final class Chunk { + volatile Chunk next; + volatile Data data; + + public Chunk(Data data) { + this.data = data; + } + + /** + * Creates a new chunk and adds to linked list. + * + * @param dataHead of the linked list + * @param buf MIME part partial data + * @return created chunk + */ + public Chunk createNext(DataHead dataHead, ByteBuffer buf) { + return next = new Chunk(data.createNext(dataHead, buf)); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/org/jvnet/mimepull/ChunkInputStream.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,94 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.xml.internal.org.jvnet.mimepull; + +import java.io.InputStream; +import java.io.IOException; + +/** + * Constructs a InputStream from a linked list of {@link Chunk}s. + * + * @author Kohsuke Kawaguchi + * @author Jitendra Kotamraju + */ +final class ChunkInputStream extends InputStream { + Chunk current; + int offset; + int len; + final MIMEMessage msg; + final MIMEPart part; + byte[] buf; + + public ChunkInputStream(MIMEMessage msg, MIMEPart part, Chunk startPos) { + this.current = startPos; + len = current.data.size(); + buf = current.data.read(); + this.msg = msg; + this.part = part; + } + + @Override + public int read(byte b[], int off, int sz) throws IOException { + if(!fetch()) return -1; + + sz = Math.min(sz, len-offset); + System.arraycopy(buf,offset,b,off,sz); + return sz; + } + + public int read() throws IOException { + if(!fetch()) return -1; + return (buf[offset++] & 0xff); + } + + /** + * Gets to the next chunk if we are done with the current one. + * @return + */ + private boolean fetch() { + if (current == null) { + throw new IllegalStateException("Stream already closed"); + } + while(offset==len) { + while(!part.parsed && current.next == null) { + msg.makeProgress(); + } + current = current.next; + + if (current == null) { + return false; + } + this.offset = 0; + this.buf = current.data.read(); + this.len = current.data.size(); + } + return true; + } + + public void close() throws IOException { + super.close(); + current = null; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/org/jvnet/mimepull/Data.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,70 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.xml.internal.org.jvnet.mimepull; + +import java.nio.ByteBuffer; + +/** + * @author Kohsuke Kawaguchi + * @author Jitendra Kotamraju + */ +interface Data { + + /** + * size of the chunk given by the parser + * + * @return size of the chunk + */ + int size(); + + /** + * TODO: should the return type be ByteBuffer ?? + * Return part's partial data. The data is read only. + * + * @return a byte array which contains {#size()} bytes. The returned + * array may be larger than {#size()} bytes and contains data + * from offset 0. + */ + byte[] read(); + + /** + * Write this partial data to a file + * + * @param file to which the data needs to be written + * @return file pointer before the write operation(at which the data is + * written from) + */ + long writeTo(DataFile file); + + /** + * Factory method to create a Data. The implementation could + * be file based one or memory based one. + * + * @param dataHead start of the linked list of data objects + * @param buf contains partial content for a part + * @return Data + */ + Data createNext(DataHead dataHead, ByteBuffer buf); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/org/jvnet/mimepull/DataFile.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,83 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.xml.internal.org.jvnet.mimepull; + +import java.io.*; + +/** + * Use {@link RandomAccessFile} for concurrent access of read + * and write partial part's content. + * + * @author Kohsuke Kawaguchi + * @author Jitendra Kotamraju + */ +final class DataFile { + private WeakDataFile weak; + private long writePointer; + + DataFile(File file) { + writePointer=0; + weak = new WeakDataFile(this, file); + } + + /** + * + */ + void close() { + weak.close(); + } + + /** + * Read data from the given file pointer position. + * + * @param pointer read position + * @param buf that needs to be filled + * @param offset the start offset of the data. + * @param length of data that needs to be read + */ + synchronized void read(long pointer, byte[] buf, int offset, int length ) { + weak.read(pointer, buf, offset, length); + } + + void renameTo(File f) { + weak.renameTo(f); + } + + /** + * Write data to the file + * + * @param data that needs to written to a file + * @param offset start offset in the data + * @param length no bytes to write + * @return file pointer before the write operation(or at which the + * data is written) + */ + synchronized long writeTo(byte[] data, int offset, int length) { + long temp = writePointer; + writePointer = weak.writeTo(writePointer, data, offset, length); + return temp; + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/org/jvnet/mimepull/DataHead.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,258 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.xml.internal.org.jvnet.mimepull; + +import java.io.*; +import java.nio.ByteBuffer; + +/** + * Represents an attachment part in a MIME message. MIME message parsing is done + * lazily using a pull parser, so the part may not have all the data. {@link #read} + * and {@link #readOnce} may trigger the actual parsing the message. In fact, + * parsing of an attachment part may be triggered by calling {@link #read} methods + * on some other attachemnt parts. All this happens behind the scenes so the + * application developer need not worry about these details. + * + * @author Jitendra Kotamraju + */ +final class DataHead { + + /** + * Linked list to keep the part's content + */ + volatile Chunk head, tail; + + /** + * If the part is stored in a file, non-null. + */ + DataFile dataFile; + + private final MIMEPart part; + + boolean readOnce; + volatile long inMemory; + + /** + * Used only for debugging. This records where readOnce() is called. + */ + private Throwable consumedAt; + + DataHead(MIMEPart part) { + this.part = part; + } + + void addBody(ByteBuffer buf) { + synchronized(this) { + inMemory += buf.limit(); + } + if (tail != null) { + tail = tail.createNext(this, buf); + } else { + head = tail = new Chunk(new MemoryData(buf, part.msg.config)); + } + } + + void doneParsing() { + } + + void moveTo(File f) { + if (dataFile != null) { + dataFile.renameTo(f); + } else { + try { + OutputStream os = new FileOutputStream(f); + InputStream in = readOnce(); + byte[] buf = new byte[8192]; + int len; + while((len=in.read(buf)) != -1) { + os.write(buf, 0, len); + } + os.close(); + } catch(IOException ioe) { + throw new MIMEParsingException(ioe); + } + } + } + + void close() { + if (dataFile != null) { + head = tail = null; + dataFile.close(); + } + } + + + /** + * Can get the attachment part's content multiple times. That means + * the full content needs to be there in memory or on the file system. + * Calling this method would trigger parsing for the part's data. So + * do not call this unless it is required(otherwise, just wrap MIMEPart + * into a object that returns InputStream for e.g DataHandler) + * + * @return data for the part's content + */ + public InputStream read() { + if (readOnce) { + throw new IllegalStateException("readOnce() is called before, read() cannot be called later."); + } + + // Trigger parsing for the part + while(tail == null) { + if (!part.msg.makeProgress()) { + throw new IllegalStateException("No such MIME Part: "+part); + } + } + + if (head == null) { + throw new IllegalStateException("Already read. Probably readOnce() is called before."); + } + return new ReadMultiStream(); + } + + /** + * Used for an assertion. Returns true when readOnce() is not already called. + * or otherwise throw an exception. + * + * <p> + * Calling this method also marks the stream as 'consumed' + * + * @return true if readOnce() is not called before + */ + private boolean unconsumed() { + if (consumedAt != null) { + AssertionError error = new AssertionError("readOnce() is already called before. See the nested exception from where it's called."); + error.initCause(consumedAt); + throw error; + } + consumedAt = new Exception().fillInStackTrace(); + return true; + } + + /** + * Can get the attachment part's content only once. The content + * will be lost after the method. Content data is not be stored + * on the file system or is not kept in the memory for the + * following case: + * - Attachement parts contents are accessed sequentially + * + * In general, take advantage of this when the data is used only + * once. + * + * @return data for the part's content + */ + public InputStream readOnce() { + assert unconsumed(); + if (readOnce) { + throw new IllegalStateException("readOnce() is called before. It can only be called once."); + } + readOnce = true; + // Trigger parsing for the part + while(tail == null) { + if (!part.msg.makeProgress() && tail == null) { + throw new IllegalStateException("No such Part: "+part); + } + } + InputStream in = new ReadOnceStream(); + head = null; + return in; + } + + class ReadMultiStream extends InputStream { + Chunk current; + int offset; + int len; + byte[] buf; + + public ReadMultiStream() { + this.current = head; + len = current.data.size(); + buf = current.data.read(); + } + + @Override + public int read(byte b[], int off, int sz) throws IOException { + if(!fetch()) return -1; + + sz = Math.min(sz, len-offset); + System.arraycopy(buf,offset,b,off,sz); + offset += sz; + return sz; + } + + public int read() throws IOException { + if (!fetch()) { + return -1; + } + return (buf[offset++] & 0xff); + } + + void adjustInMemoryUsage() { + // Nothing to do in this case. + } + + /** + * Gets to the next chunk if we are done with the current one. + * @return + */ + private boolean fetch() { + if (current == null) { + throw new IllegalStateException("Stream already closed"); + } + while(offset==len) { + while(!part.parsed && current.next == null) { + part.msg.makeProgress(); + } + current = current.next; + + if (current == null) { + return false; + } + adjustInMemoryUsage(); + this.offset = 0; + this.buf = current.data.read(); + this.len = current.data.size(); + } + return true; + } + + public void close() throws IOException { + super.close(); + current = null; + } + } + + final class ReadOnceStream extends ReadMultiStream { + + @Override + void adjustInMemoryUsage() { + synchronized(DataHead.this) { + inMemory -= current.data.size(); // adjust current memory usage + } + } + + } + + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/org/jvnet/mimepull/FileData.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,73 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.xml.internal.org.jvnet.mimepull; + +import java.nio.ByteBuffer; + +/** + * Keeps the Part's partial content data in a file. + * + * @author Kohsuke Kawaguchi + * @author Jitendra Kotamraju + */ +final class FileData implements Data { + private final DataFile file; + private final long pointer; // read position + private final int length; + + FileData(DataFile file, ByteBuffer buf) { + this(file, file.writeTo(buf.array(), 0, buf.limit()), buf.limit()); + } + + FileData(DataFile file, long pointer, int length) { + this.file = file; + this.pointer = pointer; + this.length = length; + } + + public byte[] read() { + byte[] buf = new byte[length]; + file.read(pointer, buf, 0, length); + return buf; + } + + /* + * This shouldn't be called + */ + public long writeTo(DataFile file) { + throw new IllegalStateException(); + } + + public int size() { + return length; + } + + /* + * Always create FileData + */ + public Data createNext(DataHead dataHead, ByteBuffer buf) { + return new FileData(file, buf); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/org/jvnet/mimepull/FinalArrayList.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,49 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.xml.internal.org.jvnet.mimepull; + +import java.util.ArrayList; +import java.util.Collection; + +/** + * {@link java.util.ArrayList} with the final keyword. + * + * <p> + * This gives HotSpot a better hint that all methods can be inlined. + * + * @author Kohsuke Kawaguchi + */ +final class FinalArrayList<T> extends ArrayList<T> { + public FinalArrayList(int initialCapacity) { + super(initialCapacity); + } + + public FinalArrayList() { + } + + public FinalArrayList(Collection<? extends T> ts) { + super(ts); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/org/jvnet/mimepull/Header.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,48 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.xml.internal.org.jvnet.mimepull; + +/** + * The Header class stores a name/value pair to represent headers. + * + * @author John Mani + */ + +public interface Header { + + /** + * Returns the name of this header. + * + * @return name of the header + */ + String getName(); + + /** + * Returns the value of this header. + * + * @return value of the header + */ + String getValue(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/org/jvnet/mimepull/InternetHeaders.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,238 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.xml.internal.org.jvnet.mimepull; + +import java.io.IOException; +import java.util.NoSuchElementException; +import java.util.List; + +/** + * InternetHeaders is a utility class that manages RFC822 style + * headers. Given an RFC822 format message stream, it reads lines + * until the blank line that indicates end of header. The input stream + * is positioned at the start of the body. The lines are stored + * within the object and can be extracted as either Strings or + * {@link Header} objects. <p> + * <p/> + * This class is mostly intended for service providers. MimeMessage + * and MimeBody use this class for holding their headers. <p> + * <p/> + * <hr> <strong>A note on RFC822 and MIME headers</strong><p> + * <p/> + * RFC822 and MIME header fields <strong>must</strong> contain only + * US-ASCII characters. If a header contains non US-ASCII characters, + * it must be encoded as per the rules in RFC 2047. The MimeUtility + * class provided in this package can be used to to achieve this. + * Callers of the <code>setHeader</code>, <code>addHeader</code>, and + * <code>addHeaderLine</code> methods are responsible for enforcing + * the MIME requirements for the specified headers. In addition, these + * header fields must be folded (wrapped) before being sent if they + * exceed the line length limitation for the transport (1000 bytes for + * SMTP). Received headers may have been folded. The application is + * responsible for folding and unfolding headers as appropriate. <p> + * + * @author John Mani + * @author Bill Shannon + */ +final class InternetHeaders { + + private final FinalArrayList<hdr> headers = new FinalArrayList<hdr>(); + + /** + * Read and parse the given RFC822 message stream till the + * blank line separating the header from the body. Store the + * header lines inside this InternetHeaders object. <p> + * <p/> + * Note that the header lines are added into this InternetHeaders + * object, so any existing headers in this object will not be + * affected. + * + * @param lis RFC822 input stream + */ + InternetHeaders(MIMEParser.LineInputStream lis) { + // Read header lines until a blank line. It is valid + // to have BodyParts with no header lines. + String line; + String prevline = null; // the previous header line, as a string + // a buffer to accumulate the header in, when we know it's needed + StringBuffer lineBuffer = new StringBuffer(); + + try { + //while ((line = lis.readLine()) != null) { + do { + line = lis.readLine(); + if (line != null && + (line.startsWith(" ") || line.startsWith("\t"))) { + // continuation of header + if (prevline != null) { + lineBuffer.append(prevline); + prevline = null; + } + lineBuffer.append("\r\n"); + lineBuffer.append(line); + } else { + // new header + if (prevline != null) + addHeaderLine(prevline); + else if (lineBuffer.length() > 0) { + // store previous header first + addHeaderLine(lineBuffer.toString()); + lineBuffer.setLength(0); + } + prevline = line; + } + } while (line != null && line.length() > 0); + } catch (IOException ioex) { + throw new MIMEParsingException("Error in input stream", ioex); + } + } + + /** + * Return all the values for the specified header. The + * values are String objects. Returns <code>null</code> + * if no headers with the specified name exist. + * + * @param name header name + * @return array of header values, or null if none + */ + List<String> getHeader(String name) { + // XXX - should we just step through in index order? + FinalArrayList<String> v = new FinalArrayList<String>(); // accumulate return values + + int len = headers.size(); + for( int i=0; i<len; i++ ) { + hdr h = (hdr) headers.get(i); + if (name.equalsIgnoreCase(h.name)) { + v.add(h.getValue()); + } + } + return (v.size() == 0) ? null : v; + } + + /** + * Return all the headers as an Enumeration of + * {@link Header} objects. + * + * @return Header objects + */ + FinalArrayList<? extends Header> getAllHeaders() { + return headers; // conceptually it should be read-only, but for performance reason I'm not wrapping it here + } + + /** + * Add an RFC822 header line to the header store. + * If the line starts with a space or tab (a continuation line), + * add it to the last header line in the list. <p> + * <p/> + * Note that RFC822 headers can only contain US-ASCII characters + * + * @param line raw RFC822 header line + */ + void addHeaderLine(String line) { + try { + char c = line.charAt(0); + if (c == ' ' || c == '\t') { + hdr h = (hdr) headers.get(headers.size() - 1); + h.line += "\r\n" + line; + } else + headers.add(new hdr(line)); + } catch (StringIndexOutOfBoundsException e) { + // line is empty, ignore it + return; + } catch (NoSuchElementException e) { + // XXX - vector is empty? + } + } + +} + +/* + * A private utility class to represent an individual header. + */ + +class hdr implements Header { + + String name; // the canonicalized (trimmed) name of this header + // XXX - should name be stored in lower case? + String line; // the entire RFC822 header "line" + + /* + * Constructor that takes a line and splits out + * the header name. + */ + hdr(String l) { + int i = l.indexOf(':'); + if (i < 0) { + // should never happen + name = l.trim(); + } else { + name = l.substring(0, i).trim(); + } + line = l; + } + + /* + * Constructor that takes a header name and value. + */ + hdr(String n, String v) { + name = n; + line = n + ": " + v; + } + + /* + * Return the "name" part of the header line. + */ + public String getName() { + return name; + } + + /* + * Return the "value" part of the header line. + */ + public String getValue() { + int i = line.indexOf(':'); + if (i < 0) + return line; + + int j; + if (name.equalsIgnoreCase("Content-Description")) { + // Content-Description should retain the folded whitespace after header unfolding - + // rf. RFC2822 section 2.2.3, rf. RFC2822 section 3.2.3 + for (j = i + 1; j < line.length(); j++) { + char c = line.charAt(j); + if (!(/*c == ' ' ||*/c == '\t' || c == '\r' || c == '\n')) + break; + } + } else { + // skip whitespace after ':' + for (j = i + 1; j < line.length(); j++) { + char c = line.charAt(j); + if (!(c == ' ' || c == '\t' || c == '\r' || c == '\n')) + break; + } + } + return line.substring(j); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/org/jvnet/mimepull/MIMEConfig.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,147 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.xml.internal.org.jvnet.mimepull; + +import java.io.File; +import java.io.IOException; + +/** + * Configuration for MIME message parsing and storing. + * + * @author Jitendra Kotamraju + */ +public class MIMEConfig { + + private static final int DEFAULT_CHUNK_SIZE = 8192; + private static final long DEFAULT_MEMORY_THRESHOLD = 1048576L; + private static final String DEFAULT_FILE_PREFIX = "MIME"; + + // Parses the entire message eagerly + boolean parseEagerly; + + // Approximate Chunk size + int chunkSize; + + // Maximum in-memory data per attachment + long memoryThreshold; + + // Do not store to disk + boolean onlyMemory; + + // temp Dir to store large files + File tempDir; + String prefix; + String suffix; + + + private MIMEConfig(boolean parseEagerly, int chunkSize, + long inMemoryThreshold, String dir, String prefix, String suffix) { + this.parseEagerly = parseEagerly; + this.chunkSize = chunkSize; + this.memoryThreshold = inMemoryThreshold; + this.prefix = prefix; + this.suffix = suffix; + setDir(dir); + } + + public MIMEConfig() { + this(false, DEFAULT_CHUNK_SIZE, DEFAULT_MEMORY_THRESHOLD, null, + DEFAULT_FILE_PREFIX, null); + } + + boolean isParseEagerly() { + return parseEagerly; + } + + public void setParseEagerly(boolean parseEagerly) { + this.parseEagerly = parseEagerly; + } + + int getChunkSize() { + return chunkSize; + } + + void setChunkSize(int chunkSize) { + this.chunkSize = chunkSize; + } + + long getMemoryThreshold() { + return memoryThreshold; + } + + /** + * If the attachment is greater than the threshold, it is + * written to the disk. + * + * @param memoryThreshold no of bytes per attachment + * if -1, then the whole attachment is kept in memory + */ + public void setMemoryThreshold(long memoryThreshold) { + this.memoryThreshold = memoryThreshold; + } + + boolean isOnlyMemory() { + return memoryThreshold == -1L; + } + + File getTempDir() { + return tempDir; + } + + String getTempFilePrefix() { + return prefix; + } + + String getTempFileSuffix() { + return suffix; + } + + /** + * @param dir + */ + public void setDir(String dir) { + if (tempDir == null && dir != null && !dir.equals("")) { + tempDir = new File(dir); + } + } + + /** + * Validates if it can create temporary files. Otherwise, it stores + * attachment contents in memory. + */ + public void validate() { + if (!isOnlyMemory()) { + try { + File tempFile = (tempDir == null) + ? File.createTempFile(prefix, suffix) + : File.createTempFile(prefix, suffix, tempDir); + tempFile.delete(); + } catch(Exception ioe) { + memoryThreshold = -1L; // whole attachment will be in-memory + } + } + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/org/jvnet/mimepull/MIMEEvent.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,116 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.xml.internal.org.jvnet.mimepull; + +import java.nio.ByteBuffer; + +/** + * @author Jitendra Kotamraju + */ +abstract class MIMEEvent { + + enum EVENT_TYPE {START_MESSAGE, START_PART, HEADERS, CONTENT, END_PART, END_MESSAGE} + + /** + * Returns a event for parser's current cursor location in the MIME message. + * + * <p> + * {@link EVENT_TYPE#START_MESSAGE} and {@link EVENT_TYPE#START_MESSAGE} events + * are generated only once. + * + * <p> + * {@link EVENT_TYPE#START_PART}, {@link EVENT_TYPE#END_PART}, {@link EVENT_TYPE#HEADERS} + * events are generated only once for each attachment part. + * + * <p> + * {@link EVENT_TYPE#CONTENT} event may be generated more than once for an attachment + * part. + * + * @return event type + */ + abstract EVENT_TYPE getEventType(); + + static final StartMessage START_MESSAGE = new StartMessage(); + static final StartPart START_PART = new StartPart(); + static final EndPart END_PART = new EndPart(); + static final EndMessage END_MESSAGE = new EndMessage(); + + static final class StartMessage extends MIMEEvent { + EVENT_TYPE getEventType() { + return EVENT_TYPE.START_MESSAGE; + } + } + + static final class StartPart extends MIMEEvent { + EVENT_TYPE getEventType() { + return EVENT_TYPE.START_PART; + } + } + + static final class EndPart extends MIMEEvent { + EVENT_TYPE getEventType () { + return EVENT_TYPE.END_PART; + } + } + + static final class Headers extends MIMEEvent { + InternetHeaders ih; + + Headers(InternetHeaders ih) { + this.ih = ih; + } + + EVENT_TYPE getEventType() { + return EVENT_TYPE.HEADERS; + } + + InternetHeaders getHeaders() { + return ih; + } + } + + static final class Content extends MIMEEvent { + private final ByteBuffer buf; + + Content(ByteBuffer buf) { + this.buf = buf; + } + + EVENT_TYPE getEventType() { + return EVENT_TYPE.CONTENT; + } + + ByteBuffer getData() { + return buf; + } + } + + static final class EndMessage extends MIMEEvent { + EVENT_TYPE getEventType() { + return EVENT_TYPE.END_MESSAGE; + } + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/org/jvnet/mimepull/MIMEMessage.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,248 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.xml.internal.org.jvnet.mimepull; + +import java.io.IOException; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; +import java.nio.ByteBuffer; +import java.util.*; +import java.util.logging.Logger; + +/** + * Represents MIME message. MIME message parsing is done lazily using a + * pull parser. + * + * @author Jitendra Kotamraju + */ +public class MIMEMessage { + private static final Logger LOGGER = Logger.getLogger(MIMEMessage.class.getName()); + + MIMEConfig config; + + private final InputStream in; + private final List<MIMEPart> partsList; + private final Map<String, MIMEPart> partsMap; + private final Iterator<MIMEEvent> it; + private boolean parsed; // true when entire message is parsed + private MIMEPart currentPart; + private int currentIndex; + + /** + * @see MIMEMessage(InputStream, String, MIMEConfig) + */ + public MIMEMessage(InputStream in, String boundary) { + this(in, boundary, new MIMEConfig()); + } + + /** + * Creates a MIME message from the content's stream. The content stream + * is closed when EOF is reached. + * + * @param in MIME message stream + * @param boundary the separator for parts(pass it without --) + * @param config various configuration parameters + */ + public MIMEMessage(InputStream in, String boundary, MIMEConfig config) { + this.in = in; + this.config = config; + MIMEParser parser = new MIMEParser(in, boundary, config); + it = parser.iterator(); + + partsList = new ArrayList<MIMEPart>(); + partsMap = new HashMap<String, MIMEPart>(); + if (config.isParseEagerly()) { + parseAll(); + } + } + + /** + * Gets all the attachments by parsing the entire MIME message. Avoid + * this if possible since it is an expensive operation. + * + * @return list of attachments. + */ + public List<MIMEPart> getAttachments() { + if (!parsed) { + parseAll(); + } + return partsList; + } + + /** + * Creates nth attachment lazily. It doesn't validate + * if the message has so many attachments. To + * do the validation, the message needs to be parsed. + * The parsing of the message is done lazily and is done + * while reading the bytes of the part. + * + * @param index sequential order of the part. starts with zero. + * @return attachemnt part + */ + public MIMEPart getPart(int index) { + LOGGER.fine("index="+index); + MIMEPart part = (index < partsList.size()) ? partsList.get(index) : null; + if (parsed && part == null) { + throw new MIMEParsingException("There is no "+index+" attachment part "); + } + if (part == null) { + // Parsing will done lazily and will be driven by reading the part + part = new MIMEPart(this); + partsList.add(index, part); + } + LOGGER.fine("Got attachment at index="+index+" attachment="+part); + return part; + } + + /** + * Creates a lazy attachment for a given Content-ID. It doesn't validate + * if the message contains an attachment with the given Content-ID. To + * do the validation, the message needs to be parsed. The parsing of the + * message is done lazily and is done while reading the bytes of the part. + * + * @param contentId Content-ID of the part, expects Content-ID without <, > + * @return attachemnt part + */ + public MIMEPart getPart(String contentId) { + LOGGER.fine("Content-ID="+contentId); + MIMEPart part = getDecodedCidPart(contentId); + if (parsed && part == null) { + throw new MIMEParsingException("There is no attachment part with Content-ID = "+contentId); + } + if (part == null) { + // Parsing is done lazily and is driven by reading the part + part = new MIMEPart(this, contentId); + partsMap.put(contentId, part); + } + LOGGER.fine("Got attachment for Content-ID="+contentId+" attachment="+part); + return part; + } + + // this is required for Indigo interop, it writes content-id without escaping + private MIMEPart getDecodedCidPart(String cid) { + MIMEPart part = partsMap.get(cid); + if (part == null) { + if (cid.indexOf('%') != -1) { + try { + String tempCid = URLDecoder.decode(cid, "utf-8"); + part = partsMap.get(tempCid); + } catch(UnsupportedEncodingException ue) { + // Ignore it + } + } + } + return part; + } + + + /** + * Parses the whole MIME message eagerly + */ + public void parseAll() { + while(makeProgress()) { + // Nothing to do + } + } + + + /** + * Parses the MIME message in a pull fashion. + * + * @return + * false if the parsing is completed. + */ + public synchronized boolean makeProgress() { + if (!it.hasNext()) { + return false; + } + + MIMEEvent event = it.next(); + + switch(event.getEventType()) { + case START_MESSAGE : + LOGGER.fine("MIMEEvent="+MIMEEvent.EVENT_TYPE.START_MESSAGE); + break; + + case START_PART : + LOGGER.fine("MIMEEvent="+MIMEEvent.EVENT_TYPE.START_PART); + break; + + case HEADERS : + LOGGER.fine("MIMEEvent="+MIMEEvent.EVENT_TYPE.HEADERS); + MIMEEvent.Headers headers = (MIMEEvent.Headers)event; + InternetHeaders ih = headers.getHeaders(); + List<String> cids = ih.getHeader("content-id"); + String cid = (cids != null) ? cids.get(0) : currentIndex+""; + if (cid.length() > 2 && cid.charAt(0)=='<') { + cid = cid.substring(1,cid.length()-1); + } + MIMEPart listPart = (currentIndex < partsList.size()) ? partsList.get(currentIndex) : null; + MIMEPart mapPart = getDecodedCidPart(cid); + if (listPart == null && mapPart == null) { + currentPart = getPart(cid); + partsList.add(currentIndex, currentPart); + } else if (listPart == null) { + currentPart = mapPart; + partsList.add(currentIndex, mapPart); + } else if (mapPart == null) { + currentPart = listPart; + currentPart.setContentId(cid); + partsMap.put(cid, currentPart); + } else if (listPart != mapPart) { + throw new MIMEParsingException("Created two different attachments using Content-ID and index"); + } + currentPart.setHeaders(ih); + break; + + case CONTENT : + LOGGER.finer("MIMEEvent="+MIMEEvent.EVENT_TYPE.CONTENT); + MIMEEvent.Content content = (MIMEEvent.Content)event; + ByteBuffer buf = content.getData(); + currentPart.addBody(buf); + break; + + case END_PART : + LOGGER.fine("MIMEEvent="+MIMEEvent.EVENT_TYPE.END_PART); + currentPart.doneParsing(); + ++currentIndex; + break; + + case END_MESSAGE : + LOGGER.fine("MIMEEvent="+MIMEEvent.EVENT_TYPE.END_MESSAGE); + parsed = true; + try { + in.close(); + } catch(IOException ioe) { + throw new MIMEParsingException(ioe); + } + break; + + default : + throw new MIMEParsingException("Unknown Parser state = "+event.getEventType()); + } + return true; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/org/jvnet/mimepull/MIMEParser.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,500 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.xml.internal.org.jvnet.mimepull; + +import java.io.InputStream; +import java.io.IOException; +import java.util.*; +import java.util.logging.Logger; +import java.nio.ByteBuffer; + +/** + * Pull parser for the MIME messages. Applications can use pull API to continue + * the parsing MIME messages lazily. + * + * <pre> + * for e.g.: + * <p> + * + * MIMEParser parser = ... + * Iterator<MIMEEvent> it = parser.iterator(); + * while(it.hasNext()) { + * MIMEEvent event = it.next(); + * ... + * } + * </pre> + * + * @author Jitendra Kotamraju + */ +class MIMEParser implements Iterable<MIMEEvent> { + + private static final Logger LOGGER = Logger.getLogger(MIMEParser.class.getName()); + + // Actually, the grammar doesn't support whitespace characters + // after boundary. But the mail implementation checks for it. + // We will only check for these many whitespace characters after boundary + private static final int NO_LWSP = 1000; + private enum STATE {START_MESSAGE, SKIP_PREAMBLE, START_PART, HEADERS, BODY, END_PART, END_MESSAGE} + private STATE state = STATE.START_MESSAGE; + + private final InputStream in; + private final byte[] bndbytes; + private final int bl; + private final MIMEConfig config; + private final int[] bcs = new int[128]; // BnM algo: Bad Character Shift table + private final int[] gss; // BnM algo : Good Suffix Shift table + + /** + * Have we parsed the data from our InputStream yet? + */ + private boolean parsed; + + /* + * Read and process body partsList until we see the + * terminating boundary line (or EOF). + */ + private boolean done = false; + + private boolean eof; + private final int capacity; + private byte[] buf; + private int len; + private boolean bol; // beginning of the line + + /* + * Parses the MIME content. At the EOF, it also closes input stream + */ + MIMEParser(InputStream in, String boundary, MIMEConfig config) { + this.in = in; + this.bndbytes = getBytes("--"+boundary); + bl = bndbytes.length; + this.config = config; + gss = new int[bl]; + compileBoundaryPattern(); + + // \r\n + boundary + "--\r\n" + lots of LWSP + capacity = config.chunkSize+2+bl+4+NO_LWSP; + createBuf(capacity); + } + + /** + * Returns iterator for the parsing events. Use the iterator to advance + * the parsing. + * + * @return iterator for parsing events + */ + public Iterator<MIMEEvent> iterator() { + return new MIMEEventIterator(); + } + + class MIMEEventIterator implements Iterator<MIMEEvent> { + + public boolean hasNext() { + return !parsed; + } + + public MIMEEvent next() { + switch(state) { + case START_MESSAGE : + LOGGER.finer("MIMEParser state="+STATE.START_MESSAGE); + state = STATE.SKIP_PREAMBLE; + return MIMEEvent.START_MESSAGE; + + case SKIP_PREAMBLE : + LOGGER.finer("MIMEParser state="+STATE.SKIP_PREAMBLE); + skipPreamble(); + // fall through + case START_PART : + LOGGER.finer("MIMEParser state="+STATE.START_PART); + state = STATE.HEADERS; + return MIMEEvent.START_PART; + + case HEADERS : + LOGGER.finer("MIMEParser state="+STATE.HEADERS); + InternetHeaders ih = readHeaders(); + state = STATE.BODY; + bol = true; + return new MIMEEvent.Headers(ih); + + case BODY : + LOGGER.finer("MIMEParser state="+STATE.BODY); + ByteBuffer buf = readBody(); + bol = false; + return new MIMEEvent.Content(buf); + + case END_PART : + LOGGER.finer("MIMEParser state="+STATE.END_PART); + if (done) { + state = STATE.END_MESSAGE; + } else { + state = STATE.START_PART; + } + return MIMEEvent.END_PART; + + case END_MESSAGE : + LOGGER.finer("MIMEParser state="+STATE.END_MESSAGE); + parsed = true; + return MIMEEvent.END_MESSAGE; + + default : + throw new MIMEParsingException("Unknown Parser state = "+state); + } + } + + public void remove() { + throw new UnsupportedOperationException(); + } + } + + /** + * Collects the headers for the current part by parsing mesage stream. + * + * @return headers for the current part + */ + private InternetHeaders readHeaders() { + if (!eof) { + fillBuf(); + } + return new InternetHeaders(new LineInputStream()); + } + + /** + * Reads and saves the part of the current attachment part's content. + * At the end of this method, buf should have the remaining data + * at index 0. + * + * @return a chunk of the part's content + * + */ + private ByteBuffer readBody() { + if (!eof) { + fillBuf(); + } + int start = match(buf, 0, len); // matches boundary + if (start == -1) { + // No boundary is found + assert eof || len >= config.chunkSize; + int chunkSize = eof ? len : config.chunkSize; + if (eof) { + // Should we throw exception as there is no closing boundary ? But some impl + // like SAAJ do not throw excpetion. + // throw new MIMEParsingException("Reached EOF, but there is no closing MIME boundary."); + done = true; + state = STATE.END_PART; + } + return adjustBuf(chunkSize, len-chunkSize); + } + // Found boundary. + // Is it at the start of a line ? + int chunkLen = start; + if (bol && start == 0) { + // nothing to do + } else if (start > 0 && (buf[start-1] == '\n' || buf[start-1] =='\r')) { + --chunkLen; + if (buf[start-1] == '\n' && start >1 && buf[start-2] == '\r') { + --chunkLen; + } + } else { + return adjustBuf(start+1, len-start-1); // boundary is not at beginning of a line + } + + if (start+bl+1 < len && buf[start+bl] == '-' && buf[start+bl+1] == '-') { + state = STATE.END_PART; + done = true; + return adjustBuf(chunkLen, 0); + } + + // Consider all the whitespace in boundary+whitespace+"\r\n" + int lwsp = 0; + for(int i=start+bl; i < len && (buf[i] == ' ' || buf[i] == '\t'); i++) { + ++lwsp; + } + + // Check for \n or \r\n in boundary+whitespace+"\n" or boundary+whitespace+"\r\n" + if (start+bl+lwsp < len && buf[start+bl+lwsp] == '\n') { + state = STATE.END_PART; + return adjustBuf(chunkLen, len-start-bl-lwsp-1); + } else if (start+bl+lwsp+1 < len && buf[start+bl+lwsp] == '\r' && buf[start+bl+lwsp+1] == '\n') { + state = STATE.END_PART; + return adjustBuf(chunkLen, len-start-bl-lwsp-2); + } else if (start+bl+lwsp+1 < len) { + return adjustBuf(chunkLen+1, len-chunkLen-1); // boundary string in a part data + } else if (eof) { + done = true; + state = STATE.END_PART; + return adjustBuf(chunkLen, 0); + // Should we throw exception as there is no closing boundary ? But some impl + // like SAAJ do not throw excpetion. + //throw new MIMEParsingException("Reached EOF, but there is no closing MIME boundary."); + } + + // Some more data needed to determine if it is indeed a proper boundary + return adjustBuf(chunkLen, len-chunkLen); + } + + /** + * Returns a chunk from the original buffer. A new buffer is + * created with the remaining bytes. + * + * @param chunkSize create a chunk with these many bytes + * @param remaining bytes from the end of the buffer that need to be copied to + * the beginning of the new buffer + * @return chunk + */ + private ByteBuffer adjustBuf(int chunkSize, int remaining) { + assert buf != null; + assert chunkSize >= 0; + assert remaining >= 0; + + byte[] temp = buf; + // create a new buf and adjust it without this chunk + createBuf(remaining); + System.arraycopy(temp, len-remaining, buf, 0, remaining); + len = remaining; + + return ByteBuffer.wrap(temp, 0, chunkSize); + } + + private void createBuf(int min) { + buf = new byte[min < capacity ? capacity : min]; + } + + /** + * Skips the preamble to find the first attachment part + */ + private void skipPreamble() { + + while(true) { + if (!eof) { + fillBuf(); + } + int start = match(buf, 0, len); // matches boundary + if (start == -1) { + // No boundary is found + if (eof) { + throw new MIMEParsingException("Missing start boundary"); + } else { + adjustBuf(len-bl+1, bl-1); + continue; + } + } + + if (start > config.chunkSize) { + adjustBuf(start, len-start); + continue; + } + // Consider all the whitespace boundary+whitespace+"\r\n" + int lwsp = 0; + for(int i=start+bl; i < len && (buf[i] == ' ' || buf[i] == '\t'); i++) { + ++lwsp; + } + // Check for \n or \r\n + if (start+bl+lwsp < len && (buf[start+bl+lwsp] == '\n' || buf[start+bl+lwsp] == '\r') ) { + if (buf[start+bl+lwsp] == '\n') { + adjustBuf(start+bl+lwsp+1, len-start-bl-lwsp-1); + break; + } else if (start+bl+lwsp+1 < len && buf[start+bl+lwsp+1] == '\n') { + adjustBuf(start+bl+lwsp+2, len-start-bl-lwsp-2); + break; + } + } + adjustBuf(start+1, len-start-1); + } + LOGGER.fine("Skipped the preamble. buffer len="+len); + } + + private static byte[] getBytes(String s) { + char [] chars= s.toCharArray(); + int size = chars.length; + byte[] bytes = new byte[size]; + + for (int i = 0; i < size;) + bytes[i] = (byte) chars[i++]; + return bytes; + } + + /** + * Boyer-Moore search method. Copied from java.util.regex.Pattern.java + * + * Pre calculates arrays needed to generate the bad character + * shift and the good suffix shift. Only the last seven bits + * are used to see if chars match; This keeps the tables small + * and covers the heavily used ASCII range, but occasionally + * results in an aliased match for the bad character shift. + */ + private void compileBoundaryPattern() { + int i, j; + + // Precalculate part of the bad character shift + // It is a table for where in the pattern each + // lower 7-bit value occurs + for (i = 0; i < bndbytes.length; i++) { + bcs[bndbytes[i]&0x7F] = i + 1; + } + + // Precalculate the good suffix shift + // i is the shift amount being considered +NEXT: for (i = bndbytes.length; i > 0; i--) { + // j is the beginning index of suffix being considered + for (j = bndbytes.length - 1; j >= i; j--) { + // Testing for good suffix + if (bndbytes[j] == bndbytes[j-i]) { + // src[j..len] is a good suffix + gss[j-1] = i; + } else { + // No match. The array has already been + // filled up with correct values before. + continue NEXT; + } + } + // This fills up the remaining of optoSft + // any suffix can not have larger shift amount + // then its sub-suffix. Why??? + while (j > 0) { + gss[--j] = i; + } + } + // Set the guard value because of unicode compression + gss[bndbytes.length -1] = 1; + } + + /** + * Finds the boundary in the given buffer using Boyer-Moore algo. + * Copied from java.util.regex.Pattern.java + * + * @param mybuf boundary to be searched in this mybuf + * @param off start index in mybuf + * @param len number of bytes in mybuf + * + * @return -1 if there is no match or index where the match starts + */ + private int match(byte[] mybuf, int off, int len) { + int last = len - bndbytes.length; + + // Loop over all possible match positions in text +NEXT: while (off <= last) { + // Loop over pattern from right to left + for (int j = bndbytes.length - 1; j >= 0; j--) { + byte ch = mybuf[off+j]; + if (ch != bndbytes[j]) { + // Shift search to the right by the maximum of the + // bad character shift and the good suffix shift + off += Math.max(j + 1 - bcs[ch&0x7F], gss[j]); + continue NEXT; + } + } + // Entire pattern matched starting at off + return off; + } + return -1; + } + + /** + * Fills the remaining buf to the full capacity + */ + private void fillBuf() { + LOGGER.finer("Before fillBuf() buffer len="+len); + assert !eof; + while(len < buf.length) { + int read; + try { + read = in.read(buf, len, buf.length-len); + } catch(IOException ioe) { + throw new MIMEParsingException(ioe); + } + if (read == -1) { + eof = true; + try { + LOGGER.fine("Closing the input stream."); + in.close(); + } catch(IOException ioe) { + throw new MIMEParsingException(ioe); + } + break; + } else { + len += read; + } + } + LOGGER.finer("After fillBuf() buffer len="+len); + } + + private void doubleBuf() { + byte[] temp = new byte[2*len]; + System.arraycopy(buf, 0, temp, 0, len); + buf = temp; + if (!eof) { + fillBuf(); + } + } + + class LineInputStream { + private int offset; + + /* + * Read a line containing only ASCII characters from the input + * stream. A line is terminated by a CR or NL or CR-NL sequence. + * A common error is a CR-CR-NL sequence, which will also terminate + * a line. + * The line terminator is not returned as part of the returned + * String. Returns null if no data is available. <p> + * + * This class is similar to the deprecated + * <code>DataInputStream.readLine()</code> + */ + public String readLine() throws IOException { + + int hdrLen = 0; + int lwsp = 0; + while(offset+hdrLen < len) { + if (buf[offset+hdrLen] == '\n') { + lwsp = 1; + break; + } + if (offset+hdrLen+1 == len) { + doubleBuf(); + } + if (offset+hdrLen+1 >= len) { // No more data in the stream + assert eof; + return null; + } + if (buf[offset+hdrLen] == '\r' && buf[offset+hdrLen+1] == '\n') { + lwsp = 2; + break; + } + ++hdrLen; + } + if (hdrLen == 0) { + adjustBuf(offset+lwsp, len-offset-lwsp); + return null; + } + + String hdr = new String(buf, offset, hdrLen); + offset += hdrLen+lwsp; + return hdr; + } + + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/org/jvnet/mimepull/MIMEParsingException.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,87 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.xml.internal.org.jvnet.mimepull; + +/** + * @author Jitendra Kotamraju + */ + +/** + * The <code>MIMEParsingException</code> class is the base + * exception class for all MIME message parsing exceptions. + * + */ + +public class MIMEParsingException extends java.lang.RuntimeException { + + /** + * Constructs a new exception with <code>null</code> as its + * detail message. The cause is not initialized. + */ + public MIMEParsingException() { + super(); + } + + /** + * Constructs a new exception with the specified detail + * message. The cause is not initialized. + * + * @param message The detail message which is later + * retrieved using the getMessage method + */ + public MIMEParsingException(String message) { + super(message); + } + + /** + * Constructs a new exception with the specified detail + * message and cause. + * + * @param message The detail message which is later retrieved + * using the getMessage method + * @param cause The cause which is saved for the later + * retrieval throw by the getCause method + */ + public MIMEParsingException(String message, Throwable cause) { + super(message, cause); + } + + /** + * Constructs a new WebServiceException with the specified cause + * and a detail message of <tt>(cause==null ? null : + * cause.toString())</tt> (which typically contains the + * class and detail message of <tt>cause</tt>). + * + * @param cause The cause which is saved for the later + * retrieval throw by the getCause method. + * (A <tt>null</tt> value is permitted, and + * indicates that the cause is nonexistent or + * unknown.) + */ + public MIMEParsingException(Throwable cause) { + super(cause); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/org/jvnet/mimepull/MIMEPart.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,206 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.xml.internal.org.jvnet.mimepull; + +import java.io.File; +import java.io.InputStream; +import java.nio.ByteBuffer; +import java.util.List; + +/** + * Represents an attachment part in a MIME message. MIME message parsing is done + * lazily using a pull parser, so the part may not have all the data. {@link #read} + * and {@link #readOnce} may trigger the actual parsing the message. In fact, + * parsing of an attachment part may be triggered by calling {@link #read} methods + * on some other attachemnt parts. All this happens behind the scenes so the + * application developer need not worry about these details. + * + * @author Jitendra Kotamraju + */ +public class MIMEPart { + + private volatile InternetHeaders headers; + private volatile String contentId; + private String contentType; + volatile boolean parsed; // part is parsed or not + final MIMEMessage msg; + private final DataHead dataHead; + + MIMEPart(MIMEMessage msg) { + this.msg = msg; + this.dataHead = new DataHead(this); + } + + MIMEPart(MIMEMessage msg, String contentId) { + this(msg); + this.contentId = contentId; + } + + /** + * Can get the attachment part's content multiple times. That means + * the full content needs to be there in memory or on the file system. + * Calling this method would trigger parsing for the part's data. So + * do not call this unless it is required(otherwise, just wrap MIMEPart + * into a object that returns InputStream for e.g DataHandler) + * + * @return data for the part's content + */ + public InputStream read() { + return dataHead.read(); + } + + /** + * Cleans up any resources that are held by this part (for e.g. deletes + * the temp file that is used to serve this part's content). After + * calling this, one shouldn't call {@link #read()} or {@link #readOnce()} + */ + public void close() { + dataHead.close(); + } + + + /** + * Can get the attachment part's content only once. The content + * will be lost after the method. Content data is not be stored + * on the file system or is not kept in the memory for the + * following case: + * - Attachement parts contents are accessed sequentially + * + * In general, take advantage of this when the data is used only + * once. + * + * @return data for the part's content + */ + public InputStream readOnce() { + return dataHead.readOnce(); + } + + public void moveTo(File f) { + dataHead.moveTo(f); + } + + /** + * Returns Content-ID MIME header for this attachment part + * + * @return Content-ID of the part + */ + public String getContentId() { + if (contentId == null) { + getHeaders(); + } + return contentId; + } + + /** + * Returns Content-Type MIME header for this attachment part + * + * @return Content-Type of the part + */ + public String getContentType() { + if (contentType == null) { + getHeaders(); + } + return contentType; + } + + private void getHeaders() { + // Trigger parsing for the part headers + while(headers == null) { + if (!msg.makeProgress()) { + if (headers == null) { + throw new IllegalStateException("Internal Error. Didn't get Headers even after complete parsing."); + } + } + } + } + + /** + * Return all the values for the specified header. + * Returns <code>null</code> if no headers with the + * specified name exist. + * + * @param name header name + * @return list of header values, or null if none + */ + public List<String> getHeader(String name) { + getHeaders(); + assert headers != null; + return headers.getHeader(name); + } + + /** + * Return all the headers + * + * @return list of Header objects + */ + public List<? extends Header> getAllHeaders() { + getHeaders(); + assert headers != null; + return headers.getAllHeaders(); + } + + /** + * Callback to set headers + * + * @param headers MIME headers for the part + */ + void setHeaders(InternetHeaders headers) { + this.headers = headers; + List<String> ct = getHeader("Content-Type"); + this.contentType = (ct == null) ? "application/octet-stream" : ct.get(0); + } + + /** + * Callback to notify that there is a partial content for the part + * + * @param buf content data for the part + */ + void addBody(ByteBuffer buf) { + dataHead.addBody(buf); + } + + /** + * Callback to indicate that parsing is done for this part + * (no more update events for this part) + */ + void doneParsing() { + parsed = true; + dataHead.doneParsing(); + } + + /** + * Callback to set Content-ID for this part + * @param cid Content-ID of the part + */ + void setContentId(String cid) { + this.contentId = cid; + } + + @Override + public String toString() { + return "Part="+contentId; + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/org/jvnet/mimepull/MemoryData.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,96 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.xml.internal.org.jvnet.mimepull; + +import java.nio.ByteBuffer; +import java.io.File; +import java.io.IOException; +import java.util.logging.Logger; + +/** + * Keeps the Part's partial content data in memory. + * + * @author Kohsuke Kawaguchi + * @author Jitendra Kotamraju + */ +final class MemoryData implements Data { + private static final Logger LOGGER = Logger.getLogger(MemoryData.class.getName()); + + private final byte[] data; + private final int len; + private final MIMEConfig config; + + MemoryData(ByteBuffer buf, MIMEConfig config) { + data = buf.array(); + len = buf.limit(); + this.config = config; + } + + // size of the chunk given by the parser + public int size() { + return len; + } + + public byte[] read() { + return data; + } + + public long writeTo(DataFile file) { + return file.writeTo(data, 0, len); + } + + /** + * + * @param dataHead + * @param buf + * @return + */ + public Data createNext(DataHead dataHead, ByteBuffer buf) { + if (!config.isOnlyMemory() && dataHead.inMemory >= config.memoryThreshold) { + try { + String prefix = config.getTempFilePrefix(); + String suffix = config.getTempFileSuffix(); + File dir = config.getTempDir(); + File tempFile = (dir == null) + ? File.createTempFile(prefix, suffix) + : File.createTempFile(prefix, suffix, dir); + LOGGER.fine("Created temp file = "+tempFile); + dataHead.dataFile = new DataFile(tempFile); + } catch(IOException ioe) { + throw new MIMEParsingException(ioe); + } + + if (dataHead.head != null) { + for(Chunk c=dataHead.head; c != null; c=c.next) { + long pointer = c.data.writeTo(dataHead.dataFile); + c.data = new FileData(dataHead.dataFile, pointer, len); + } + } + return new FileData(dataHead.dataFile, buf); + } else { + return new MemoryData(buf, config); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/org/jvnet/mimepull/WeakDataFile.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,116 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.xml.internal.org.jvnet.mimepull; + +import java.io.File; +import java.io.IOException; +import java.io.RandomAccessFile; +import java.lang.ref.ReferenceQueue; +import java.lang.ref.WeakReference; +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Logger; + +/** + * Removing files based on this + * <a href="http://java.sun.com/developer/technicalArticles/javase/finalization/">article</a> + * + * @author Jitendra Kotamraju + */ +final class WeakDataFile extends WeakReference<DataFile> { + + private static final Logger LOGGER = Logger.getLogger(WeakDataFile.class.getName()); + private static final int MAX_ITERATIONS = 2; + private static ReferenceQueue<DataFile> refQueue = new ReferenceQueue<DataFile>(); + private static List<WeakDataFile> refList = new ArrayList<WeakDataFile>(); + private final File file; + private final RandomAccessFile raf; + + WeakDataFile(DataFile df, File file) { + super(df, refQueue); + refList.add(this); + this.file = file; + try { + raf = new RandomAccessFile(file, "rw"); + } catch(IOException ioe) { + throw new MIMEParsingException(ioe); + } + drainRefQueueBounded(); + } + + synchronized void read(long pointer, byte[] buf, int offset, int length ) { + try { + raf.seek(pointer); + raf.readFully(buf, offset, length); + } catch(IOException ioe) { + throw new MIMEParsingException(ioe); + } + } + + synchronized long writeTo(long pointer, byte[] data, int offset, int length) { + try { + raf.seek(pointer); + raf.write(data, offset, length); + return raf.getFilePointer(); // Update pointer for next write + } catch(IOException ioe) { + throw new MIMEParsingException(ioe); + } + } + + void close() { + LOGGER.fine("Deleting file = "+file.getName()); + refList.remove(this); + try { + raf.close(); + file.delete(); + } catch(IOException ioe) { + throw new MIMEParsingException(ioe); + } + } + + void renameTo(File f) { + LOGGER.fine("Moving file="+file+" to="+f); + refList.remove(this); + try { + raf.close(); + file.renameTo(f); + } catch(IOException ioe) { + throw new MIMEParsingException(ioe); + } + + } + + static void drainRefQueueBounded() { + int iterations = 0; + WeakDataFile weak = (WeakDataFile) refQueue.poll(); + while (weak != null && iterations < MAX_ITERATIONS) { + LOGGER.fine("Cleaning file = "+weak.file+" from reference queue."); + weak.close(); + ++iterations; + weak = (WeakDataFile) refQueue.poll(); + } + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/org/jvnet/staxex/StreamingDataHandler.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,143 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.xml.internal.org.jvnet.staxex; + +import javax.activation.DataHandler; +import javax.activation.DataSource; +import java.io.BufferedInputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; + +/** + * {@link DataHandler} extended to offer better buffer management + * in a streaming environment. + * + * <p> + * {@link DataHandler} is used commonly as a data format across + * multiple systems (such as JAXB/WS.) Unfortunately, {@link DataHandler} + * has the semantics of "read as many times as you want", so this makes + * it difficult for involving parties to handle a BLOB in a streaming fashion. + * + * <p> + * {@link StreamingDataHandler} solves this problem by offering methods + * that enable faster bulk "consume once" read operation. + * + * @author Jitendra Kotamraju + */ +public abstract class StreamingDataHandler extends DataHandler { + + public StreamingDataHandler(Object o, String s) { + super(o, s); + } + + public StreamingDataHandler(URL url) { + super(url); + } + + public StreamingDataHandler(DataSource dataSource) { + super(dataSource); + } + + /** + * Works like {@link #getInputStream()} except that this method + * can be invoked only once. + * + * <p> + * This is used as a signal from the caller that there will + * be no further {@link #getInputStream()} invocation nor + * {@link #readOnce()} invocation on this object (which would + * result in {@link IOException}.) + * + * <p> + * When {@link DataHandler} is backed by a streaming BLOB + * (such as an attachment in a web service read from the network), + * this allows the callee to avoid unnecessary buffering. + * + * <p> + * Note that it is legal to call {@link #getInputStream()} + * multiple times and then call {@link #readOnce()} afterward. + * Streams created such a way can be read in any order — + * there's no requirement that streams created earlier must be read + * first. + * + * @return + * always non-null. Represents the content of this BLOB. + * The returned stream is generally not buffered, so for + * better performance read in a big batch or wrap this into + * {@link BufferedInputStream}. + * @throws IOException + * if any i/o error + */ + public abstract InputStream readOnce() throws IOException; + + /** + * Obtains the BLOB into a specified file. + * + * <p> + * Semantically, this method is roughly equivalent to the following + * code, except that the actual implementation is likely to be a lot faster. + * + * <pre> + * InputStream i = getInputStream(); + * OutputStream o = new FileOutputStream(dst); + * int ch; + * while((ch=i.read())!=-1) o.write(ch); + * i.close(); + * o.close(); + * </pre> + * + * <p> + * The main motivation behind this method is that often + * {@link DataHandler} that reads data from a streaming source + * will use a temporary file as a data store to hold data + * (think of commons-fileupload.) In such case this method + * can be as fast as calling {@link File#renameTo(File)}. + * + * <p> + * This method shouldn't be called when there are any + * open streams. + * + * <p> + * After this method is invoked, {@link #readOnce()} and + * {@link #getInputStream()} will simply open the destination + * file you've specified as an argument. So if you further + * move the file or delete this file, those methods will + * behave in undefined fashion. For a simliar reason, + * calling this method multiple times will cause + * undefined behavior. + */ + public abstract void moveTo(File dst) throws IOException; + + /** + * Releases any resources associated with this DataHandler. + * (such as an attachment in a web service read from a temp + * file will be deleted.) After calling this method, it is + * illegal to call any other methods. + */ + public abstract void close() throws IOException; + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/txw2/output/TXWResult.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,65 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.xml.internal.txw2.output; + +import com.sun.xml.internal.txw2.TypedXmlWriter; + +import javax.xml.transform.Result; + +/** + * Allow you to wrap {@link TypedXmlWriter} into a {@link Result} + * so that it can be passed to {@link ResultFactory}. + * + * <p> + * This class doesn't extend from known {@link Result} type, + * so it won't work elsewhere. + * + * @author Kohsuke Kawaguchi + */ +public class TXWResult implements Result { + private String systemId; + + private TypedXmlWriter writer; + + public TXWResult(TypedXmlWriter writer) { + this.writer = writer; + } + + public TypedXmlWriter getWriter() { + return writer; + } + + public void setWriter(TypedXmlWriter writer) { + this.writer = writer; + } + + public String getSystemId() { + return systemId; + } + + public void setSystemId(String systemId) { + this.systemId = systemId; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/txw2/output/TXWSerializer.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,86 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.xml.internal.txw2.output; + +import com.sun.xml.internal.txw2.TypedXmlWriter; +import com.sun.xml.internal.txw2.TXW; + +/** + * Dummpy implementation to pass through {@link TypedXmlWriter} + * to {@link TXW} + * + * @author Kohsuke Kawaguchi + */ +public final class TXWSerializer implements XmlSerializer { + public final TypedXmlWriter txw; + + public TXWSerializer(TypedXmlWriter txw) { + this.txw = txw; + } + + public void startDocument() { + throw new UnsupportedOperationException(); + } + + public void endDocument() { + throw new UnsupportedOperationException(); + } + + public void beginStartTag(String uri, String localName, String prefix) { + throw new UnsupportedOperationException(); + } + + public void writeAttribute(String uri, String localName, String prefix, StringBuilder value) { + throw new UnsupportedOperationException(); + } + + public void writeXmlns(String prefix, String uri) { + throw new UnsupportedOperationException(); + } + + public void endStartTag(String uri, String localName, String prefix) { + throw new UnsupportedOperationException(); + } + + public void endTag() { + throw new UnsupportedOperationException(); + } + + public void text(StringBuilder text) { + throw new UnsupportedOperationException(); + } + + public void cdata(StringBuilder text) { + throw new UnsupportedOperationException(); + } + + public void comment(StringBuilder comment) { + throw new UnsupportedOperationException(); + } + + public void flush() { + throw new UnsupportedOperationException(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/ws/addressing/W3CWsaClientTube.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,69 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.xml.internal.ws.addressing; + +import com.sun.xml.internal.ws.api.model.wsdl.WSDLPort; +import com.sun.xml.internal.ws.api.WSBinding; +import com.sun.xml.internal.ws.api.message.Packet; +import com.sun.xml.internal.ws.api.pipe.Tube; +import com.sun.xml.internal.ws.api.pipe.TubeCloner; +import com.sun.xml.internal.ws.addressing.model.MissingAddressingHeaderException; + +/** + * @author Rama Pulavarthi + */ +public class W3CWsaClientTube extends WsaClientTube { + public W3CWsaClientTube(WSDLPort wsdlPort, WSBinding binding, Tube next) { + super(wsdlPort, binding, next); + } + + public W3CWsaClientTube(WsaClientTube that, TubeCloner cloner) { + super(that, cloner); + } + + public W3CWsaClientTube copy(TubeCloner cloner) { + return new W3CWsaClientTube(this, cloner); + } + + @Override + protected void checkMandatoryHeaders(Packet packet, boolean foundAction, boolean foundTo, boolean foundReplyTo, + boolean foundFaultTo, boolean foundMessageID, boolean foundRelatesTo) { + super.checkMandatoryHeaders(packet, foundAction, foundTo, foundReplyTo, foundFaultTo, foundMessageID, foundRelatesTo); + + // if it is not one-way, response must contain wsa:RelatesTo + // RelatesTo required as per + // Table 5-3 of http://www.w3.org/TR/2006/WD-ws-addr-wsdl-20060216/#wsdl11requestresponse + if (expectReply && (packet.getMessage() != null) && !foundRelatesTo) { + String action = packet.getMessage().getHeaders().getAction(addressingVersion, soapVersion); + // Don't check for AddressingFaults as + // Faults for requests with duplicate MessageId will have no wsa:RelatesTo + if (!packet.getMessage().isFault() || !action.equals(addressingVersion.getDefaultFaultAction())) { + throw new MissingAddressingHeaderException(addressingVersion.relatesToTag,packet); + } + } + + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/ws/addressing/W3CWsaServerTube.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,76 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.xml.internal.ws.addressing; + +import com.sun.xml.internal.ws.api.server.WSEndpoint; +import com.sun.xml.internal.ws.api.model.wsdl.WSDLPort; +import com.sun.xml.internal.ws.api.model.wsdl.WSDLBoundOperation; +import com.sun.xml.internal.ws.api.WSBinding; +import com.sun.xml.internal.ws.api.message.Packet; +import com.sun.xml.internal.ws.api.pipe.Tube; +import com.sun.xml.internal.ws.api.pipe.TubeCloner; +import com.sun.xml.internal.ws.addressing.model.MissingAddressingHeaderException; +import com.sun.istack.internal.NotNull; + +/** + * @author Rama Pulavarthi + */ +public class W3CWsaServerTube extends WsaServerTube{ + public W3CWsaServerTube(WSEndpoint endpoint, @NotNull WSDLPort wsdlPort, WSBinding binding, Tube next) { + super(endpoint, wsdlPort, binding, next); + } + + public W3CWsaServerTube(WsaServerTube that, TubeCloner cloner) { + super(that, cloner); + } + + protected Packet validateInboundHeaders(Packet packet) { + return super.validateInboundHeaders(packet); + } + + public W3CWsaServerTube copy(TubeCloner cloner) { + return new W3CWsaServerTube(this, cloner); + } + + @Override + protected void checkMandatoryHeaders( + Packet packet, boolean foundAction, boolean foundTo, boolean foundReplyTo, + boolean foundFaultTo, boolean foundMessageId, boolean foundRelatesTo) { + super.checkMandatoryHeaders(packet, foundAction, foundTo, foundReplyTo, + foundFaultTo, foundMessageId, foundRelatesTo); + + // find Req/Response or Oneway using WSDLModel(if it is availabe) + WSDLBoundOperation wbo = getWSDLBoundOperation(packet); + // Taking care of protocol messages as they do not have any corresponding operations + if (wbo != null) { + // if two-way and no wsa:MessageID is found + if (!wbo.getOperation().isOneWay() && !foundMessageId) { + throw new MissingAddressingHeaderException(addressingVersion.messageIDTag,packet); + } + } + + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/ws/addressing/WsaPropertyBag.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,126 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.xml.internal.ws.addressing; + +import com.sun.istack.internal.NotNull; +import com.sun.xml.internal.ws.api.PropertySet; +import com.sun.xml.internal.ws.api.SOAPVersion; +import com.sun.xml.internal.ws.api.addressing.AddressingVersion; +import com.sun.xml.internal.ws.api.addressing.WSEndpointReference; +import com.sun.xml.internal.ws.api.message.Header; +import com.sun.xml.internal.ws.api.message.Message; +import com.sun.xml.internal.ws.api.message.Packet; +import com.sun.xml.internal.ws.developer.JAXWSProperties; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamException; + +/** + * Provides access to the Addressing headers. + * + * @author Kohsuke Kawaguchi + * @author Rama Pulavarthi + * @since 2.1.3 + */ +public class WsaPropertyBag extends PropertySet { + private final @NotNull AddressingVersion addressingVersion; + private final @NotNull SOAPVersion soapVersion; + /** + * We can't store {@link Message} here as those may get replaced as + * the packet travels through the pipeline. + */ + private final @NotNull Packet packet; + + + WsaPropertyBag(AddressingVersion addressingVersion, SOAPVersion soapVersion, Packet packet) { + this.addressingVersion = addressingVersion; + this.soapVersion = soapVersion; + this.packet = packet; + } + + /** + * Gets the <tt>wsa:To</tt> header. + * + * @return + * null if the incoming SOAP message didn't have the header. + */ + @Property(JAXWSProperties.ADDRESSING_TO) + public String getTo() throws XMLStreamException { + Header h = packet.getMessage().getHeaders().get(addressingVersion.toTag, false); + if (h == null) return null; + return h.getStringContent(); + } + + /** + * Gets the <tt>wsa:From</tt> header. + * + * @return + * null if the incoming SOAP message didn't have the header. + */ + @Property(JAXWSProperties.ADDRESSING_FROM) + public WSEndpointReference getFrom() throws XMLStreamException { + return getEPR(addressingVersion.fromTag); + } + + /** + * Gets the <tt>wsa:Action</tt> header content as String. + * + * @return + * null if the incoming SOAP message didn't have the header. + */ + @Property(JAXWSProperties.ADDRESSING_ACTION) + public String getAction() { + Header h = packet.getMessage().getHeaders().get(addressingVersion.actionTag, false); + if(h==null) return null; + return h.getStringContent(); + } + + /** + * Gets the <tt>wsa:MessageID</tt> header content as String. + * + * @return + * null if the incoming SOAP message didn't have the header. + */ + // WsaServerTube.REQUEST_MESSAGE_ID is exposed for backward compatibility with 2.1 + @Property({JAXWSProperties.ADDRESSING_MESSAGEID,WsaServerTube.REQUEST_MESSAGE_ID}) + public String getMessageID() { + return packet.getMessage().getHeaders().getMessageID(addressingVersion,soapVersion); + } + + private WSEndpointReference getEPR(QName tag) throws XMLStreamException { + Header h = packet.getMessage().getHeaders().get(tag, false); + if(h==null) return null; + return h.readAsEPR(addressingVersion); + } + + protected PropertyMap getPropertyMap() { + return model; + } + + private static final PropertyMap model; + static { + model = parse(WsaPropertyBag.class); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/ws/addressing/model/InvalidAddressingHeaderException.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,64 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.xml.internal.ws.addressing.model; + +import com.sun.xml.internal.ws.resources.AddressingMessages; + +import javax.xml.ws.WebServiceException; +import javax.xml.namespace.QName; + +/** + * This exception captures SOAP Fault information when a WS-Addressing 1.0 Message Addressing + * Property is invalid and cannot be processed. + * + * @author Rama Pulavarthi + */ +public class InvalidAddressingHeaderException extends WebServiceException { + private QName problemHeader; + private QName subsubcode; + + /** + * Creates a InvalidAddressingHeader exception capturing information about the invalid + * Addressing Message Property and the reason in Subsubcode. + * @param problemHeader + * represents the invalid Addressing Header. + * @param subsubcode + * represents the reason why the Addressing header in question is invalid. + */ + public InvalidAddressingHeaderException(QName problemHeader, QName subsubcode) { + super(AddressingMessages.INVALID_ADDRESSING_HEADER_EXCEPTION(problemHeader,subsubcode)); + this.problemHeader = problemHeader; + this.subsubcode = subsubcode; + } + + public QName getProblemHeader() { + return problemHeader; + } + + public QName getSubsubcode() { + return subsubcode; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/ws/addressing/model/MissingAddressingHeaderException.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,78 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.xml.internal.ws.addressing.model; + +import com.sun.istack.internal.NotNull; +import com.sun.istack.internal.Nullable; +import com.sun.xml.internal.ws.api.message.Packet; +import com.sun.xml.internal.ws.resources.AddressingMessages; + +import javax.xml.ws.WebServiceException; +import javax.xml.namespace.QName; + +/** + * This exception signals that a particular WS-Addressing header is missing in a SOAP message. + * + * @author Rama Pulavarthi + */ +public class MissingAddressingHeaderException extends WebServiceException { + private final QName name; + private final Packet packet; + + /** + * + * @param name QName of the missing WS-Addressing Header + */ + public MissingAddressingHeaderException(@NotNull QName name) { + this(name,null); + } + + public MissingAddressingHeaderException(@NotNull QName name, @Nullable Packet p) { + super(AddressingMessages.MISSING_HEADER_EXCEPTION(name)); + this.name = name; + this.packet = p; + } + + /** + * Gets the QName of the missing WS-Addressing Header. + * + * @return + * never null. + */ + public QName getMissingHeaderQName() { + return name; + } + + /** + * The {@link Packet} in which a header was missing. + * + * <p> + * This object can be used to deep-inspect the problematic SOAP message. + */ + public Packet getPacket() { + return packet; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/ws/addressing/v200408/MemberSubmissionWsaClientTube.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,84 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.xml.internal.ws.addressing.v200408; + +import com.sun.xml.internal.ws.addressing.WsaClientTube; +import com.sun.xml.internal.ws.addressing.model.MissingAddressingHeaderException; +import com.sun.xml.internal.ws.api.model.wsdl.WSDLPort; +import com.sun.xml.internal.ws.api.WSBinding; +import com.sun.xml.internal.ws.api.message.Packet; +import com.sun.xml.internal.ws.api.pipe.Tube; +import com.sun.xml.internal.ws.api.pipe.TubeCloner; +import com.sun.xml.internal.ws.developer.MemberSubmissionAddressing; +import com.sun.xml.internal.ws.developer.MemberSubmissionAddressingFeature; + +/** + * @author Rama Pulavarthi + */ +public class MemberSubmissionWsaClientTube extends WsaClientTube { + private final MemberSubmissionAddressing.Validation validation; + + public MemberSubmissionWsaClientTube(WSDLPort wsdlPort, WSBinding binding, Tube next) { + super(wsdlPort, binding, next); + validation = binding.getFeature(MemberSubmissionAddressingFeature.class).getValidation(); + + } + + public MemberSubmissionWsaClientTube(MemberSubmissionWsaClientTube that, TubeCloner cloner) { + super(that, cloner); + this.validation = that.validation; + + } + public MemberSubmissionWsaClientTube copy(TubeCloner cloner) { + return new MemberSubmissionWsaClientTube(this, cloner); + } + + @Override + protected void checkMandatoryHeaders(Packet packet, boolean foundAction, boolean foundTo, boolean foundReplyTo, + boolean foundFaultTo, boolean foundMessageID, boolean foundRelatesTo) { + super.checkMandatoryHeaders(packet,foundAction,foundTo,foundReplyTo,foundFaultTo,foundMessageID,foundRelatesTo); + + // if no wsa:To header is found + if (!foundTo) { + throw new MissingAddressingHeaderException(addressingVersion.toTag,packet); + } + + if (!validation.equals(MemberSubmissionAddressing.Validation.LAX)) { + + // if it is not one-way, response must contain wsa:RelatesTo + // RelatesTo required as per + // Table 5-3 of http://www.w3.org/TR/2006/WD-ws-addr-wsdl-20060216/#wsdl11requestresponse + if (expectReply && (packet.getMessage() != null) && !foundRelatesTo) { + String action = packet.getMessage().getHeaders().getAction(addressingVersion, soapVersion); + // Don't check for AddressingFaults as + // Faults for requests with duplicate MessageId will have no wsa:RelatesTo + if (!packet.getMessage().isFault() || !action.equals(addressingVersion.getDefaultFaultAction())) { + throw new MissingAddressingHeaderException(addressingVersion.relatesToTag,packet); + } + } + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/ws/addressing/v200408/MemberSubmissionWsaServerTube.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,87 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.xml.internal.ws.addressing.v200408; + +import com.sun.istack.internal.NotNull; +import com.sun.xml.internal.ws.addressing.WsaServerTube; +import com.sun.xml.internal.ws.addressing.model.MissingAddressingHeaderException; +import com.sun.xml.internal.ws.api.WSBinding; +import com.sun.xml.internal.ws.api.message.Packet; +import com.sun.xml.internal.ws.api.model.wsdl.WSDLBoundOperation; +import com.sun.xml.internal.ws.api.model.wsdl.WSDLPort; +import com.sun.xml.internal.ws.api.pipe.Tube; +import com.sun.xml.internal.ws.api.pipe.TubeCloner; +import com.sun.xml.internal.ws.api.server.WSEndpoint; +import com.sun.xml.internal.ws.developer.MemberSubmissionAddressing; +import com.sun.xml.internal.ws.developer.MemberSubmissionAddressingFeature; + +/** + * @author Rama Pulavarthi + */ +public class MemberSubmissionWsaServerTube extends WsaServerTube { + private final MemberSubmissionAddressing.Validation validation; + public MemberSubmissionWsaServerTube(WSEndpoint endpoint, @NotNull WSDLPort wsdlPort, WSBinding binding, Tube next) { + super(endpoint, wsdlPort, binding, next); + validation = binding.getFeature(MemberSubmissionAddressingFeature.class).getValidation(); + } + + public MemberSubmissionWsaServerTube(MemberSubmissionWsaServerTube that, TubeCloner cloner) { + super(that, cloner); + this.validation = that.validation; + } + + public MemberSubmissionWsaServerTube copy(TubeCloner cloner) { + return new MemberSubmissionWsaServerTube(this, cloner); + } + + @Override + protected void checkMandatoryHeaders(Packet packet, boolean foundAction, boolean foundTo, boolean foundReplyTo, + boolean foundFaultTo, boolean foundMessageId, boolean foundRelatesTo) { + + super.checkMandatoryHeaders(packet, foundAction, foundTo, foundReplyTo, + foundFaultTo, foundMessageId, foundRelatesTo); + + // if no wsa:To header is found + if (!foundTo) + throw new MissingAddressingHeaderException(addressingVersion.toTag,packet); + + //we can find Req/Response or Oneway only with WSDLModel + if (wsdlPort != null) { + WSDLBoundOperation wbo = getWSDLBoundOperation(packet); + // if two-way, must contain wsa:ReplyTo + // Unlike W3C version, we cannot assume default value as anonymous if not present. + // For protocol messages, don't check as they do not have any corresponding wsdl operations + if (wbo != null && !wbo.getOperation().isOneWay() && !foundReplyTo) { + throw new MissingAddressingHeaderException(addressingVersion.replyToTag,packet); + } + } + if (!validation.equals(MemberSubmissionAddressing.Validation.LAX)) { + // wsa:MessageId is required if wsa:ReplyTo is present. + if ((foundReplyTo || foundFaultTo) && !foundMessageId) + throw new MissingAddressingHeaderException(addressingVersion.messageIDTag,packet); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/ws/api/ResourceLoader.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,67 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.xml.internal.ws.api; + +import com.sun.xml.internal.ws.api.server.Container; + +import java.net.MalformedURLException; +import java.net.URL; + +/** + * Used to locate resources for jax-ws extensions. Using this, extensions + * do not to have to write container specific code to locate resources. + * + * @author Jitendra Kotamraju + */ +public abstract class ResourceLoader { + + /** + * Returns the actual location of the resource from the 'resource' arg + * that represents a virtual locaion of a file understood by a container. + * ResourceLoader impl for a Container knows how to map this + * virtual location to actual location. + * <p> + * Extensions can get hold of this object using {@link Container}. + * <p/> + * for e.g.: + * <pre> + * ResourceLoader loader = container.getSPI(ResourceLoader.class); + * URL catalog = loader.get("jax-ws-catalog.xml"); + * </pre> + * A ResourceLoader for servlet environment, may do the following. + * <pre> + * URL getResource(String resource) { + * return servletContext.getResource("/WEB-INF/"+resource); + * } + * </pre> + * + * @param resource Designates a path that is understood by the container. The + * implementations must support "jax-ws-catalog.xml" resource. + * @return the actual location, if found, or null if not found. + * @throws MalformedURLException if there is an error in creating URL + */ + public abstract URL getResource(String resource) throws MalformedURLException; + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/ws/api/handler/MessageHandler.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,54 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.xml.internal.ws.api.handler; + +import javax.xml.ws.handler.Handler; +import javax.xml.namespace.QName; +import java.util.Set; + + +/** + * The <code>MessageHandler</code> class extends <code>Handler</code> + * to provide typesafety for the message context parameter and add a method + * to obtain access to the headers that may be processed by the handler. + * Its provides similar functionality as a SOAPHandler but provides RI's + * Message in the MessageContext. + * + * @author Rama Pulavarthi + * @since JAX-WS 2.1.3 + */ +public interface MessageHandler<C extends MessageHandlerContext> extends Handler<C> { + + + /** Gets the header blocks that can be processed by this Handler + * instance. + * + * @return Set of <code>QNames</code> of header blocks processed by this + * handler instance. <code>QName</code> is the qualified + * name of the outermost element of the Header block. + **/ + Set<QName> getHeaders(); + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/ws/api/handler/MessageHandlerContext.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,88 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.xml.internal.ws.api.handler; + +import com.sun.istack.internal.Nullable; +import com.sun.xml.internal.ws.api.WSBinding; +import com.sun.xml.internal.ws.api.message.Message; +import com.sun.xml.internal.ws.api.model.SEIModel; +import com.sun.xml.internal.ws.api.model.wsdl.WSDLPort; + +import javax.xml.ws.handler.MessageContext; +import java.util.Set; + +/** + * The <code>MessageHandlerContext</code> interface extends + * <code>MessageContext</code> to provide easy access to the contained message. + * + * This context provides access to RI's <code>Message</code> model for efficient access + * to various things like accessing headers etc. It also provides access to + * binding information as <code>WSBinding</code>. + * + * @author Rama Pulavarthi + * @since JAX-WS 2.1.3 + */ +public interface MessageHandlerContext extends MessageContext { + /** + * Gets the message from this message context + * + * @return The contained message; returns <code>null</code> if no + * message is present in this message context + */ + public Message getMessage(); + + + /** + * Sets the message in this message context + */ + public void setMessage(Message message); + + /** + * @see javax.xml.ws.handler.soap.SOAPMessageContext#getRoles() + */ + public Set<String> getRoles(); + + + /** + * Provides access to <code>WSBinding</code> which can be used in various ways. + * for example: <code>WSBinding#getSOAPVersion</code> to get SOAP version of the binding. + * <code>WSBinding#isFeatureEnabled(AddressingFeature)</code> to check if addressing is enabled + */ + public WSBinding getWSBinding(); + + /** + * Provides access to <code>SEIModel</code>. + */ + public @Nullable SEIModel getSEIModel(); + + /** + * Gets the {@link WSDLPort} that represents the port. + * @return + * returns the WSDLModel of the port that the client/endpoint binds to. + * null when the Service is not configured with WSDL information. + */ + public @Nullable WSDLPort getPort(); + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/ws/api/message/FilterMessageImpl.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,164 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.xml.internal.ws.api.message; + +import com.sun.istack.internal.NotNull; +import com.sun.istack.internal.Nullable; +import com.sun.xml.internal.bind.api.Bridge; +import com.sun.xml.internal.ws.api.SOAPVersion; +import com.sun.xml.internal.ws.api.WSBinding; +import com.sun.xml.internal.ws.api.addressing.AddressingVersion; +import com.sun.xml.internal.ws.api.model.wsdl.WSDLPort; +import org.xml.sax.ContentHandler; +import org.xml.sax.ErrorHandler; +import org.xml.sax.SAXException; + +import javax.xml.bind.JAXBException; +import javax.xml.bind.Unmarshaller; +import javax.xml.namespace.QName; +import javax.xml.soap.SOAPException; +import javax.xml.soap.SOAPMessage; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; +import javax.xml.stream.XMLStreamWriter; +import javax.xml.transform.Source; + +/** + * A <code>FilterMessageImpl</code> contains some other Message, which it uses + * as its basic source of message data, possibly transforming the data along + * the way or providing additional functionality. + * + * <p> + * The class <code>FilterMessageImpl</code> itself simply overrides + * all the methods of <code>Message</code> and invokes them on + * contained Message delegate. Subclasses of <code>FilterMessageImpl</code> + * may further override some of these methods and may also provide + * additional methods and fields. + * + * @author Jitendra Kotamraju + */ +public class FilterMessageImpl extends Message { + private final Message delegate; + + protected FilterMessageImpl(Message delegate) { + this.delegate = delegate; + } + + public boolean hasHeaders() { + return delegate.hasHeaders(); + } + + public @NotNull HeaderList getHeaders() { + return delegate.getHeaders(); + } + + public @NotNull AttachmentSet getAttachments() { + return delegate.getAttachments(); + } + + protected boolean hasAttachments() { + return delegate.hasAttachments(); + } + + public boolean isOneWay(@NotNull WSDLPort port) { + return delegate.isOneWay(port); + } + + public @Nullable String getPayloadLocalPart() { + return delegate.getPayloadLocalPart(); + } + + public String getPayloadNamespaceURI() { + return delegate.getPayloadNamespaceURI(); + } + + public boolean hasPayload() { + return delegate.hasPayload(); + } + + public boolean isFault() { + return delegate.isFault(); + } + + public @Nullable QName getFirstDetailEntryName() { + return delegate.getFirstDetailEntryName(); + } + + public Source readEnvelopeAsSource() { + return delegate.readEnvelopeAsSource(); + } + + public Source readPayloadAsSource() { + return delegate.readPayloadAsSource(); + } + + public SOAPMessage readAsSOAPMessage() throws SOAPException { + return delegate.readAsSOAPMessage(); + } + + public SOAPMessage readAsSOAPMessage(Packet packet, boolean inbound) throws SOAPException { + return delegate.readAsSOAPMessage(packet, inbound); + } + + public <T> T readPayloadAsJAXB(Unmarshaller unmarshaller) throws JAXBException { + return (T)delegate.readPayloadAsJAXB(unmarshaller); + } + + public <T> T readPayloadAsJAXB(Bridge<T> bridge) throws JAXBException { + return delegate.readPayloadAsJAXB(bridge); + } + + public XMLStreamReader readPayload() throws XMLStreamException { + return delegate.readPayload(); + } + + public void consume() { + delegate.consume(); + } + + public void writePayloadTo(XMLStreamWriter sw) throws XMLStreamException { + delegate.writePayloadTo(sw); + } + + public void writeTo(XMLStreamWriter sw) throws XMLStreamException { + delegate.writeTo(sw); + } + + public void writeTo(ContentHandler contentHandler, ErrorHandler errorHandler) throws SAXException { + delegate.writeTo(contentHandler, errorHandler); + } + + public Message copy() { + return delegate.copy(); + } + + public @NotNull String getID(@NotNull WSBinding binding) { + return delegate.getID(binding); + } + + public @NotNull String getID(AddressingVersion av, SOAPVersion sv) { + return delegate.getID(av, sv); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/ws/api/model/wsdl/WSDLBoundFault.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,73 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.xml.internal.ws.api.model.wsdl; + +import com.sun.istack.internal.NotNull; +import com.sun.istack.internal.Nullable; + +import javax.xml.namespace.QName; + +/** + * Abstracts wsdl:binding/wsdl:operation/wsdl:fault + * + * @author Vivek Pandey + */ +public interface WSDLBoundFault extends WSDLObject, WSDLExtensible { + + /** + * Gives the wsdl:binding/wsdl:operation/wsdl:fault@name value + */ + public + @NotNull + String getName(); + + /** + * Gives the qualified name associated with the fault. the namespace URI of the bounded fault + * will be the one derived from wsdl:portType namespace. + * + * Maybe null if this method is called before the model is completely build (frozen), if a binding fault has no + * corresponding fault in abstractwsdl:portType/wsdl:operation then the namespace URI of the fault will be that of + * the WSDBoundPortType. + */ + public @Nullable QName getQName(); + + /** + * Gives the associated abstract fault from + * wsdl:portType/wsdl:operation/wsdl:fault. It is only available after + * the WSDL parsing is complete and the entire model is frozen. + * <p/> + * Maybe null if a binding fault has no corresponding fault in abstract + * wsdl:portType/wsdl:operation + */ + public + @Nullable + WSDLFault getFault(); + + /** + * Gives the owner {@link WSDLBoundOperation} + */ + @NotNull WSDLBoundOperation getBoundOperation(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/ws/api/server/EndpointComponent.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,52 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.xml.internal.ws.api.server; + +import com.sun.istack.internal.NotNull; +import com.sun.istack.internal.Nullable; + +/** + * Interface that allows components around {@link WSEndpoint} to hook up + * with each other. + * + * @author Kohsuke Kawaguchi + * @since 2.1.2 + * @see WSEndpoint#getComponentRegistry() + */ +public interface EndpointComponent { + /** + * Gets the specified SPI. + * + * <p> + * This method works as a kind of directory service + * for SPIs, allowing various components to define private contract + * and talk to each other. + * + * @return + * null if such an SPI is not provided by this object. + */ + @Nullable <T> T getSPI(@NotNull Class<T> spiType); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/ws/api/server/HttpEndpoint.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,62 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.xml.internal.ws.api.server; + +import com.sun.istack.internal.NotNull; + +/** + * Light-weight http server transport for {@link WSEndpoint}. + * It provides a way to start the transport at a local http address and + * to stop the transport. + * + * @author Jitendra Kotamraju + */ +public abstract class HttpEndpoint { + + /** + * Factory to deploy {@link WSEndpoint} on light-weight + * http server container. + * + * @param endpoint that needs to be deployed at http server + * @return transport object for the endpoint + */ + public static HttpEndpoint create(@NotNull WSEndpoint endpoint) { + return new com.sun.xml.internal.ws.transport.http.server.HttpEndpoint(endpoint, null); + } + + /** + * Publishes this endpoint at a localhost's http address. + * + * @param address endpoint's http address + * for e.g http://localhost:8080/ctxt/pattern + */ + public abstract void publish(@NotNull String address); + + /** + * Stops the published endpoint + */ + public abstract void stop(); + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/ws/client/ClientContainer.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,55 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.xml.internal.ws.client; + +import com.sun.xml.internal.ws.api.ResourceLoader; +import com.sun.xml.internal.ws.api.server.Container; + +import java.net.MalformedURLException; +import java.net.URL; + +/** + * @author Jitendra Kotamraju + */ +final class ClientContainer extends Container { + + private final ResourceLoader loader = new ResourceLoader() { + public URL getResource(String resource) throws MalformedURLException { + ClassLoader cl = Thread.currentThread().getContextClassLoader(); + if (cl == null) { + cl = this.getClass().getClassLoader(); + } + return cl.getResource("META-INF/"+resource); + } + }; + + public <T> T getSPI(Class<T> spiType) { + if (spiType == ResourceLoader.class) { + return spiType.cast(loader); + } + return null; + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/ws/client/ClientSchemaValidationTube.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,163 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.xml.internal.ws.client; + +import com.sun.xml.internal.ws.api.WSBinding; +import com.sun.xml.internal.ws.api.model.wsdl.WSDLPort; +import com.sun.xml.internal.ws.api.pipe.Tube; +import com.sun.xml.internal.ws.api.pipe.TubeCloner; +import com.sun.xml.internal.ws.api.pipe.helper.AbstractTubeImpl; +import com.sun.xml.internal.ws.api.server.SDDocument; +import com.sun.xml.internal.ws.api.server.SDDocumentSource; +import com.sun.xml.internal.ws.util.MetadataUtil; +import com.sun.xml.internal.ws.util.pipe.AbstractSchemaValidationTube; +import com.sun.xml.internal.ws.util.xml.MetadataDocument; +import org.w3c.dom.Document; +import org.xml.sax.SAXException; + +import javax.xml.XMLConstants; +import javax.xml.namespace.QName; +import javax.xml.transform.Source; +import javax.xml.transform.dom.DOMSource; +import javax.xml.validation.Schema; +import javax.xml.validation.SchemaFactory; +import javax.xml.validation.Validator; +import javax.xml.ws.WebServiceException; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.logging.Logger; + +/** + * {@link Tube} that does the schema validation on the client side. + * + * @author Jitendra Kotamraju + */ +public class ClientSchemaValidationTube extends AbstractSchemaValidationTube { + + private static final Logger LOGGER = Logger.getLogger(ClientSchemaValidationTube.class.getName()); + + private final Schema schema; + private final Validator validator; + private final boolean noValidation; + private final WSDLPort port; + + public ClientSchemaValidationTube(WSBinding binding, WSDLPort port, Tube next) { + super(binding, next); + this.port = port; + Source[] sources = null; + if (port != null) { + String primaryWsdl = port.getOwner().getParent().getLocation().getSystemId(); + sources = getSchemaSources(primaryWsdl); + for(Source source : sources) { + LOGGER.fine("Constructing validation Schema from = "+source.getSystemId()); + //printDOM((DOMSource)source); + } + } + if (sources != null) { + noValidation = false; + SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); + try { + schema = sf.newSchema(sources); + } catch(SAXException e) { + throw new WebServiceException(e); + } + validator = schema.newValidator(); + } else { + noValidation = true; + schema = null; + validator = null; + } + } + + private class MetadataResolverImpl implements MetadataUtil.MetadataResolver{ + + Map<String, SDDocument> docs = new HashMap<String, SDDocument>(); + + public SDDocument resolveEntity(String systemId) { + SDDocument sdi = docs.get(systemId); + if (sdi == null) { + SDDocumentSource sds; + try { + sds = SDDocumentSource.create(new URL(systemId)); + } catch(MalformedURLException e) { + throw new WebServiceException(e); + } + sdi = MetadataDocument.create(sds, new QName(""), new QName("")); + docs.put(systemId, sdi); + } + return sdi; + } + } + + private Source[] getSchemaSources(String primary) { + + MetadataUtil.MetadataResolver mdresolver = new MetadataResolverImpl(); + Map<String, SDDocument> docs = MetadataUtil.getMetadataClosure(primary, mdresolver, true); + + List<Source> list = new ArrayList<Source>(); + for(Map.Entry<String, SDDocument> entry : docs.entrySet()) { + SDDocument doc = entry.getValue(); + // Add all xsd:schema fragments from all WSDLs. That should form a closure of schemas. + if (doc.isWSDL()) { + Document dom = createDOM(doc); + // Get xsd:schema node from WSDL's DOM + addSchemaFragmentSource(dom, doc.getURL().toExternalForm(), list); + } else if (doc.isSchema()) { + // If there are multiple schemas with the same targetnamespace, + // JAXP works only with the first one. Above, all schema fragments may have the same targetnamespace, + // and that means it will not include all the schemas. Since we have a list of schemas, just add them. + Document dom = createDOM(doc); + list.add(new DOMSource(dom, doc.getURL().toExternalForm())); + } + } + //addSchemaSource(list); + return list.toArray(new Source[list.size()]) ; + } + + protected Validator getValidator() { + return validator; + } + + protected boolean isNoValidation() { + return noValidation; + } + + protected ClientSchemaValidationTube(ClientSchemaValidationTube that, TubeCloner cloner) { + super(that,cloner); + this.port = that.port; + this.schema = that.schema; + this.validator = schema.newValidator(); + this.noValidation = that.noValidation; + } + + public AbstractTubeImpl copy(TubeCloner cloner) { + return new ClientSchemaValidationTube(this,cloner); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/ws/client/sei/SEIMethodHandler.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,214 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.xml.internal.ws.client.sei; + +import com.sun.xml.internal.ws.api.message.Message; +import com.sun.xml.internal.ws.model.CheckedExceptionImpl; +import com.sun.xml.internal.ws.model.JavaMethodImpl; +import com.sun.xml.internal.ws.model.ParameterImpl; +import com.sun.xml.internal.ws.model.WrapperParameter; + +import javax.xml.namespace.QName; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * {@link com.sun.xml.internal.ws.client.sei.MethodHandler} that handles synchronous method invocations. + * + * <p> + * This class mainly performs the following two tasks: + * <ol> + * <li>Accepts Object[] that represents arguments for a Java method, + * and creates {@link com.sun.xml.internal.ws.message.jaxb.JAXBMessage} that represents a request message. + * <li>Takes a {@link com.sun.xml.internal.ws.api.message.Message] that represents a response, + * and extracts the return value (and updates {@link javax.xml.ws.Holder }s.) + * </ol> + * + * <h2>Creating {@link com.sun.xml.internal.ws.message.jaxb.JAXBMessage }</h2> + * <p> + * At the construction time, we prepare {@link com.sun.xml.internal.ws.client.sei.BodyBuilder} and {@link com.sun.xml.internal.ws.client.sei.MessageFiller}s + * that know how to move arguments into a {@link com.sun.xml.internal.ws.api.message.Message }. + * Some arguments go to the payload, some go to headers, still others go to attachments. + * + * @author Kohsuke Kawaguchi + * @author Jitendra Kotamraju + */ +abstract class SEIMethodHandler extends MethodHandler { + + // these objects together create a message from method parameters + private final BodyBuilder bodyBuilder; + private final MessageFiller[] inFillers; + + protected final String soapAction; + + protected final boolean isOneWay; + + protected final JavaMethodImpl javaMethod; + + protected final Map<QName, CheckedExceptionImpl> checkedExceptions; + + SEIMethodHandler(SEIStub owner, JavaMethodImpl method) { + super(owner); + + //keep all the CheckedException model for the detail qname + this.checkedExceptions = new HashMap<QName, CheckedExceptionImpl>(); + for(CheckedExceptionImpl ce : method.getCheckedExceptions()){ + checkedExceptions.put(ce.getBridge().getTypeReference().tagName, ce); + } + //If a non-"" soapAction is specified, wsa:action the SOAPAction + if(method.getInputAction() != null && !method.getBinding().getSOAPAction().equals("") ) { + this.soapAction = method.getInputAction(); + } else { + this.soapAction = method.getBinding().getSOAPAction(); + } + this.javaMethod = method; + + {// prepare objects for creating messages + List<ParameterImpl> rp = method.getRequestParameters(); + + BodyBuilder bodyBuilder = null; + List<MessageFiller> fillers = new ArrayList<MessageFiller>(); + + for (ParameterImpl param : rp) { + ValueGetter getter = getValueGetterFactory().get(param); + + switch(param.getInBinding().kind) { + case BODY: + if(param.isWrapperStyle()) { + if(param.getParent().getBinding().isRpcLit()) + bodyBuilder = new BodyBuilder.RpcLit((WrapperParameter)param, owner.soapVersion, getValueGetterFactory()); + else + bodyBuilder = new BodyBuilder.DocLit((WrapperParameter)param, owner.soapVersion, getValueGetterFactory()); + } else { + bodyBuilder = new BodyBuilder.Bare(param, owner.soapVersion, getter); + } + break; + case HEADER: + fillers.add(new MessageFiller.Header( + param.getIndex(), + param.getBridge(), + getter )); + break; + case ATTACHMENT: + fillers.add(MessageFiller.AttachmentFiller.createAttachmentFiller(param, getter)); + break; + case UNBOUND: + break; + default: + throw new AssertionError(); // impossible + } + } + + if(bodyBuilder==null) { + // no parameter binds to body. we create an empty message + switch(owner.soapVersion) { + case SOAP_11: + bodyBuilder = BodyBuilder.EMPTY_SOAP11; + break; + case SOAP_12: + bodyBuilder = BodyBuilder.EMPTY_SOAP12; + break; + default: + throw new AssertionError(); + } + } + + this.bodyBuilder = bodyBuilder; + this.inFillers = fillers.toArray(new MessageFiller[fillers.size()]); + } + + this.isOneWay = method.getMEP().isOneWay(); + } + + ResponseBuilder buildResponseBuilder(JavaMethodImpl method, ValueSetterFactory setterFactory) { + // prepare objects for processing response + List<ParameterImpl> rp = method.getResponseParameters(); + List<ResponseBuilder> builders = new ArrayList<ResponseBuilder>(); + + for( ParameterImpl param : rp ) { + ValueSetter setter; + switch(param.getOutBinding().kind) { + case BODY: + if(param.isWrapperStyle()) { + if(param.getParent().getBinding().isRpcLit()) + builders.add(new ResponseBuilder.RpcLit((WrapperParameter)param, setterFactory)); + else + builders.add(new ResponseBuilder.DocLit((WrapperParameter)param, setterFactory)); + } else { + setter = setterFactory.get(param); + builders.add(new ResponseBuilder.Body(param.getBridge(),setter)); + } + break; + case HEADER: + setter = setterFactory.get(param); + builders.add(new ResponseBuilder.Header(owner.soapVersion, param, setter)); + break; + case ATTACHMENT: + setter = setterFactory.get(param); + builders.add(ResponseBuilder.AttachmentBuilder.createAttachmentBuilder(param, setter)); + break; + case UNBOUND: + setter = setterFactory.get(param); + builders.add(new ResponseBuilder.NullSetter(setter, + ResponseBuilder.getVMUninitializedValue(param.getTypeReference().type))); + break; + default: + throw new AssertionError(); + } + } + ResponseBuilder rb; + switch(builders.size()) { + case 0: + rb = ResponseBuilder.NONE; + break; + case 1: + rb = builders.get(0); + break; + default: + rb = new ResponseBuilder.Composite(builders); + } + return rb; + } + + + /** + * Creates a request {@link com.sun.xml.internal.ws.message.jaxb.JAXBMessage} from method arguments. + * @param args proxy invocation arguments + * @return Message for the arguments + */ + Message createRequestMessage(Object[] args) { + Message msg = bodyBuilder.createMessage(args); + + for (MessageFiller filler : inFillers) + filler.fillIn(args,msg); + + return msg; + } + + abstract ValueGetterFactory getValueGetterFactory(); + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/ws/client/sei/ValueGetterFactory.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,57 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.xml.internal.ws.client.sei; + +import com.sun.xml.internal.ws.model.ParameterImpl; + +import javax.jws.WebParam; + +/** + * {@link ValueGetterFactory} is used to create {@link ValueGetter} objects. + * + * @author Jitendra Kotamraju + */ +abstract class ValueGetterFactory { + + abstract ValueGetter get(ParameterImpl p); + + static final ValueGetterFactory SYNC = new ValueGetterFactory() { + ValueGetter get(ParameterImpl p) { + return (p.getMode()== WebParam.Mode.IN || p.getIndex() == -1) + ? ValueGetter.PLAIN : ValueGetter.HOLDER; + } + }; + + /** + * In case of SEI async signatures, there are no holders. The OUT + * parameters go in async bean class + */ + static final ValueGetterFactory ASYNC = new ValueGetterFactory() { + ValueGetter get(ParameterImpl p) { + return ValueGetter.PLAIN; + } + }; + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/ws/client/sei/ValueSetterFactory.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,70 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.xml.internal.ws.client.sei; + +import com.sun.xml.internal.ws.model.ParameterImpl; + +import javax.xml.ws.WebServiceException; + +/** + * {@link ValueSetterFactory} is used to create {@link ValueSetter}. + * + * @author Jitendra Kotamraju + */ +abstract class ValueSetterFactory { + + abstract ValueSetter get(ParameterImpl p); + + static final ValueSetterFactory SYNC = new ValueSetterFactory() { + ValueSetter get(ParameterImpl p) { + return ValueSetter.getSync(p); + } + }; + + static final ValueSetterFactory NONE = new ValueSetterFactory() { + ValueSetter get(ParameterImpl p) { + throw new WebServiceException("This shouldn't happen. No response parameters."); + } + }; + + static final ValueSetterFactory SINGLE = new ValueSetterFactory() { + ValueSetter get(ParameterImpl p) { + return ValueSetter.SINGLE_VALUE; + } + }; + + static final class AsyncBeanValueSetterFactory extends ValueSetterFactory { + private Class asyncBean; + + AsyncBeanValueSetterFactory(Class asyncBean) { + this.asyncBean = asyncBean; + } + + ValueSetter get(ParameterImpl p) { + return new ValueSetter.AsyncBeanValueSetter(p, asyncBean); + } + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/ws/developer/BindingTypeFeature.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,55 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.xml.internal.ws.developer; + +import com.sun.xml.internal.ws.api.BindingID; + +import javax.xml.ws.WebServiceFeature; + +/** + * Using this feature, the application could override the binding used by + * the runtime(usually determined from WSDL). + * + * @author Jitendra Kotamraju + */ +public final class BindingTypeFeature extends WebServiceFeature { + + public static final String ID = "http://jax-ws.dev.java.net/features/binding"; + + private final String bindingId; + + public BindingTypeFeature(String bindingId) { + this.bindingId = bindingId; + } + + public String getID() { + return ID; + } + + public String getBindingId() { + return bindingId; + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/ws/developer/JAXBContextFactory.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,101 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.xml.internal.ws.developer; + +import com.sun.istack.internal.NotNull; +import com.sun.xml.internal.bind.api.JAXBRIContext; +import com.sun.xml.internal.bind.api.TypeReference; +import com.sun.xml.internal.ws.api.model.SEIModel; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBException; +import java.util.List; + +/** + * Factory to create {@link JAXBContext}. + * + * <p> + * JAX-WS uses JAXB to perform databinding when you use the service endpoint interface, and normally + * the JAX-WS RI drives JAXB and creates a necessary {@link JAXBContext} automatically. + * + * <p> + * This annotation is a JAX-WS RI vendor-specific feature, which lets applications create {@link JAXBRIContext} + * (which is the JAXB RI's {@link JAXBContext} implementation.) + * Combined with the JAXB RI vendor extensions defined in {@link JAXBRIContext}, appliation can use this to + * fine-tune how the databinding happens, such as by adding more classes to the binding context, + * by controlling the namespace mappings, and so on. + * + * <p> + * Applications should either use {@link UsesJAXBContextFeature} or {@link UsesJAXBContext} to instruct + * the JAX-WS runtime to use a custom factory. + * + * @author Kohsuke Kawaguchi + * @since 2.1.5 + */ +public interface JAXBContextFactory { + /** + * Called by the JAX-WS runtime to create a {@link JAXBRIContext} for the given SEI. + * + * @param sei + * The {@link SEIModel} object being constructed. This object provides you access to + * what SEI is being processed, and therefore useful if you are writing a generic + * {@link JAXBContextFactory} that can work with arbitrary SEI classes. + * + * @param classesToBind + * List of classes that needs to be bound by JAXB. This value is computed according to + * the JAX-WS spec and given to you. + * + * The calling JAX-WS runtime expects the returned {@link JAXBRIContext} to be capable of + * handling all these classes, but you can add more (which is more common), or remove some + * (if you know what you are doing.) + * + * The callee is free to mutate this list. + * + * @param typeReferences + * List of {@link TypeReference}s, which is also a part of the input to the JAXB RI to control + * how the databinding happens. Most likely this will be just a pass-through to the + * {@link JAXBRIContext#newInstance} method. + * + * @return + * A non-null valid {@link JAXBRIContext} object. + * + * @throws JAXBException + * If the callee encounters a fatal problem and wants to abort the JAX-WS runtime processing + * of the given SEI, throw a {@link JAXBException}. This will cause the port instantiation + * to fail (if on client), or the application deployment to fail (if on server.) + */ + @NotNull JAXBRIContext createJAXBContext(@NotNull SEIModel sei, @NotNull List<Class> classesToBind, @NotNull List<TypeReference> typeReferences) throws JAXBException; + + /** + * The default implementation that creates {@link JAXBRIContext} according to the standard behavior. + */ + public static final JAXBContextFactory DEFAULT = new JAXBContextFactory() { + @NotNull + public JAXBRIContext createJAXBContext(@NotNull SEIModel sei, @NotNull List<Class> classesToBind, @NotNull List<TypeReference> typeReferences) throws JAXBException { + return JAXBRIContext.newInstance(classesToBind.toArray(new Class[classesToBind.size()]), + typeReferences, null, sei.getTargetNamespace(), false, null); + } + }; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/ws/developer/SchemaValidation.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,92 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.xml.internal.ws.developer; + +import com.sun.xml.internal.ws.server.DraconianValidationErrorHandler; + +import javax.jws.WebService; +import javax.xml.transform.Source; +import javax.xml.validation.Schema; +import javax.xml.ws.spi.WebServiceFeatureAnnotation; +import java.lang.annotation.Documented; +import static java.lang.annotation.ElementType.TYPE; +import java.lang.annotation.Retention; +import static java.lang.annotation.RetentionPolicy.RUNTIME; +import java.lang.annotation.Target; + +/** + * Validates all request and response messages payload(SOAP:Body) for a {@link WebService} + * against the XML schema. To use this feature, annotate the endpoint class with + * this annotation. + * + * <pre> + * for e.g.: + * + * @WebService + * @SchemaValidation + * public class HelloImpl { + * ... + * } + * </pre> + * + * At present, schema validation works for doc/lit web services only. + * + * @since JAX-WS 2.1.3 + * @author Jitendra Kotamraju + * @see SchemaValidationFeature + */ +@Retention(RUNTIME) +@Target(TYPE) +@Documented +@WebServiceFeatureAnnotation(id = SchemaValidationFeature.ID, bean = SchemaValidationFeature.class) +public @interface SchemaValidation { + + /** + * Configure the validation behaviour w.r.t error handling. The default handler + * just rejects any invalid schema intances. If the application want to change + * this default behaviour(say just log the errors), it can do so by providing + * a custom implementation of {@link ValidationErrorHandler}. + */ + Class<? extends ValidationErrorHandler> handler() default DraconianValidationErrorHandler.class; + + /** + * Does validation for bound headers in a SOAP message. + * + boolean headers() default false; + */ + + /** + * Additional schema documents that are used to create {@link Schema} object. Useful + * when the application adds additional SOAP headers to the message. This is a list + * of system-ids, that are used to create {@link Source} objects and used in creation + * of {@link Schema} object + * + * for e.g.: + * @SchemaValidation(schemaLocations={"http://bar.foo/b.xsd", "http://foo.bar/a.xsd"} + * + String[] schemaLocations() default {}; + */ + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/ws/developer/SchemaValidationFeature.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,74 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.xml.internal.ws.developer; + +import com.sun.xml.internal.ws.api.FeatureConstructor; +import com.sun.xml.internal.ws.server.DraconianValidationErrorHandler; + +import javax.xml.ws.WebServiceFeature; + + +/** + * {@link WebServiceFeature} for schema validation. + * + * @since JAX-WS 2.1.3 + * @author Jitendra Kotamraju + * @see SchemaValidation + */ +public class SchemaValidationFeature extends WebServiceFeature { + /** + * Constant value identifying the SchemaValidationFeature + */ + public static final String ID = "http://jax-ws.dev.java.net/features/schema-validation"; + + private Class<? extends ValidationErrorHandler> clazz; + + public SchemaValidationFeature() { + this(DraconianValidationErrorHandler.class); + } + + /** + * Create an <code>SchemaValidationFeature</code>. + * The instance created will be enabled. + */ + @FeatureConstructor({"handler"}) + public SchemaValidationFeature(Class<? extends ValidationErrorHandler> clazz) { + this.enabled = true; + this.clazz = clazz; + } + + public String getID() { + return ID; + } + + /** + * Invalid schema instances are rejected, a SOAP fault message is created + * for any invalid request and response message. If it is set to false, schema + * validation messages are just logged. + */ + public Class<? extends ValidationErrorHandler> getErrorHandler() { + return clazz; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/ws/developer/StreamingAttachment.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,76 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.xml.internal.ws.developer; + +import javax.xml.ws.spi.WebServiceFeatureAnnotation; +import java.lang.annotation.*; +import java.io.File; + +/** + * This feature represents the use of StreamingAttachment attachments with a + * web service. + * + * <p> + * for e.g.: To keep all MIME attachments in memory, do the following + * + * <pre> + * @WebService + * @MIME(memoryThreshold=-1L) + * public class HelloService { + * } + * </pre> + * + * @see StreamingAttachmentFeature + * + * @author Jitendra Kotamraju + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +@Documented +@WebServiceFeatureAnnotation(id = StreamingAttachmentFeature.ID, bean = StreamingAttachmentFeature.class) +public @interface StreamingAttachment { + + /** + * Directory in which large attachments are stored. {@link File#createTempFile} + * methods are used to create temp files for storing attachments. This + * value is used in {@link File#createTempFile}, if specified. If a file + * cannot be created in this dir, then all the content is kept in memory. + */ + String dir() default ""; + + /** + * MIME message is parsed eagerly. + */ + boolean parseEagerly() default false; + + /** + * After this threshold(no of bytes per attachment), large attachment is + * written to file system. + * + * If the value is -1, then all the attachment content is kept in memory. + */ + long memoryThreshold() default 1048576L; + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/ws/developer/StreamingAttachmentFeature.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,117 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.xml.internal.ws.developer; + +import com.sun.xml.internal.ws.api.FeatureConstructor; +import com.sun.istack.internal.Nullable; + +import javax.xml.ws.WebServiceFeature; + +import com.sun.xml.internal.org.jvnet.mimepull.MIMEConfig; + +/** + * Proxy needs to be created with this feature to configure StreamingAttachment + * attachments behaviour. + * + * <pre> + * for e.g.: To configure all StreamingAttachment attachments to be kept in memory + * <p> + * + * StreamingAttachmentFeature feature = new StreamingAttachmentFeature(); + * feature.setAllMemory(true); + * + * proxy = HelloService().getHelloPort(feature); + * + * </pre> + * + * @author Jitendra Kotamraju + */ +public final class StreamingAttachmentFeature extends WebServiceFeature { + /** + * Constant value identifying the {@link @StreamingAttachment} feature. + */ + public static final String ID = "http://jax-ws.dev.java.net/features/mime"; + + private MIMEConfig config; + + private String dir; + private boolean parseEagerly; + private long memoryThreshold; + + public StreamingAttachmentFeature() { + } + + @FeatureConstructor({"dir","parseEagerly","memoryThreshold"}) + public StreamingAttachmentFeature(@Nullable String dir, boolean parseEagerly, long memoryThreshold) { + this.enabled = true; + this.dir = dir; + this.parseEagerly = parseEagerly; + this.memoryThreshold = memoryThreshold; + } + + public String getID() { + return ID; + } + + /** + * Returns the configuration object. Once this is called, you cannot + * change the configuration. + * + * @return + */ + public MIMEConfig getConfig() { + if (config == null) { + config = new MIMEConfig(); + config.setDir(dir); + config.setParseEagerly(parseEagerly); + config.setMemoryThreshold(memoryThreshold); + config.validate(); + } + return config; + } + + /** + * Directory in which large attachments are stored + */ + public void setDir(String dir) { + this.dir = dir; + } + + /** + * StreamingAttachment message is parsed eagerly + */ + public void setParseEagerly(boolean parseEagerly) { + this.parseEagerly = parseEagerly; + } + + /** + * After this threshold(no of bytes), large attachments are + * written to file system + */ + public void setMemoryThreshold(int memoryThreshold) { + this.memoryThreshold = memoryThreshold; + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/ws/developer/StreamingDataHandler.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,69 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.xml.internal.ws.developer; + +import com.sun.xml.internal.org.jvnet.mimepull.MIMEPart; + +import javax.activation.DataSource; +import java.io.InputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.io.File; +import java.net.URL; + +/** + * Implementation of {@link com.sun.xml.internal.org.jvnet.staxex.StreamingDataHandler} to access MIME + * attachments efficiently. Applications can use the additional methods and decide + * on how to access the attachment data in JAX-WS applications. + * + * <p> + * for e.g.: + * + * DataHandler dh = proxy.getData(); + * StreamingDataHandler sdh = (StreamingDataHandler)dh; + * // readOnce() doesn't store attachment on the disk in some cases + * // for e.g when only one huge attachment after soap envelope part in MIME message + * InputStream in = sdh.readOnce(); + * ... + * in.close(); + * sdh.close(); + * + * @author Jitendra Kotamraju + */ +public abstract class StreamingDataHandler extends com.sun.xml.internal.org.jvnet.staxex.StreamingDataHandler { + + public StreamingDataHandler(Object o, String s) { + super(o, s); + } + + public StreamingDataHandler(URL url) { + super(url); + } + + public StreamingDataHandler(DataSource dataSource) { + super(dataSource); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/ws/developer/UsesJAXBContext.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,68 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.xml.internal.ws.developer; + +import javax.xml.ws.spi.WebServiceFeatureAnnotation; +import javax.xml.bind.JAXBContext; +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * This feature instructs that the specified {@link JAXBContextFactory} be used for performing + * data-binding for the SEI. + * + * <p> + * For example, + * <pre> + * @WebService + * @UsesJAXBContext(MyJAXBContextFactory.class) + * public class HelloService { + * ... + * } + * </pre> + * + * <p> + * If your {@link JAXBContextFactory} needs to carry some state from your calling application, + * you can use {@link UsesJAXBContextFeature} to pass in an instance of {@link JAXBContextFactory}, + * instead of using this to specify the type. + * + * @author Kohsuke Kawaguchi + * @since 2.1.5 + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@WebServiceFeatureAnnotation(id=UsesJAXBContextFeature.ID,bean=UsesJAXBContextFeature.class) +public @interface UsesJAXBContext { + /** + * Designates the {@link JAXBContextFactory} to be used to create the {@link JAXBContext} object, + * which in turn will be used by the JAX-WS runtime to marshal/unmarshal parameters and return + * values to/from XML. + */ + Class<? extends JAXBContextFactory> value(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/ws/developer/UsesJAXBContextFeature.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,124 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.xml.internal.ws.developer; + +import com.sun.xml.internal.ws.api.FeatureConstructor; +import com.sun.xml.internal.ws.api.model.SEIModel; +import com.sun.xml.internal.bind.api.JAXBRIContext; +import com.sun.xml.internal.bind.api.TypeReference; +import com.sun.istack.internal.NotNull; +import com.sun.istack.internal.Nullable; + +import javax.xml.ws.WebServiceFeature; +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBException; +import java.lang.reflect.InvocationTargetException; +import java.util.List; + +/** + * A {@link WebServiceFeature} that instructs the JAX-WS runtime to use a specific {@link JAXBContextFactory} + * instance of creating {@link JAXBContext}. + * + * @see UsesJAXBContext + * @since 2.1.5 + * @author Kohsuke Kawaguchi + */ +public class UsesJAXBContextFeature extends WebServiceFeature { + /** + * Constant value identifying the {@link UsesJAXBContext} feature. + */ + public static final String ID = "http://jax-ws.dev.java.net/features/uses-jaxb-context"; + + private final JAXBContextFactory factory; + + /** + * Creates {@link UsesJAXBContextFeature}. + * + * @param factoryClass + * This class has to have a public no-arg constructor, which will be invoked to create + * a new instance. {@link JAXBContextFactory#createJAXBContext(SEIModel, List, List)} will + * be then called to create {@link JAXBContext}. + */ + @FeatureConstructor("value") + public UsesJAXBContextFeature(@NotNull Class<? extends JAXBContextFactory> factoryClass) { + try { + factory = factoryClass.getConstructor().newInstance(); + } catch (InstantiationException e) { + Error x = new InstantiationError(e.getMessage()); + x.initCause(e); + throw x; + } catch (IllegalAccessException e) { + Error x = new IllegalAccessError(e.getMessage()); + x.initCause(e); + throw x; + } catch (InvocationTargetException e) { + Error x = new InstantiationError(e.getMessage()); + x.initCause(e); + throw x; + } catch (NoSuchMethodException e) { + Error x = new NoSuchMethodError(e.getMessage()); + x.initCause(e); + throw x; + } + } + + /** + * Creates {@link UsesJAXBContextFeature}. + * This version allows {@link JAXBContextFactory} to carry application specific state. + * + * @param factory + * Uses a specific instance of {@link JAXBContextFactory} to create {@link JAXBContext}. + */ + public UsesJAXBContextFeature(@Nullable JAXBContextFactory factory) { + this.factory = factory; + } + + /** + * Creates {@link UsesJAXBContextFeature}. + * This version allows you to create {@link JAXBRIContext} upfront and uses it. + */ + public UsesJAXBContextFeature(@Nullable final JAXBRIContext context) { + this.factory = new JAXBContextFactory() { + @NotNull + public JAXBRIContext createJAXBContext(@NotNull SEIModel sei, @NotNull List<Class> classesToBind, @NotNull List<TypeReference> typeReferences) throws JAXBException { + return context; + } + }; + } + + /** + * Gets the {@link JAXBContextFactory} instance to be used for creating {@link JAXBContext} for SEI. + * + * @return + * null if the default {@link JAXBContext} shall be used. + */ + public @Nullable JAXBContextFactory getFactory() { + return factory; + } + + public String getID() { + return ID; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/ws/developer/ValidationErrorHandler.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,58 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.xml.internal.ws.developer; + +import com.sun.xml.internal.ws.api.message.Packet; +import org.xml.sax.ErrorHandler; + +import javax.xml.ws.handler.MessageContext; +import javax.xml.validation.Validator; + +/** + * An {@link ErrorHandler} to receive errors encountered during the + * {@link Validator#validate} method invocation. Specify + * a custom handler in {@link SchemaValidation}, {@link SchemaValidationFeature} + * to customize the error handling process during validaiton. + * + * @see SchemaValidation + * @author Jitendra Kotamraju + */ +public abstract class ValidationErrorHandler implements ErrorHandler { + protected Packet packet; + + /** + * Use it to communicate validation errors with the application. + * + * For e.g validation exceptions can be stored in {@link Packet#invocationProperties} + * during request processing and can be accessed in the endpoint + * via {@link MessageContext} + * + * @param packet for request or response message + */ + public void setPacket(Packet packet) { + this.packet = packet; + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/ws/encoding/ContentType.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,136 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +/* + * @(#)ContentType.java 1.7 02/03/27 + */ + + + +package com.sun.xml.internal.ws.encoding; + +import javax.xml.ws.WebServiceException; + +/** + * This class represents a MIME ContentType value. It provides + * methods to parse a ContentType string into individual components + * and to generate a MIME style ContentType string. + * + * @version 1.7, 02/03/27 + * @author John Mani + */ +public final class ContentType { + + private String primaryType; // primary type + private String subType; // subtype + private ParameterList list; // parameter list + + /** + * Constructor that takes a Content-Type string. The String + * is parsed into its constituents: primaryType, subType + * and parameters. A ParseException is thrown if the parse fails. + * + * @param s the Content-Type string. + * @exception WebServiceException if the parse fails. + */ + public ContentType(String s) throws WebServiceException { + HeaderTokenizer h = new HeaderTokenizer(s, HeaderTokenizer.MIME); + HeaderTokenizer.Token tk; + + // First "type" .. + tk = h.next(); + if (tk.getType() != HeaderTokenizer.Token.ATOM) + throw new WebServiceException(); + primaryType = tk.getValue(); + + // The '/' separator .. + tk = h.next(); + if ((char)tk.getType() != '/') + throw new WebServiceException(); + + // Then "subType" .. + tk = h.next(); + if (tk.getType() != HeaderTokenizer.Token.ATOM) + throw new WebServiceException(); + subType = tk.getValue(); + + // Finally parameters .. + String rem = h.getRemainder(); + if (rem != null) + list = new ParameterList(rem); + } + + + /** + * Return the primary type. + * @return the primary type + */ + public String getPrimaryType() { + return primaryType; + } + + /** + * Return the subType. + * @return the subType + */ + public String getSubType() { + return subType; + } + + /** + * Return the MIME type string, without the parameters. + * The returned value is basically the concatenation of + * the primaryType, the '/' character and the secondaryType. + * + * @return the type + */ + public String getBaseType() { + return primaryType + '/' + subType; + } + + /** + * Return the specified parameter value. Returns <code>null</code> + * if this parameter is absent. + * + * @param name parameter name + * @return parameter value + */ + public String getParameter(String name) { + if (list == null) + return null; + + return list.get(name); + } + + /** + * Return a ParameterList object that holds all the available + * parameters. Returns null if no parameters are available. + * + * @return ParameterList + */ + public ParameterList getParameterList() { + return list; + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/ws/encoding/DataSourceStreamingDataHandler.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,63 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.xml.internal.ws.encoding; + +import com.sun.xml.internal.org.jvnet.mimepull.MIMEPart; + +import javax.activation.DataSource; +import java.io.*; + +import com.sun.xml.internal.ws.developer.StreamingDataHandler; + +/** + * @author Jitendra Kotamraju + */ +public class DataSourceStreamingDataHandler extends StreamingDataHandler { + + public DataSourceStreamingDataHandler(DataSource ds) { + super(ds); + } + + public InputStream readOnce() throws IOException { + return getInputStream(); + } + + public void moveTo(File file) throws IOException { + InputStream in = getInputStream(); + OutputStream os = new FileOutputStream(file); + byte[] temp = new byte[8192]; + int len; + while((len=in.read(temp)) != -1) { + os.write(temp, 0, len); + } + in.close(); + os.close(); + } + + public void close() throws IOException { + // nothing to do here + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/ws/encoding/HeaderTokenizer.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,382 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +/* + * @(#)HeaderTokenizer.java 1.9 02/03/27 + */ + + + +package com.sun.xml.internal.ws.encoding; + +import javax.xml.ws.WebServiceException; + +/** + * This class tokenizes RFC822 and MIME headers into the basic + * symbols specified by RFC822 and MIME. <p> + * + * This class handles folded headers (ie headers with embedded + * CRLF SPACE sequences). The folds are removed in the returned + * tokens. + * + * @version 1.9, 02/03/27 + * @author John Mani + */ + +class HeaderTokenizer { + + /** + * The Token class represents tokens returned by the + * HeaderTokenizer. + */ + static class Token { + + private int type; + private String value; + + /** + * Token type indicating an ATOM. + */ + public static final int ATOM = -1; + + /** + * Token type indicating a quoted string. The value + * field contains the string without the quotes. + */ + public static final int QUOTEDSTRING = -2; + + /** + * Token type indicating a comment. The value field + * contains the comment string without the comment + * start and end symbols. + */ + public static final int COMMENT = -3; + + /** + * Token type indicating end of input. + */ + public static final int EOF = -4; + + /** + * Constructor. + * @param type Token type + * @param value Token value + */ + public Token(int type, String value) { + this.type = type; + this.value = value; + } + + /** + * Return the type of the token. If the token represents a + * delimiter or a control character, the type is that character + * itself, converted to an integer. Otherwise, it's value is + * one of the following: + * <ul> + * <li><code>ATOM</code> A sequence of ASCII characters + * delimited by either SPACE, CTL, "(", <"> or the + * specified SPECIALS + * <li><code>QUOTEDSTRING</code> A sequence of ASCII characters + * within quotes + * <li><code>COMMENT</code> A sequence of ASCII characters + * within "(" and ")". + * <li><code>EOF</code> End of header + * </ul> + */ + public int getType() { + return type; + } + + /** + * Returns the value of the token just read. When the current + * token is a quoted string, this field contains the body of the + * string, without the quotes. When the current token is a comment, + * this field contains the body of the comment. + * + * @return token value + */ + public String getValue() { + return value; + } + } + + private String string; // the string to be tokenized + private boolean skipComments; // should comments be skipped ? + private String delimiters; // delimiter string + private int currentPos; // current parse position + private int maxPos; // string length + private int nextPos; // track start of next Token for next() + private int peekPos; // track start of next Token for peek() + + /** + * RFC822 specials + */ + private final static String RFC822 = "()<>@,;:\\\"\t .[]"; + + /** + * MIME specials + */ + final static String MIME = "()<>@,;:\\\"\t []/?="; + + // The EOF Token + private final static Token EOFToken = new Token(Token.EOF, null); + + /** + * Constructor that takes a rfc822 style header. + * + * @param header The rfc822 header to be tokenized + * @param delimiters Set of delimiter characters + * to be used to delimit ATOMS. These + * are usually <code>RFC822</code> or + * <code>MIME</code> + * @param skipComments If true, comments are skipped and + * not returned as tokens + */ + HeaderTokenizer(String header, String delimiters, + boolean skipComments) { + string = (header == null) ? "" : header; // paranoia ?! + this.skipComments = skipComments; + this.delimiters = delimiters; + currentPos = nextPos = peekPos = 0; + maxPos = string.length(); + } + + /** + * Constructor. Comments are ignored and not returned as tokens + * + * @param header The header that is tokenized + * @param delimiters The delimiters to be used + */ + HeaderTokenizer(String header, String delimiters) { + this(header, delimiters, true); + } + + /** + * Constructor. The RFC822 defined delimiters - RFC822 - are + * used to delimit ATOMS. Also comments are skipped and not + * returned as tokens + */ + HeaderTokenizer(String header) { + this(header, RFC822); + } + + /** + * Parses the next token from this String. <p> + * + * Clients sit in a loop calling next() to parse successive + * tokens until an EOF Token is returned. + * + * @return the next Token + * @exception WebServiceException if the parse fails + */ + Token next() throws WebServiceException { + Token tk; + + currentPos = nextPos; // setup currentPos + tk = getNext(); + nextPos = peekPos = currentPos; // update currentPos and peekPos + return tk; + } + + /** + * Peek at the next token, without actually removing the token + * from the parse stream. Invoking this method multiple times + * will return successive tokens, until <code>next()</code> is + * called. <p> + * + * @return the next Token + * @exception WebServiceException if the parse fails + */ + Token peek() throws WebServiceException { + Token tk; + + currentPos = peekPos; // setup currentPos + tk = getNext(); + peekPos = currentPos; // update peekPos + return tk; + } + + /** + * Return the rest of the Header. + * + * @return String rest of header. null is returned if we are + * already at end of header + */ + String getRemainder() { + return string.substring(nextPos); + } + + /* + * Return the next token starting from 'currentPos'. After the + * parse, 'currentPos' is updated to point to the start of the + * next token. + */ + private Token getNext() throws WebServiceException { + // If we're already at end of string, return EOF + if (currentPos >= maxPos) + return EOFToken; + + // Skip white-space, position currentPos beyond the space + if (skipWhiteSpace() == Token.EOF) + return EOFToken; + + char c; + int start; + boolean filter = false; + + c = string.charAt(currentPos); + + // Check or Skip comments and position currentPos + // beyond the comment + while (c == '(') { + // Parsing comment .. + int nesting; + for (start = ++currentPos, nesting = 1; + nesting > 0 && currentPos < maxPos; + currentPos++) { + c = string.charAt(currentPos); + if (c == '\\') { // Escape sequence + currentPos++; // skip the escaped character + filter = true; + } else if (c == '\r') + filter = true; + else if (c == '(') + nesting++; + else if (c == ')') + nesting--; + } + if (nesting != 0) + throw new WebServiceException("Unbalanced comments"); + + if (!skipComments) { + // Return the comment, if we are asked to. + // Note that the comment start & end markers are ignored. + String s; + if (filter) // need to go thru the token again. + s = filterToken(string, start, currentPos-1); + else + s = string.substring(start,currentPos-1); + + return new Token(Token.COMMENT, s); + } + + // Skip any whitespace after the comment. + if (skipWhiteSpace() == Token.EOF) + return EOFToken; + c = string.charAt(currentPos); + } + + // Check for quoted-string and position currentPos + // beyond the terminating quote + if (c == '"') { + for (start = ++currentPos; currentPos < maxPos; currentPos++) { + c = string.charAt(currentPos); + if (c == '\\') { // Escape sequence + currentPos++; + filter = true; + } else if (c == '\r') + filter = true; + else if (c == '"') { + currentPos++; + String s; + + if (filter) + s = filterToken(string, start, currentPos-1); + else + s = string.substring(start,currentPos-1); + + return new Token(Token.QUOTEDSTRING, s); + } + } + throw new WebServiceException("Unbalanced quoted string"); + } + + // Check for SPECIAL or CTL + if (c < 040 || c >= 0177 || delimiters.indexOf(c) >= 0) { + currentPos++; // re-position currentPos + char ch[] = new char[1]; + ch[0] = c; + return new Token((int)c, new String(ch)); + } + + // Check for ATOM + for (start = currentPos; currentPos < maxPos; currentPos++) { + c = string.charAt(currentPos); + // ATOM is delimited by either SPACE, CTL, "(", <"> + // or the specified SPECIALS + if (c < 040 || c >= 0177 || c == '(' || c == ' ' || + c == '"' || delimiters.indexOf(c) >= 0) + break; + } + return new Token(Token.ATOM, string.substring(start, currentPos)); + } + + // Skip SPACE, HT, CR and NL + private int skipWhiteSpace() { + char c; + for (; currentPos < maxPos; currentPos++) + if (((c = string.charAt(currentPos)) != ' ') && + (c != '\t') && (c != '\r') && (c != '\n')) + return currentPos; + return Token.EOF; + } + + /* Process escape sequences and embedded LWSPs from a comment or + * quoted string. + */ + private static String filterToken(String s, int start, int end) { + StringBuffer sb = new StringBuffer(); + char c; + boolean gotEscape = false; + boolean gotCR = false; + + for (int i = start; i < end; i++) { + c = s.charAt(i); + if (c == '\n' && gotCR) { + // This LF is part of an unescaped + // CRLF sequence (i.e, LWSP). Skip it. + gotCR = false; + continue; + } + + gotCR = false; + if (!gotEscape) { + // Previous character was NOT '\' + if (c == '\\') // skip this character + gotEscape = true; + else if (c == '\r') // skip this character + gotCR = true; + else // append this character + sb.append(c); + } else { + // Previous character was '\'. So no need to + // bother with any special processing, just + // append this character + sb.append(c); + gotEscape = false; + } + } + return sb.toString(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/ws/encoding/ImageDataContentHandler.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,164 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + + +package com.sun.xml.internal.ws.encoding; + +import javax.activation.DataContentHandler; +import javax.activation.ActivationDataFlavor; +import javax.activation.DataSource; +import javax.imageio.ImageIO; +import javax.imageio.ImageWriter; +import javax.imageio.stream.ImageOutputStream; +import java.awt.*; +import java.awt.image.BufferedImage; +import java.awt.datatransfer.DataFlavor; +import java.util.logging.Logger; +import java.util.Iterator; +import java.io.IOException; +import java.io.BufferedInputStream; +import java.io.OutputStream; + +/** + * @author Jitendra Kotamraju + */ + +public class ImageDataContentHandler extends Component + implements DataContentHandler { + + private static final Logger log = Logger.getLogger(ImageDataContentHandler.class.getName()); + private final DataFlavor[] flavor; + + public ImageDataContentHandler() { + String[] mimeTypes = ImageIO.getReaderMIMETypes(); + flavor = new DataFlavor[mimeTypes.length]; + for(int i=0; i < mimeTypes.length; i++) { + flavor[i] = new ActivationDataFlavor(Image.class, mimeTypes[i], "Image"); + } + } + + /** + * Returns an array of DataFlavor objects indicating the flavors the + * data can be provided in. The array should be ordered according to + * preference for providing the data (from most richly descriptive to + * least descriptive). + * + * @return The DataFlavors. + */ + public DataFlavor[] getTransferDataFlavors() { + return flavor; + } + + /** + * Returns an object which represents the data to be transferred. + * The class of the object returned is defined by the representation class + * of the flavor. + * + * @param df The DataFlavor representing the requested type. + * @param ds The DataSource representing the data to be converted. + * @return The constructed Object. + */ + public Object getTransferData(DataFlavor df, DataSource ds) + throws IOException { + for (DataFlavor aFlavor : flavor) { + if (aFlavor.equals(df)) { + return getContent(ds); + } + } + return null; + } + + /** + * Return an object representing the data in its most preferred form. + * Generally this will be the form described by the first DataFlavor + * returned by the <code>getTransferDataFlavors</code> method. + * + * @param ds The DataSource representing the data to be converted. + * @return The constructed Object. + */ + public Object getContent(DataSource ds) throws IOException { + return ImageIO.read(new BufferedInputStream(ds.getInputStream())); + } + + /** + * Convert the object to a byte stream of the specified MIME type + * and write it to the output stream. + * + * @param obj The object to be converted. + * @param type The requested MIME type of the resulting byte stream. + * @param os The output stream into which to write the converted + * byte stream. + */ + + public void writeTo(Object obj, String type, OutputStream os) + throws IOException { + + try { + BufferedImage bufImage; + if (obj instanceof BufferedImage) { + bufImage = (BufferedImage)obj; + } else if (obj instanceof Image) { + bufImage = render((Image)obj); + } else { + throw new IOException( + "ImageDataContentHandler requires Image object, " + + "was given object of type " + + obj.getClass().toString()); + } + ImageWriter writer = null; + Iterator<ImageWriter> i = ImageIO.getImageWritersByMIMEType(type); + if (i.hasNext()) { + writer = i.next(); + } + if (writer != null) { + ImageOutputStream stream = ImageIO.createImageOutputStream(os); + writer.setOutput(stream); + writer.write(bufImage); + writer.dispose(); + stream.close(); + } else { + throw new IOException("Unsupported mime type:"+ type); + } + } catch (Exception e) { + throw new IOException("Unable to encode the image to a stream " + + e.getMessage()); + } + } + + + private BufferedImage render(Image img) throws InterruptedException { + + MediaTracker tracker = new MediaTracker(this); + tracker.addImage(img, 0); + tracker.waitForAll(); + BufferedImage bufImage = new BufferedImage(img.getWidth(null), + img.getHeight(null), BufferedImage.TYPE_INT_RGB); + Graphics g = bufImage.createGraphics(); + g.drawImage(img, 0, 0, null); + g.dispose(); + return bufImage; + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/ws/encoding/MIMEPartStreamingDataHandler.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,129 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.xml.internal.ws.encoding; + +import com.sun.xml.internal.org.jvnet.mimepull.MIMEPart; + +import javax.activation.DataSource; +import java.io.InputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.io.File; + +import com.sun.xml.internal.ws.developer.StreamingDataHandler; + +/** + * Implementation of {@link StreamingDataHandler} to access MIME + * attachments efficiently. Applications can use the additional methods and decide + * on how to access the attachment data in JAX-WS applications. + * + * <p> + * for e.g.: + * + * DataHandler dh = proxy.getData(); + * StreamingDataHandler sdh = (StreamingDataHandler)dh; + * // readOnce() doesn't store attachment on the disk in some cases + * // for e.g when only one huge attachment after soap envelope part in MIME message + * InputStream in = sdh.readOnce(); + * ... + * in.close(); + * sdh.close(); + * + * @author Jitendra Kotamraju + */ +public class MIMEPartStreamingDataHandler extends StreamingDataHandler { + private final StreamingDataSource ds; + + public MIMEPartStreamingDataHandler(MIMEPart part) { + super(new StreamingDataSource(part)); + ds = (StreamingDataSource)getDataSource(); + } + + public InputStream readOnce() throws IOException { + return ds.readOnce(); + } + + public void moveTo(File file) throws IOException { + ds.moveTo(file); + } + + public void close() throws IOException { + ds.close(); + } + + private static final class StreamingDataSource implements DataSource { + private final MIMEPart part; + + StreamingDataSource(MIMEPart part) { + this.part = part; + } + + public InputStream getInputStream() throws IOException { + return part.read(); //readOnce() ?? + } + + InputStream readOnce() throws IOException { + try { + return part.readOnce(); + } catch(Exception e) { + throw new MyIOException(e); + } + } + + void moveTo(File file) throws IOException { + part.moveTo(file); + } + + public OutputStream getOutputStream() throws IOException { + return null; + } + + public String getContentType() { + return part.getContentType(); + } + + public String getName() { + return ""; + } + + public void close() throws IOException { + part.close(); + } + } + + private static final class MyIOException extends IOException { + private final Exception linkedException; + + MyIOException(Exception linkedException) { + this.linkedException = linkedException; + } + + @Override + public Throwable getCause() { + return linkedException; + } + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/ws/encoding/ParameterList.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,138 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.xml.internal.ws.encoding; + + + + +/* + * @(#)ParameterList.java 1.10 03/02/12 + */ + + +import javax.xml.ws.WebServiceException; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +/** + * This class holds MIME parameters (attribute-value pairs). + * + * @version 1.10, 03/02/12 + * @author John Mani + */ + +final class ParameterList { + + private final Map<String, String> list; + + /** + * Constructor that takes a parameter-list string. The String + * is parsed and the parameters are collected and stored internally. + * A ParseException is thrown if the parse fails. + * Note that an empty parameter-list string is valid and will be + * parsed into an empty ParameterList. + * + * @param s the parameter-list string. + * @exception WebServiceException if the parse fails. + */ + ParameterList(String s) { + HeaderTokenizer h = new HeaderTokenizer(s, HeaderTokenizer.MIME); + HeaderTokenizer.Token tk; + int type; + String name; + + list = new HashMap<String, String>(); + while (true) { + tk = h.next(); + type = tk.getType(); + + if (type == HeaderTokenizer.Token.EOF) // done + return; + + if ((char)type == ';') { + // expect parameter name + tk = h.next(); + // tolerate trailing semicolon, even though it violates the spec + if (tk.getType() == HeaderTokenizer.Token.EOF) + return; + // parameter name must be a MIME Atom + if (tk.getType() != HeaderTokenizer.Token.ATOM) + throw new WebServiceException(); + name = tk.getValue().toLowerCase(); + + // expect '=' + tk = h.next(); + if ((char)tk.getType() != '=') + throw new WebServiceException(); + + // expect parameter value + tk = h.next(); + type = tk.getType(); + // parameter value must be a MIME Atom or Quoted String + if (type != HeaderTokenizer.Token.ATOM && + type != HeaderTokenizer.Token.QUOTEDSTRING) + throw new WebServiceException(); + + list.put(name, tk.getValue()); + } else + throw new WebServiceException(); + } + } + + /** + * Return the number of parameters in this list. + * + * @return number of parameters. + */ + int size() { + return list.size(); + } + + /** + * Returns the value of the specified parameter. Note that + * parameter names are case-insensitive. + * + * @param name parameter name. + * @return Value of the parameter. Returns + * <code>null</code> if the parameter is not + * present. + */ + String get(String name) { + return list.get(name.trim().toLowerCase()); + } + + + /** + * Return an enumeration of the names of all parameters in this + * list. + * + * @return Enumeration of all parameter names in this list. + */ + Iterator<String> getNames() { + return list.keySet().iterator(); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/ws/encoding/RootOnlyCodec.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,71 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.xml.internal.ws.encoding; + +import com.sun.istack.internal.NotNull; +import com.sun.xml.internal.ws.api.message.AttachmentSet; +import com.sun.xml.internal.ws.api.message.Message; +import com.sun.xml.internal.ws.api.message.Packet; +import com.sun.xml.internal.ws.api.pipe.Codec; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.channels.ReadableByteChannel; + +/** + * {@link Codec} that works only on the root part of the MIME/multipart. + * It doesn't work on the attachment parts, so it takes {@link AttachmentSet} + * as an argument and creates a corresponding {@link Message}. This enables + * attachments to be parsed lazily by wrapping the mimepull parser into an + * {@link AttachmentSet} + * + * @author Jitendra Kotamraju + */ +public interface RootOnlyCodec extends Codec { + + /** + * Reads root part bytes from {@link InputStream} and constructs a {@link Message} + * along with the given attachments. + * + * @param in root part's data + * + * @param contentType root part's MIME content type (like "application/xml") + * + * @param packet the new created {@link Message} is set in this packet + * + * @param att attachments + * + * @throws IOException + * if {@link InputStream} throws an exception. + */ + void decode(@NotNull InputStream in, @NotNull String contentType, @NotNull Packet packet, @NotNull AttachmentSet att) + throws IOException; + + /** + * + * @see #decode(InputStream, String, Packet, AttachmentSet) + */ + void decode(@NotNull ReadableByteChannel in, @NotNull String contentType, @NotNull Packet packet, @NotNull AttachmentSet att); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/ws/encoding/StringDataContentHandler.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,148 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.xml.internal.ws.encoding; + +import javax.activation.ActivationDataFlavor; +import javax.activation.DataSource; +import javax.activation.DataContentHandler; +import java.awt.datatransfer.DataFlavor; +import java.io.*; + +/** + * JAF data content handler for text/plain --> String + * + * @author Anil Vijendran + */ +public class StringDataContentHandler implements DataContentHandler { + + /** + * return the DataFlavors for this <code>DataContentHandler</code> + * @return The DataFlavors. + */ + public DataFlavor[] getTransferDataFlavors() { // throws Exception; + DataFlavor flavors[] = new DataFlavor[2]; + flavors[0] = new ActivationDataFlavor(String.class, "text/plain", "text string"); + flavors[1] = new DataFlavor("text/plain", "Plain Text"); + return flavors; + } + + /** + * return the Transfer Data of type DataFlavor from InputStream + * @param df The DataFlavor. + * @param ds The InputStream corresponding to the data. + * @return The constructed Object. + */ + public Object getTransferData(DataFlavor df, DataSource ds) { + + // this is sort of hacky, but will work for the + // sake of testing... + if (df.getMimeType().startsWith("text/plain")) { + if (df + .getRepresentationClass() + .getName() + .equals("java.lang.String")) { + // spit out String + StringBuffer buf = new StringBuffer(); + char data[] = new char[1024]; + // InputStream is = null; + InputStreamReader isr = null; + int bytes_read = 0; + int total_bytes = 0; + + try { + isr = new InputStreamReader(ds.getInputStream()); + + while (true) { + bytes_read = isr.read(data); + if (bytes_read > 0) + buf.append(data, 0, bytes_read); + else + break; + total_bytes += bytes_read; + } + } catch (Exception e) { + } + + return buf.toString(); + + } else if ( + df.getRepresentationClass().getName().equals( + "java.io.InputStream")) { + // spit out InputStream + try { + return ds.getInputStream(); + } catch (Exception e) { + } + } + + } + return null; + } + + /** + * + */ + public Object getContent(DataSource ds) { // throws Exception; + StringBuffer buf = new StringBuffer(); + char data[] = new char[1024]; + // InputStream is = null; + InputStreamReader isr = null; + int bytes_read = 0; + int total_bytes = 0; + + try { + isr = new InputStreamReader(ds.getInputStream()); + + while (true) { + bytes_read = isr.read(data); + if (bytes_read > 0) + buf.append(data, 0, bytes_read); + else + break; + total_bytes += bytes_read; + } + } catch (Exception e) { + } + + return buf.toString(); + } + /** + * construct an object from a byte stream + * (similar semantically to previous method, we are deciding + * which one to support) + */ + public void writeTo(Object obj, String mimeType, OutputStream os) + throws IOException { + if (!mimeType.startsWith("text/plain")) + throw new IOException( + "Invalid type \"" + mimeType + "\" on StringDCH"); + + Writer out = new OutputStreamWriter(os); + out.write((String) obj); + out.flush(); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/ws/encoding/XmlDataContentHandler.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,114 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.xml.internal.ws.encoding; + +import com.sun.xml.internal.ws.util.xml.XmlUtil; + +import javax.activation.ActivationDataFlavor; +import javax.activation.DataContentHandler; +import javax.activation.DataSource; +import javax.xml.transform.Source; +import javax.xml.transform.Transformer; +import javax.xml.transform.stream.StreamResult; +import javax.xml.transform.stream.StreamSource; +import java.awt.datatransfer.DataFlavor; +import java.io.IOException; +import java.io.OutputStream; + + +/** + * JAF data handler for XML content + * + * @author Anil Vijendran + */ +public class XmlDataContentHandler implements DataContentHandler { + + private final DataFlavor[] flavors; + + public XmlDataContentHandler() throws ClassNotFoundException { + flavors = new DataFlavor[2]; + flavors[0] = new ActivationDataFlavor(StreamSource.class, "text/xml", "XML"); + flavors[1] = new ActivationDataFlavor(StreamSource.class, "application/xml", "XML"); + } + + /** + * return the DataFlavors for this <code>DataContentHandler</code> + * @return The DataFlavors. + */ + public DataFlavor[] getTransferDataFlavors() { // throws Exception; + return flavors; + } + + /** + * return the Transfer Data of type DataFlavor from InputStream + * @param df The DataFlavor. + * @param ds The InputStream corresponding to the data. + * @return The constructed Object. + */ + public Object getTransferData(DataFlavor df, DataSource ds) + throws IOException { + + for (DataFlavor aFlavor : flavors) { + if (aFlavor.equals(df)) { + return getContent(ds); + } + } + return null; + } + + /** + * + */ + public Object getContent(DataSource dataSource) throws IOException { + return new StreamSource(dataSource.getInputStream()); + } + + /** + * construct an object from a byte stream + * (similar semantically to previous method, we are deciding + * which one to support) + */ + public void writeTo(Object obj, String mimeType, OutputStream os) + throws IOException { + if (!mimeType.equals("text/xml") && !mimeType.equals("application/xml")) + throw new IOException( + "Invalid content type \"" + mimeType + "\" for XmlDCH"); + + try { + Transformer transformer = XmlUtil.newTransformer(); + StreamResult result = new StreamResult(os); + if (obj instanceof DataSource) { + // Streaming transform applies only to javax.xml.transform.StreamSource + transformer.transform((Source) getContent((DataSource)obj), result); + } else { + transformer.transform((Source) obj, result); + } + } catch (Exception ex) { + throw new IOException( + "Unable to run the JAXP transformer on a stream " + + ex.getMessage()); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/ws/handler/ClientMessageHandlerTube.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,150 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.xml.internal.ws.handler; + +import com.sun.istack.internal.Nullable; +import com.sun.xml.internal.ws.api.WSBinding; +import com.sun.xml.internal.ws.api.handler.MessageHandler; +import com.sun.xml.internal.ws.api.message.Attachment; +import com.sun.xml.internal.ws.api.message.AttachmentSet; +import com.sun.xml.internal.ws.api.message.Packet; +import com.sun.xml.internal.ws.api.model.SEIModel; +import com.sun.xml.internal.ws.api.model.wsdl.WSDLPort; +import com.sun.xml.internal.ws.api.pipe.Tube; +import com.sun.xml.internal.ws.api.pipe.TubeCloner; +import com.sun.xml.internal.ws.api.pipe.helper.AbstractFilterTubeImpl; +import com.sun.xml.internal.ws.binding.BindingImpl; +import com.sun.xml.internal.ws.client.HandlerConfiguration; +import com.sun.xml.internal.ws.message.DataHandlerAttachment; + +import javax.activation.DataHandler; +import javax.xml.ws.WebServiceException; +import javax.xml.ws.handler.MessageContext; +import javax.xml.ws.handler.Handler; +import java.util.*; + +/** + * @author Rama Pulavarthi + */ +public class ClientMessageHandlerTube extends HandlerTube { + private SEIModel seiModel; + private WSBinding binding; + private Set<String> roles; + + /** + * Creates a new instance of MessageHandlerTube + */ + public ClientMessageHandlerTube(@Nullable SEIModel seiModel, WSBinding binding, WSDLPort port, Tube next) { + super(next, port); + this.seiModel = seiModel; + this.binding = binding; + } + + /** + * Copy constructor for {@link com.sun.xml.internal.ws.api.pipe.Tube#copy(com.sun.xml.internal.ws.api.pipe.TubeCloner)}. + */ + private ClientMessageHandlerTube(ClientMessageHandlerTube that, TubeCloner cloner) { + super(that, cloner); + this.seiModel = that.seiModel; + this.binding = that.binding; + } + + public AbstractFilterTubeImpl copy(TubeCloner cloner) { + return new ClientMessageHandlerTube(this, cloner); + } + + void callHandlersOnResponse(MessageUpdatableContext context, boolean handleFault) { + try { + //CLIENT-SIDE + processor.callHandlersResponse(HandlerProcessor.Direction.INBOUND, context, handleFault); + + } catch (WebServiceException wse) { + //no rewrapping + throw wse; + } catch (RuntimeException re) { + throw new WebServiceException(re); + } + } + + boolean callHandlersOnRequest(MessageUpdatableContext context, boolean isOneWay) { + boolean handlerResult; + + //Lets copy all the MessageContext.OUTBOUND_ATTACHMENT_PROPERTY to the message + Map<String, DataHandler> atts = (Map<String, DataHandler>) context.get(MessageContext.OUTBOUND_MESSAGE_ATTACHMENTS); + AttachmentSet attSet = packet.getMessage().getAttachments(); + for(String cid : atts.keySet()){ + if (attSet.get(cid) == null) { // Otherwise we would be adding attachments twice + Attachment att = new DataHandlerAttachment(cid, atts.get(cid)); + attSet.add(att); + } + } + + try { + //CLIENT-SIDE + handlerResult = processor.callHandlersRequest(HandlerProcessor.Direction.OUTBOUND, context, !isOneWay); + } catch (WebServiceException wse) { + remedyActionTaken = true; + //no rewrapping + throw wse; + } catch (RuntimeException re) { + remedyActionTaken = true; + + throw new WebServiceException(re); + + } + if (!handlerResult) { + remedyActionTaken = true; + } + return handlerResult; + } + + void closeHandlers(MessageContext mc) { + closeClientsideHandlers(mc); + + } + + void setUpProcessor() { + // Take a snapshot, User may change chain after invocation, Same chain + // should be used for the entire MEP + handlers = new ArrayList<Handler>(); + HandlerConfiguration handlerConfig = ((BindingImpl) binding).getHandlerConfig(); + List<MessageHandler> msgHandlersSnapShot= handlerConfig.getMessageHandlers(); + if (!msgHandlersSnapShot.isEmpty()) { + handlers.addAll(msgHandlersSnapShot); + roles = new HashSet<String>(); + roles.addAll(handlerConfig.getRoles()); + processor = new SOAPHandlerProcessor(true, this, binding, handlers); + } + } + + + + MessageUpdatableContext getContext(Packet p) { + MessageHandlerContextImpl context = new MessageHandlerContextImpl(seiModel, binding, port, packet,roles); + return context; + } + + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/ws/handler/MessageHandlerContextImpl.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,84 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.xml.internal.ws.handler; + +import com.sun.istack.internal.Nullable; +import com.sun.xml.internal.ws.api.WSBinding; +import com.sun.xml.internal.ws.api.handler.MessageHandlerContext; +import com.sun.xml.internal.ws.api.message.Message; +import com.sun.xml.internal.ws.api.message.Packet; +import com.sun.xml.internal.ws.api.model.SEIModel; +import com.sun.xml.internal.ws.api.model.wsdl.WSDLPort; + +import java.util.Set; + +/** + * @author Rama Pulavarthi + */ +public class MessageHandlerContextImpl extends MessageUpdatableContext implements MessageHandlerContext { + private @Nullable SEIModel seiModel; + private Set<String> roles; + private WSBinding binding; + private @Nullable WSDLPort wsdlModel; + + public MessageHandlerContextImpl(@Nullable SEIModel seiModel, WSBinding binding, @Nullable WSDLPort wsdlModel, Packet packet, Set<String> roles) { + super(packet); + this.seiModel = seiModel; + this.binding = binding; + this.wsdlModel = wsdlModel; + this.roles = roles; + } + public Message getMessage() { + return packet.getMessage(); + } + + public void setMessage(Message message) { + packet.setMessage(message); + } + + public Set<String> getRoles() { + return roles; + } + + public WSBinding getWSBinding() { + return binding; + } + + public @Nullable SEIModel getSEIModel() { + return seiModel; + } + + public @Nullable WSDLPort getPort() { + return wsdlModel; + } + + void updateMessage() { + // Do Nothing + } + + void setPacketMessage(Message newMessage) { + setMessage(newMessage); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/ws/handler/ServerMessageHandlerTube.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,149 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.xml.internal.ws.handler; + +import com.sun.xml.internal.ws.api.WSBinding; +import com.sun.xml.internal.ws.api.handler.MessageHandler; +import com.sun.xml.internal.ws.api.message.Attachment; +import com.sun.xml.internal.ws.api.message.AttachmentSet; +import com.sun.xml.internal.ws.api.message.Packet; +import com.sun.xml.internal.ws.api.model.SEIModel; +import com.sun.xml.internal.ws.api.pipe.Tube; +import com.sun.xml.internal.ws.api.pipe.TubeCloner; +import com.sun.xml.internal.ws.api.pipe.helper.AbstractFilterTubeImpl; +import com.sun.xml.internal.ws.binding.BindingImpl; +import com.sun.xml.internal.ws.client.HandlerConfiguration; +import com.sun.xml.internal.ws.message.DataHandlerAttachment; + +import javax.activation.DataHandler; +import javax.xml.ws.WebServiceException; +import javax.xml.ws.handler.MessageContext; +import javax.xml.ws.handler.Handler; +import java.util.*; + +/** + * @author Rama Pulavarthi + */ +public class ServerMessageHandlerTube extends HandlerTube{ + private SEIModel seiModel; + private WSBinding binding; + private Set<String> roles; + + public ServerMessageHandlerTube(SEIModel seiModel, WSBinding binding, Tube next, HandlerTube cousinTube) { + super(next, cousinTube); + this.seiModel = seiModel; + this.binding = binding; + setUpHandlersOnce(); + } + + /** + * Copy constructor for {@link com.sun.xml.internal.ws.api.pipe.Tube#copy(com.sun.xml.internal.ws.api.pipe.TubeCloner)}. + */ + private ServerMessageHandlerTube(ServerMessageHandlerTube that, TubeCloner cloner) { + super(that, cloner); + this.seiModel = that.seiModel; + this.binding = that.binding; + this.handlers = that.handlers; + this.roles = that.roles; + } + + private void setUpHandlersOnce() { + handlers = new ArrayList<Handler>(); + HandlerConfiguration handlerConfig = ((BindingImpl) binding).getHandlerConfig(); + List<MessageHandler> msgHandlersSnapShot= handlerConfig.getMessageHandlers(); + if (!msgHandlersSnapShot.isEmpty()) { + handlers.addAll(msgHandlersSnapShot); + roles = new HashSet<String>(); + roles.addAll(handlerConfig.getRoles()); + } + } + + void callHandlersOnResponse(MessageUpdatableContext context, boolean handleFault) { + //Lets copy all the MessageContext.OUTBOUND_ATTACHMENT_PROPERTY to the message + Map<String, DataHandler> atts = (Map<String, DataHandler>) context.get(MessageContext.OUTBOUND_MESSAGE_ATTACHMENTS); + AttachmentSet attSet = packet.getMessage().getAttachments(); + for(String cid : atts.keySet()){ + if (attSet.get(cid) == null) { // Otherwise we would be adding attachments twice + Attachment att = new DataHandlerAttachment(cid, atts.get(cid)); + attSet.add(att); + } + } + + try { + //SERVER-SIDE + processor.callHandlersResponse(HandlerProcessor.Direction.OUTBOUND, context, handleFault); + + } catch (WebServiceException wse) { + //no rewrapping + throw wse; + } catch (RuntimeException re) { + throw re; + + } + } + + boolean callHandlersOnRequest(MessageUpdatableContext context, boolean isOneWay) { + boolean handlerResult; + try { + //SERVER-SIDE + handlerResult = processor.callHandlersRequest(HandlerProcessor.Direction.INBOUND, context, !isOneWay); + + } catch (RuntimeException re) { + remedyActionTaken = true; + throw re; + + } + if (!handlerResult) { + remedyActionTaken = true; + } + return handlerResult; + } + + void setUpProcessor() { + if(!handlers.isEmpty()) { + processor = new SOAPHandlerProcessor(false, this, binding, handlers); + } + } + + void closeHandlers(MessageContext mc) { + closeServersideHandlers(mc); + + } + MessageUpdatableContext getContext(Packet packet) { + MessageHandlerContextImpl context = new MessageHandlerContextImpl(seiModel, binding, port, packet, roles); + return context; + } + + //should be overridden by DriverHandlerTubes + @Override + protected void initiateClosing(MessageContext mc) { + close(mc); + super.initiateClosing(mc); + } + + public AbstractFilterTubeImpl copy(TubeCloner cloner) { + return new ServerMessageHandlerTube(this, cloner); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/ws/message/FaultMessage.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,55 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.xml.internal.ws.message; + +import com.sun.istack.internal.Nullable; +import com.sun.xml.internal.ws.api.message.Message; +import com.sun.xml.internal.ws.api.message.FilterMessageImpl; +import com.sun.xml.internal.ws.api.model.wsdl.WSDLFault; + +import javax.xml.namespace.QName; + +/** + * SOAP Fault message. It has optimized implementation to get + * first detail entry's name. This is useful to identify the + * corresponding {@link WSDLFault} + * + * @author Jitendra Kotamraju + */ +public class FaultMessage extends FilterMessageImpl { + + private final @Nullable QName detailEntryName; + + public FaultMessage(Message delegate, @Nullable QName detailEntryName) { + super(delegate); + this.detailEntryName = detailEntryName; + } + + @Override + public @Nullable QName getFirstDetailEntryName() { + return detailEntryName; + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/ws/model/FieldSignature.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,100 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.xml.internal.ws.model; + +import java.util.*; +import java.util.logging.Logger; +import java.lang.reflect.*; + +/** + * Creates vm signature string from Type + * + * TypeSignature: Z | C | B | S | I | F | J | D | FieldTypeSignature + * FieldTypeSignature: ClassTypeSignature | [ TypeSignature | TypeVar + * ClassTypeSignature: L Id ( / Id )* TypeArgs? ( . Id TypeArgs? )* ; + * TypeArgs: < TypeArg+ > + * TypeArg: * | ( + | - )? FieldTypeSignature + * TypeVar: T Id ; + * + * @author Jitendra Kotamraju + */ +public class FieldSignature { + + static String vms(Type t) { + if (t instanceof Class || t instanceof ParameterizedType) { + return "L"+fqcn(t)+";"; + } else if (t instanceof GenericArrayType) { + return "["+vms(((GenericArrayType)t).getGenericComponentType()); + } else if (t instanceof TypeVariable) { + // While creating wrapper bean fields, it doesn't create with TypeVariables + // Otherwise, the type variable need to be declared in the wrapper bean class + // return "T"+((TypeVariable)t).getName()+";"; + return "Ljava/lang/Object;"; // TODO bounds ?? + } else if (t instanceof WildcardType) { + WildcardType w = (WildcardType)t; + if (w.getLowerBounds().length > 0) { + return "-"+vms(w.getLowerBounds()[0]); + } else if (w.getUpperBounds().length > 0) { + Type wt = w.getUpperBounds()[0]; + if (wt.equals(Object.class)) { + return "*"; + } else { + return "+"+vms(wt); + } + } + } + throw new IllegalArgumentException("Illegal vms arg " + t); + } + + private static String fqcn(Type t) { + if (t instanceof Class) { + Class c = (Class)t; + if (c.getDeclaringClass() == null) { + return c.getName().replace('.', '/'); + } else { + return fqcn(c.getDeclaringClass())+"."+c.getSimpleName(); + } + } else if (t instanceof ParameterizedType) { + ParameterizedType p = (ParameterizedType)t; + if (p.getOwnerType() == null) { + return fqcn(p.getRawType())+args(p); + } else { + assert p.getRawType() instanceof Class; + return fqcn(p.getOwnerType())+"."+ + ((Class)p.getRawType()).getSimpleName()+args(p); + } + } + throw new IllegalArgumentException("Illegal fqcn arg = "+t); + } + + private static String args(ParameterizedType p) { + String sig = "<"; + for(Type t : p.getActualTypeArguments()) { + sig += vms(t); + } + return sig+">"; + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/ws/model/Injector.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,192 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.xml.internal.ws.model; + +import com.sun.xml.internal.bind.Util; +import com.sun.xml.internal.bind.v2.runtime.reflect.Accessor; + +import java.lang.ref.WeakReference; +import java.lang.reflect.Method; +import java.lang.reflect.InvocationTargetException; +import java.util.Map; +import java.util.Collections; +import java.util.WeakHashMap; +import java.util.HashMap; +import java.util.logging.Logger; +import java.util.logging.Level; +import java.security.AccessController; +import java.security.PrivilegedAction; + +/** + * A {@link ClassLoader} used to "inject" optimized accessor classes + * into the VM. + * + * <p> + * Its parent class loader needs to be set to the one that can see the user + * class. + * + * @author Kohsuke Kawaguchi + */ +final class Injector { + + /** + * {@link Injector}s keyed by their parent {@link ClassLoader}. + * + * We only need one injector per one user class loader. + */ + private static final Map<ClassLoader,WeakReference<Injector>> injectors = + Collections.synchronizedMap(new WeakHashMap<ClassLoader,WeakReference<Injector>>()); + + private static final Logger logger = Util.getClassLogger(); + + /** + * Injects a new class into the given class loader. + * + * @return null + * if it fails to inject. + */ + static Class inject( ClassLoader cl, String className, byte[] image ) { + Injector injector = get(cl); + if(injector!=null) + return injector.inject(className,image); + else + return null; + } + + /** + * Returns the already injected class, or null. + */ + static Class find( ClassLoader cl, String className ) { + Injector injector = get(cl); + if(injector!=null) + return injector.find(className); + else + return null; + } + + /** + * Gets or creates an {@link Injector} for the given class loader. + * + * @return null + * if it fails. + */ + private static Injector get(ClassLoader cl) { + Injector injector = null; + WeakReference<Injector> wr = injectors.get(cl); + if(wr!=null) + injector = wr.get(); + if(injector==null) + try { + injectors.put(cl,new WeakReference<Injector>(injector = new Injector(cl))); + } catch (SecurityException e) { + logger.log(Level.FINE,"Unable to set up a back-door for the injector",e); + return null; + } + return injector; + } + + /** + * Injected classes keyed by their names. + */ + private final Map<String,Class> classes = new HashMap<String,Class>(); + + private final ClassLoader parent; + + /** + * True if this injector is capable of injecting accessors. + * False otherwise, which happens if this classloader can't see {@link com.sun.xml.internal.bind.v2.runtime.reflect.Accessor}. + */ + private final boolean loadable; + + private static final Method defineClass; + private static final Method resolveClass; + + static { + try { + defineClass = ClassLoader.class.getDeclaredMethod("defineClass",String.class,byte[].class,Integer.TYPE,Integer.TYPE); + resolveClass = ClassLoader.class.getDeclaredMethod("resolveClass",Class.class); + } catch (NoSuchMethodException e) { + // impossible + throw new NoSuchMethodError(e.getMessage()); + } + AccessController.doPrivileged(new PrivilegedAction<Void>() { + public Void run() { + // TODO: check security implication + // do these setAccessible allow anyone to call these methods freely?s + defineClass.setAccessible(true); + resolveClass.setAccessible(true); + return null; + } + }); + } + + private Injector(ClassLoader parent) { + this.parent = parent; + assert parent!=null; + + boolean loadable = false; + + try { + loadable = parent.loadClass(Accessor.class.getName())==Accessor.class; + } catch (ClassNotFoundException e) { + ; // not loadable + } + + this.loadable = loadable; + } + + + private synchronized Class inject(String className, byte[] image) { + if(!loadable) // this injector cannot inject anything + return null; + + Class c = classes.get(className); + if(c==null) { + // we need to inject a class into the + try { + c = (Class)defineClass.invoke(parent,className.replace('/','.'),image,0,image.length); + resolveClass.invoke(parent,c); + } catch (IllegalAccessException e) { + logger.log(Level.FINE,"Unable to inject "+className,e); + return null; + } catch (InvocationTargetException e) { + logger.log(Level.FINE,"Unable to inject "+className,e); + return null; + } catch (SecurityException e) { + logger.log(Level.FINE,"Unable to inject "+className,e); + return null; + } catch (LinkageError e) { + logger.log(Level.FINE,"Unable to inject "+className,e); + return null; + } + classes.put(className,c); + } + return c; + } + + private synchronized Class find(String className) { + return classes.get(className); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/ws/model/WrapperBeanGenerator.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,659 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.xml.internal.ws.model; + +import com.sun.istack.internal.NotNull; +import com.sun.xml.internal.bind.api.JAXBRIContext; +import com.sun.xml.internal.ws.util.StringUtils; +import static com.sun.xml.internal.ws.org.objectweb.asm.Opcodes.*; +import com.sun.xml.internal.ws.org.objectweb.asm.Type; +import com.sun.xml.internal.ws.org.objectweb.asm.*; + +import javax.jws.WebParam; +import javax.jws.WebResult; +import javax.xml.bind.annotation.XmlAttachmentRef; +import javax.xml.bind.annotation.XmlList; +import javax.xml.bind.annotation.XmlMimeType; +import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; +import javax.xml.ws.Holder; +import javax.xml.ws.WebServiceException; +import javax.xml.namespace.QName; +import java.lang.annotation.Annotation; +import java.lang.reflect.*; +import java.util.*; +import java.util.logging.Logger; +import java.util.logging.Level; + +/** + * Byte code generator for request,response wrapper and exception beans + * + * @author Jitendra Kotamraju + */ +public class WrapperBeanGenerator { + + private static final Logger LOGGER = Logger.getLogger(WrapperBeanGenerator.class.getName()); + + public static final String PD = "."; + public static final String JAXWS = "jaxws"; + public static final String JAXWS_PACKAGE_PD = JAXWS+PD; + public static final String PD_JAXWS_PACKAGE_PD = PD+JAXWS+PD; + + // Creates class's bytes + private static byte[] createBeanImage(String className, + String rootName, String rootNS, + String typeName, String typeNS, String[] propOrder, + List<Field> fields) throws Exception { + + ClassWriter cw = new ClassWriter(0); + //org.objectweb.asm.util.TraceClassVisitor cw = new org.objectweb.asm.util.TraceClassVisitor(actual, new java.io.PrintWriter(System.out)); + + cw.visit(V1_5, ACC_PUBLIC + ACC_SUPER, replaceDotWithSlash(className), null, "java/lang/Object", null); + + AnnotationVisitor root = cw.visitAnnotation("Ljavax/xml/bind/annotation/XmlRootElement;", true); + root.visit("name", rootName); + root.visit("namespace", rootNS); + root.visitEnd(); + + AnnotationVisitor type = cw.visitAnnotation("Ljavax/xml/bind/annotation/XmlType;", true); + type.visit("name", typeName); + type.visit("namespace", typeNS); + if (propOrder.length > 1) { + AnnotationVisitor propVisitor = type.visitArray("propOrder"); + for(String prop : propOrder) { + propVisitor.visit("propOrder", prop); + } + propVisitor.visitEnd(); + } + type.visitEnd(); + + for(Field field : fields) { + FieldVisitor fv = cw.visitField(ACC_PUBLIC, field.fieldName, field.asmType.getDescriptor(), field.getSignature(), null); + + if (!field.noXmlElem) { // Exception fields do not have any @XmlElement + AnnotationVisitor elem = fv.visitAnnotation("Ljavax/xml/bind/annotation/XmlElement;", true); + elem.visit("name", field.elementName); + elem.visit("namespace", field.elementNS); + if (field.reflectType instanceof GenericArrayType) { + elem.visit("nillable", true); + } + elem.visitEnd(); + } + + for(Annotation ann : field.jaxbAnnotations) { + if (ann instanceof XmlMimeType) { + AnnotationVisitor mime = fv.visitAnnotation("Ljavax/xml/bind/annotation/XmlMimeType;", true); + mime.visit("value", ((XmlMimeType)ann).value()); + mime.visitEnd(); + } else if (ann instanceof XmlJavaTypeAdapter) { + AnnotationVisitor ada = fv.visitAnnotation("Ljavax/xml/bind/annotation/XmlJavaTypeAdapter;", true); + ada.visit("value", ((XmlJavaTypeAdapter)ann).value()); + ada.visit("type", ((XmlJavaTypeAdapter)ann).type()); + ada.visitEnd(); + } else if (ann instanceof XmlAttachmentRef) { + AnnotationVisitor att = fv.visitAnnotation("Ljavax/xml/bind/annotation/XmlAttachmentRef;", true); + att.visitEnd(); + } else if (ann instanceof XmlList) { + AnnotationVisitor list = fv.visitAnnotation("Ljavax/xml/bind/annotation/XmlList;", true); + list.visitEnd(); + } else { + throw new WebServiceException("Unknown JAXB annotation " + ann); + } + } + + fv.visitEnd(); + } + + MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null); + mv.visitCode(); + mv.visitVarInsn(ALOAD, 0); + mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V"); + mv.visitInsn(RETURN); + mv.visitMaxs(1, 1); + mv.visitEnd(); + + cw.visitEnd(); + + if (LOGGER.isLoggable(Level.INFO)) { + // Class's @XmlRootElement + StringBuilder sb = new StringBuilder(); + sb.append("\n"); + sb.append("@XmlRootElement(name="); + sb.append(rootName); + sb.append(", namespace="); + sb.append(rootNS); + sb.append(")"); + + // Class's @XmlType + sb.append("\n"); + sb.append("@XmlType(name="); + sb.append(typeName); + sb.append(", namespace="); + sb.append(typeNS); + if (propOrder.length > 1) { + sb.append(", propOrder={"); + for(int i=0; i < propOrder.length; i++) { + if (i != 0) { + sb.append(", "); + } + sb.append(propOrder[i]); + } + sb.append("}"); + } + sb.append(")"); + + // class declaration + sb.append("\n"); + sb.append("public class "); + sb.append(className); + sb.append(" {"); + + // fields declaration + for(Field field : fields) { + sb.append("\n"); + + // Field's @XmlRootElement decl + if (!field.noXmlElem) { + sb.append("\n "); + sb.append("@XmlRootElement(name="); + sb.append(field.elementName); + sb.append(", namespace="); + sb.append(field.elementNS); + if (field.reflectType instanceof GenericArrayType) { + sb.append("nillable=true"); + } + sb.append(")"); + } + + // Field's other JAXB annotations + for(Annotation ann : field.jaxbAnnotations) { + sb.append("\n "); + + if (ann instanceof XmlMimeType) { + sb.append("@XmlMimeType(value="); + sb.append(((XmlMimeType)ann).value()); + sb.append(")"); + } else if (ann instanceof XmlJavaTypeAdapter) { + sb.append("@XmlJavaTypeAdapter(value="); + sb.append(((XmlMimeType)ann).value()); + sb.append(", type="); + sb.append(((XmlJavaTypeAdapter)ann).type()); + sb.append(")"); + } else if (ann instanceof XmlAttachmentRef) { + sb.append("@XmlAttachmentRef"); + } else if (ann instanceof XmlList) { + sb.append("@XmlList"); + } else { + throw new WebServiceException("Unknown JAXB annotation " + ann); + } + } + + // Field declaration + sb.append("\n "); + sb.append("public "); + if (field.getSignature() == null) { + sb.append(field.asmType.getDescriptor()); + } else { + sb.append(field.getSignature()); + } + sb.append(" "); + sb.append(field.fieldName); + } + + sb.append("\n\n}"); + LOGGER.fine(sb.toString()); + } + + return cw.toByteArray(); + } + + private static String replaceDotWithSlash(String name) { + return name.replace('.', '/'); + } + + static Class createRequestWrapperBean(String className, Method method, QName reqElemName, ClassLoader cl) { + + LOGGER.fine("Request Wrapper Class : "+className); + + List<Field> fields = collectRequestWrapperMembers(method); + + String[] propOrder = getPropOrder(fields); + + byte[] image; + try { + image = createBeanImage(className, reqElemName.getLocalPart(), reqElemName.getNamespaceURI(), + reqElemName.getLocalPart(), reqElemName.getNamespaceURI(), propOrder, + fields); + } catch(Exception e) { + throw new WebServiceException(e); + } + + return Injector.inject(cl, className, image); + } + + static Class createResponseWrapperBean(String className, Method method, QName resElemName, ClassLoader cl) { + + LOGGER.fine("Response Wrapper Class : "+className); + + List<Field> fields = collectResponseWrapperMembers(method); + + String[] propOrder = getPropOrder(fields); + + byte[] image; + try { + image = createBeanImage(className, resElemName.getLocalPart(), resElemName.getNamespaceURI(), + resElemName.getLocalPart(), resElemName.getNamespaceURI(), propOrder, + fields); + } catch(Exception e) { + throw new WebServiceException(e); + } + + return Injector.inject(cl, className, image); + } + + private static String[] getPropOrder(List<Field> fields) { + String[] propOrder = new String[fields.size()]; + for(int i=0; i < fields.size(); i++) { + propOrder[i] = fields.get(i).fieldName; + } + return propOrder; + } + + private static List<Field> collectRequestWrapperMembers(Method method) { + + List<Field> fields = new ArrayList<Field>(); + Annotation[][] paramAnns = method.getParameterAnnotations(); + java.lang.reflect.Type[] paramTypes = method.getGenericParameterTypes(); + Type[] asmTypes = Type.getArgumentTypes(method); + for(int i=0; i < paramTypes.length; i++) { + WebParam webParam = findAnnotation(paramAnns[i], WebParam.class); + if (webParam != null && webParam.header()) { + continue; + } + List<Annotation> jaxb = collectJAXBAnnotations(paramAnns[i]); + + java.lang.reflect.Type paramType = getHolderValueType(paramTypes[i]); + Type asmType = isHolder(paramTypes[i]) ? getASMType(paramType) : asmTypes[i]; + + String paramNamespace = ""; + String paramName = "arg"+i; + WebParam.Mode mode = WebParam.Mode.IN; + if (webParam != null) { + mode = webParam.mode(); + if (webParam.name().length() > 0) + paramName = webParam.name(); + if (webParam.targetNamespace().length() > 0) + paramNamespace = webParam.targetNamespace(); + } + + String fieldName = JAXBRIContext.mangleNameToVariableName(paramName); + //We wont have to do this if JAXBRIContext.mangleNameToVariableName() takes + //care of mangling java reserved keywords + fieldName = getJavaReservedVarialbeName(fieldName); + + Field memInfo = new Field(fieldName, paramType, asmType, paramName, paramNamespace, jaxb); + + if (mode.equals(WebParam.Mode.IN) || mode.equals(WebParam.Mode.INOUT)) { + fields.add(memInfo); + } + + } + return fields; + } + + private static List<Field> collectResponseWrapperMembers(Method method) { + + List<Field> fields = new ArrayList<Field>(); + + // Collect all OUT, INOUT parameters as fields + Annotation[][] paramAnns = method.getParameterAnnotations(); + java.lang.reflect.Type[] paramTypes = method.getGenericParameterTypes(); + Type[] asmTypes = Type.getArgumentTypes(method); + for(int i=0; i < paramTypes.length; i++) { + WebParam webParam = findAnnotation(paramAnns[i], WebParam.class); + if (webParam != null) { + if (webParam.header() || webParam.mode() == WebParam.Mode.IN) { + continue; + } + } + if (!isHolder(paramTypes[i])) { + continue; + } + + List<Annotation> jaxb = collectJAXBAnnotations(paramAnns[i]); + + java.lang.reflect.Type paramType = getHolderValueType(paramTypes[i]); + Type asmType = getASMType(paramType); + + String paramNamespace = ""; + String paramName = "arg"+i; + + if (webParam != null) { + if (webParam.name().length() > 0) + paramName = webParam.name(); + if (webParam.targetNamespace().length() > 0) + paramNamespace = webParam.targetNamespace(); + } + + String fieldName = JAXBRIContext.mangleNameToVariableName(paramName); + //We wont have to do this if JAXBRIContext.mangleNameToVariableName() takes + //care of mangling java reserved keywords + fieldName = getJavaReservedVarialbeName(fieldName); + + fields.add(new Field(fieldName, paramType, asmType, paramName, paramNamespace, jaxb)); + } + + WebResult webResult = method.getAnnotation(WebResult.class); + java.lang.reflect.Type returnType = method.getGenericReturnType(); + Type asmType = Type.getReturnType(method); + if (!((webResult != null && webResult.header()) || returnType == Void.TYPE)) { + String fieldElementName = "return"; + String fieldName = "_return"; + String fieldNamespace = ""; + + if (webResult != null) { + if (webResult.name().length() > 0) { + fieldElementName = webResult.name(); + fieldName = JAXBRIContext.mangleNameToVariableName(webResult.name()); + //We wont have to do this if JAXBRIContext.mangleNameToVariableName() takes + //care of mangling java identifiers + fieldName = getJavaReservedVarialbeName(fieldName); + } + if (webResult.targetNamespace().length() > 1) { + fieldNamespace = webResult.targetNamespace(); + } + } + + List<Annotation> jaxb = collectJAXBAnnotations(method.getAnnotations()); + + fields.add(new Field(fieldName, returnType, asmType, fieldElementName, fieldNamespace, jaxb)); + } + return fields; + } + + private static boolean isHolder(java.lang.reflect.Type type) { + if (type instanceof ParameterizedType) { + ParameterizedType p = (ParameterizedType)type; + if (p.getRawType().equals(Holder.class)) { + return true; + } + } + return false; + } + + private static Type getASMType(java.lang.reflect.Type t) { + assert t!=null; + + if (t instanceof Class) { + return Type.getType((Class)t); + } + + if (t instanceof ParameterizedType) { + ParameterizedType pt = (ParameterizedType)t; + if (pt.getRawType() instanceof Class) { + return Type.getType((Class)pt.getRawType()); + } + } + if (t instanceof GenericArrayType) { + // TODO + } + + if (t instanceof WildcardType) { + // TODO + } + if (t instanceof TypeVariable) { + TypeVariable tv = (TypeVariable)t; + if (tv.getBounds()[0] instanceof Class) { + return Type.getType((Class)tv.getBounds()[0]); + } + } + + // covered all the cases + assert false; + throw new IllegalArgumentException("Not creating ASM Type for type = "+t); + } + + private static java.lang.reflect.Type getHolderValueType(java.lang.reflect.Type paramType) { + if (paramType instanceof ParameterizedType) { + ParameterizedType p = (ParameterizedType)paramType; + if (p.getRawType().equals(Holder.class)) { + return p.getActualTypeArguments()[0]; + } + } + return paramType; + } + + private static <T extends Annotation> T findAnnotation(Annotation[] anns, Class<T> annotationClass) { + for(Annotation a : anns) { + if (a.annotationType() == annotationClass) { + return (T)a; + } + } + return null; + } + + static Class createExceptionBean(String className, Class exception, String typeNS, String elemName, String elemNS, ClassLoader cl) { + + List<Field> fields = collectExceptionProperties(exception); + String[] propOrder = getPropOrder(fields); + + byte[] image; + try { + image = createBeanImage(className, elemName, elemNS, + exception.getSimpleName(), typeNS, propOrder, + fields); + } catch(Exception e) { + throw new WebServiceException(e); + } + + return Injector.inject(cl, className, image); + } + + private static List<Field> collectExceptionProperties(Class exception) { + List<Field> fields = new ArrayList<Field>(); + + Method[] methods = exception.getMethods(); + for (Method method : methods) { + int mod = method.getModifiers(); + if (!Modifier.isPublic(mod) + || (Modifier.isFinal(mod) && Modifier.isStatic(mod)) + || Modifier.isTransient(mod)) { // no final static, transient, non-public + continue; + } + String name = method.getName(); + if (!(name.startsWith("get") || name.startsWith("is")) || skipProperties.contains(name) || + name.equals("get") || name.equals("is")) { + // Don't bother with invalid propertyNames. + continue; + } + + java.lang.reflect.Type[] paramTypes = method.getGenericParameterTypes(); + java.lang.reflect.Type returnType = method.getGenericReturnType(); + Type asmType = Type.getReturnType(method); + if (paramTypes.length == 0) { + if (name.startsWith("get")) { + String fieldName = StringUtils.decapitalize(name.substring(3)); + Field field = new Field(fieldName, returnType, asmType, true, Collections.<Annotation>emptyList()); + fields.add(field); + } else { + String fieldName = StringUtils.decapitalize(name.substring(2)); + Field field = new Field(fieldName, returnType, asmType, true, Collections.<Annotation>emptyList()); + fields.add(field); + } + } + } + Collections.sort(fields); + return fields; + } + + + private static List<Annotation> collectJAXBAnnotations(Annotation[] anns) { + Class[] known = { XmlAttachmentRef.class, XmlMimeType.class, XmlJavaTypeAdapter.class, XmlList.class }; + List<Annotation> jaxbAnnotation = new ArrayList<Annotation>(); + for(Class c : known) { + Annotation a = findAnnotation(anns, c); + if (a != null) { + jaxbAnnotation.add(a); + } + } + return jaxbAnnotation; + } + + + private List<Annotation> collectJAXBAnnotations(Method method) { + Class[] known = { XmlAttachmentRef.class, XmlMimeType.class, XmlJavaTypeAdapter.class, XmlList.class }; + List<Annotation> jaxbAnnotation = new ArrayList<Annotation>(); + for(Class c : known) { + Annotation ann = method.getAnnotation(c); + if(ann != null) { + jaxbAnnotation.add(ann); + } + } + return jaxbAnnotation; + } + + private static class Field implements Comparable<Field> { + private final java.lang.reflect.Type reflectType; + private final Type asmType; + private final String fieldName; + private final String elementName; + private final String elementNS; + private final List<Annotation> jaxbAnnotations; + private final boolean noXmlElem; + + Field(String paramName, java.lang.reflect.Type paramType, Type asmType, String elementName, + String elementNS, List<Annotation> jaxbAnnotations) { + this(paramName, paramType, asmType, false, elementName, elementNS, jaxbAnnotations); + } + + Field(String paramName, java.lang.reflect.Type paramType, Type asmType, boolean noXmlElem, + List<Annotation> jaxbAnnotations) { + this(paramName, paramType, asmType, noXmlElem, null,null, jaxbAnnotations); + } + + Field(String paramName, java.lang.reflect.Type paramType, Type asmType, boolean noXmlElem, + String elementName, String elementNS, List<Annotation> jaxbAnnotations) { + this.reflectType = paramType; + this.asmType = asmType; + this.fieldName = paramName; + this.noXmlElem = noXmlElem; + this.elementName = elementName; + this.elementNS = elementNS; + this.jaxbAnnotations = jaxbAnnotations; + } + + String getSignature() { + if (reflectType instanceof Class) { + return null; + } + if (reflectType instanceof TypeVariable) { + return null; + } + return FieldSignature.vms(reflectType); + } + + public int compareTo(Field o) { + return fieldName.compareTo(o.fieldName); + } + + } + + // TODO MOVE Names to runtime (instead of doing the following) + + /** + * See if its a java keyword name, if so then mangle the name + */ + private static @NotNull String getJavaReservedVarialbeName(@NotNull String name) { + String reservedName = reservedWords.get(name); + return reservedName == null ? name : reservedName; + } + + private static final Map<String, String> reservedWords; + + static { + reservedWords = new HashMap<String, String>(); + reservedWords.put("abstract", "_abstract"); + reservedWords.put("assert", "_assert"); + reservedWords.put("boolean", "_boolean"); + reservedWords.put("break", "_break"); + reservedWords.put("byte", "_byte"); + reservedWords.put("case", "_case"); + reservedWords.put("catch", "_catch"); + reservedWords.put("char", "_char"); + reservedWords.put("class", "_class"); + reservedWords.put("const", "_const"); + reservedWords.put("continue", "_continue"); + reservedWords.put("default", "_default"); + reservedWords.put("do", "_do"); + reservedWords.put("double", "_double"); + reservedWords.put("else", "_else"); + reservedWords.put("extends", "_extends"); + reservedWords.put("false", "_false"); + reservedWords.put("final", "_final"); + reservedWords.put("finally", "_finally"); + reservedWords.put("float", "_float"); + reservedWords.put("for", "_for"); + reservedWords.put("goto", "_goto"); + reservedWords.put("if", "_if"); + reservedWords.put("implements", "_implements"); + reservedWords.put("import", "_import"); + reservedWords.put("instanceof", "_instanceof"); + reservedWords.put("int", "_int"); + reservedWords.put("interface", "_interface"); + reservedWords.put("long", "_long"); + reservedWords.put("native", "_native"); + reservedWords.put("new", "_new"); + reservedWords.put("null", "_null"); + reservedWords.put("package", "_package"); + reservedWords.put("private", "_private"); + reservedWords.put("protected", "_protected"); + reservedWords.put("public", "_public"); + reservedWords.put("return", "_return"); + reservedWords.put("short", "_short"); + reservedWords.put("static", "_static"); + reservedWords.put("strictfp", "_strictfp"); + reservedWords.put("super", "_super"); + reservedWords.put("switch", "_switch"); + reservedWords.put("synchronized", "_synchronized"); + reservedWords.put("this", "_this"); + reservedWords.put("throw", "_throw"); + reservedWords.put("throws", "_throws"); + reservedWords.put("transient", "_transient"); + reservedWords.put("true", "_true"); + reservedWords.put("try", "_try"); + reservedWords.put("void", "_void"); + reservedWords.put("volatile", "_volatile"); + reservedWords.put("while", "_while"); + reservedWords.put("enum", "_enum"); + } + + private static final Set<String> skipProperties = new HashSet<String>(); + static{ + skipProperties.add("getCause"); + skipProperties.add("getLocalizedMessage"); + skipProperties.add("getClass"); + skipProperties.add("getStackTrace"); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/ws/model/wsdl/WSDLBoundFaultImpl.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,84 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.xml.internal.ws.model.wsdl; + +import com.sun.istack.internal.NotNull; +import com.sun.xml.internal.ws.api.model.wsdl.WSDLBoundFault; +import com.sun.xml.internal.ws.api.model.wsdl.WSDLFault; +import com.sun.xml.internal.ws.api.model.wsdl.WSDLOperation; +import com.sun.xml.internal.ws.api.model.wsdl.WSDLBoundOperation; + +import javax.xml.stream.XMLStreamReader; +import javax.xml.namespace.QName; + +/** + * @author Vivek Pandey + */ +public class WSDLBoundFaultImpl extends AbstractExtensibleImpl implements WSDLBoundFault { + private final String name; + private WSDLFault fault; + private WSDLBoundOperationImpl owner; + + public WSDLBoundFaultImpl(XMLStreamReader xsr, String name, WSDLBoundOperationImpl owner) { + super(xsr); + this.name = name; + this.owner = owner; + } + + public + @NotNull + String getName() { + return name; + } + + public QName getQName() { + if(owner.getOperation() != null){ + return new QName(owner.getOperation().getName().getNamespaceURI(), name); + } + return null; + } + + public WSDLFault getFault() { + return fault; + } + + @NotNull + public WSDLBoundOperation getBoundOperation() { + return owner; + } + + void freeze(WSDLBoundOperationImpl root) { + assert root != null; + WSDLOperation op = root.getOperation(); + if (op != null) { + for (WSDLFault f : op.getFaults()) { + if (f.getName().equals(name)) { + this.fault = f; + break; + } + } + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/ws/org/objectweb/asm/AnnotationVisitor.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,127 @@ +/* + * Copyright 2005-2009 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2007 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.sun.xml.internal.ws.org.objectweb.asm; + +/** + * A visitor to visit a Java annotation. The methods of this interface must be + * called in the following order: (<tt>visit<tt> | <tt>visitEnum<tt> | + * <tt>visitAnnotation<tt> | <tt>visitArray<tt>)* <tt>visitEnd<tt>. + * + * @author Eric Bruneton + * @author Eugene Kuleshov + */ +public interface AnnotationVisitor { + + /** + * Visits a primitive value of the annotation. + * + * @param name the value name. + * @param value the actual value, whose type must be {@link Byte}, + * {@link Boolean}, {@link Character}, {@link Short}, + * {@link Integer}, {@link Long}, {@link Float}, {@link Double}, + * {@link String} or {@link Type}. This value can also be an array + * of byte, boolean, short, char, int, long, float or double values + * (this is equivalent to using {@link #visitArray visitArray} and + * visiting each array element in turn, but is more convenient). + */ + void visit(String name, Object value); + + /** + * Visits an enumeration value of the annotation. + * + * @param name the value name. + * @param desc the class descriptor of the enumeration class. + * @param value the actual enumeration value. + */ + void visitEnum(String name, String desc, String value); + + /** + * Visits a nested annotation value of the annotation. + * + * @param name the value name. + * @param desc the class descriptor of the nested annotation class. + * @return a visitor to visit the actual nested annotation value, or + * <tt>null</tt> if this visitor is not interested in visiting + * this nested annotation. <i>The nested annotation value must be + * fully visited before calling other methods on this annotation + * visitor</i>. + */ + AnnotationVisitor visitAnnotation(String name, String desc); + + /** + * Visits an array value of the annotation. Note that arrays of primitive + * types (such as byte, boolean, short, char, int, long, float or double) + * can be passed as value to {@link #visit visit}. This is what + * {@link ClassReader} does. + * + * @param name the value name. + * @return a visitor to visit the actual array value elements, or + * <tt>null</tt> if this visitor is not interested in visiting + * these values. The 'name' parameters passed to the methods of this + * visitor are ignored. <i>All the array values must be visited + * before calling other methods on this annotation visitor</i>. + */ + AnnotationVisitor visitArray(String name); + + /** + * Visits the end of the annotation. + */ + void visitEnd(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/ws/org/objectweb/asm/AnnotationWriter.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,346 @@ +/* + * Copyright 2005-2009 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2007 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.sun.xml.internal.ws.org.objectweb.asm; + +/** + * An {@link AnnotationVisitor} that generates annotations in bytecode form. + * + * @author Eric Bruneton + * @author Eugene Kuleshov + */ +final class AnnotationWriter implements AnnotationVisitor { + + /** + * The class writer to which this annotation must be added. + */ + private final ClassWriter cw; + + /** + * The number of values in this annotation. + */ + private int size; + + /** + * <tt>true<tt> if values are named, <tt>false</tt> otherwise. Annotation + * writers used for annotation default and annotation arrays use unnamed + * values. + */ + private final boolean named; + + /** + * The annotation values in bytecode form. This byte vector only contains + * the values themselves, i.e. the number of values must be stored as a + * unsigned short just before these bytes. + */ + private final ByteVector bv; + + /** + * The byte vector to be used to store the number of values of this + * annotation. See {@link #bv}. + */ + private final ByteVector parent; + + /** + * Where the number of values of this annotation must be stored in + * {@link #parent}. + */ + private final int offset; + + /** + * Next annotation writer. This field is used to store annotation lists. + */ + AnnotationWriter next; + + /** + * Previous annotation writer. This field is used to store annotation lists. + */ + AnnotationWriter prev; + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + + /** + * Constructs a new {@link AnnotationWriter}. + * + * @param cw the class writer to which this annotation must be added. + * @param named <tt>true<tt> if values are named, <tt>false</tt> otherwise. + * @param bv where the annotation values must be stored. + * @param parent where the number of annotation values must be stored. + * @param offset where in <tt>parent</tt> the number of annotation values must + * be stored. + */ + AnnotationWriter( + final ClassWriter cw, + final boolean named, + final ByteVector bv, + final ByteVector parent, + final int offset) + { + this.cw = cw; + this.named = named; + this.bv = bv; + this.parent = parent; + this.offset = offset; + } + + // ------------------------------------------------------------------------ + // Implementation of the AnnotationVisitor interface + // ------------------------------------------------------------------------ + + public void visit(final String name, final Object value) { + ++size; + if (named) { + bv.putShort(cw.newUTF8(name)); + } + if (value instanceof String) { + bv.put12('s', cw.newUTF8((String) value)); + } else if (value instanceof Byte) { + bv.put12('B', cw.newInteger(((Byte) value).byteValue()).index); + } else if (value instanceof Boolean) { + int v = ((Boolean) value).booleanValue() ? 1 : 0; + bv.put12('Z', cw.newInteger(v).index); + } else if (value instanceof Character) { + bv.put12('C', cw.newInteger(((Character) value).charValue()).index); + } else if (value instanceof Short) { + bv.put12('S', cw.newInteger(((Short) value).shortValue()).index); + } else if (value instanceof Type) { + bv.put12('c', cw.newUTF8(((Type) value).getDescriptor())); + } else if (value instanceof byte[]) { + byte[] v = (byte[]) value; + bv.put12('[', v.length); + for (int i = 0; i < v.length; i++) { + bv.put12('B', cw.newInteger(v[i]).index); + } + } else if (value instanceof boolean[]) { + boolean[] v = (boolean[]) value; + bv.put12('[', v.length); + for (int i = 0; i < v.length; i++) { + bv.put12('Z', cw.newInteger(v[i] ? 1 : 0).index); + } + } else if (value instanceof short[]) { + short[] v = (short[]) value; + bv.put12('[', v.length); + for (int i = 0; i < v.length; i++) { + bv.put12('S', cw.newInteger(v[i]).index); + } + } else if (value instanceof char[]) { + char[] v = (char[]) value; + bv.put12('[', v.length); + for (int i = 0; i < v.length; i++) { + bv.put12('C', cw.newInteger(v[i]).index); + } + } else if (value instanceof int[]) { + int[] v = (int[]) value; + bv.put12('[', v.length); + for (int i = 0; i < v.length; i++) { + bv.put12('I', cw.newInteger(v[i]).index); + } + } else if (value instanceof long[]) { + long[] v = (long[]) value; + bv.put12('[', v.length); + for (int i = 0; i < v.length; i++) { + bv.put12('J', cw.newLong(v[i]).index); + } + } else if (value instanceof float[]) { + float[] v = (float[]) value; + bv.put12('[', v.length); + for (int i = 0; i < v.length; i++) { + bv.put12('F', cw.newFloat(v[i]).index); + } + } else if (value instanceof double[]) { + double[] v = (double[]) value; + bv.put12('[', v.length); + for (int i = 0; i < v.length; i++) { + bv.put12('D', cw.newDouble(v[i]).index); + } + } else { + Item i = cw.newConstItem(value); + bv.put12(".s.IFJDCS".charAt(i.type), i.index); + } + } + + public void visitEnum( + final String name, + final String desc, + final String value) + { + ++size; + if (named) { + bv.putShort(cw.newUTF8(name)); + } + bv.put12('e', cw.newUTF8(desc)).putShort(cw.newUTF8(value)); + } + + public AnnotationVisitor visitAnnotation( + final String name, + final String desc) + { + ++size; + if (named) { + bv.putShort(cw.newUTF8(name)); + } + // write tag and type, and reserve space for values count + bv.put12('@', cw.newUTF8(desc)).putShort(0); + return new AnnotationWriter(cw, true, bv, bv, bv.length - 2); + } + + public AnnotationVisitor visitArray(final String name) { + ++size; + if (named) { + bv.putShort(cw.newUTF8(name)); + } + // write tag, and reserve space for array size + bv.put12('[', 0); + return new AnnotationWriter(cw, false, bv, bv, bv.length - 2); + } + + public void visitEnd() { + if (parent != null) { + byte[] data = parent.data; + data[offset] = (byte) (size >>> 8); + data[offset + 1] = (byte) size; + } + } + + // ------------------------------------------------------------------------ + // Utility methods + // ------------------------------------------------------------------------ + + /** + * Returns the size of this annotation writer list. + * + * @return the size of this annotation writer list. + */ + int getSize() { + int size = 0; + AnnotationWriter aw = this; + while (aw != null) { + size += aw.bv.length; + aw = aw.next; + } + return size; + } + + /** + * Puts the annotations of this annotation writer list into the given byte + * vector. + * + * @param out where the annotations must be put. + */ + void put(final ByteVector out) { + int n = 0; + int size = 2; + AnnotationWriter aw = this; + AnnotationWriter last = null; + while (aw != null) { + ++n; + size += aw.bv.length; + aw.visitEnd(); // in case user forgot to call visitEnd + aw.prev = last; + last = aw; + aw = aw.next; + } + out.putInt(size); + out.putShort(n); + aw = last; + while (aw != null) { + out.putByteArray(aw.bv.data, 0, aw.bv.length); + aw = aw.prev; + } + } + + /** + * Puts the given annotation lists into the given byte vector. + * + * @param panns an array of annotation writer lists. + * @param off index of the first annotation to be written. + * @param out where the annotations must be put. + */ + static void put( + final AnnotationWriter[] panns, + final int off, + final ByteVector out) + { + int size = 1 + 2 * (panns.length - off); + for (int i = off; i < panns.length; ++i) { + size += panns[i] == null ? 0 : panns[i].getSize(); + } + out.putInt(size).putByte(panns.length - off); + for (int i = off; i < panns.length; ++i) { + AnnotationWriter aw = panns[i]; + AnnotationWriter last = null; + int n = 0; + while (aw != null) { + ++n; + aw.visitEnd(); // in case user forgot to call visitEnd + aw.prev = last; + last = aw; + aw = aw.next; + } + out.putShort(n); + aw = last; + while (aw != null) { + out.putByteArray(aw.bv.data, 0, aw.bv.length); + aw = aw.prev; + } + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/ws/org/objectweb/asm/Attribute.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,284 @@ +/* + * Copyright 2005-2009 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2007 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.sun.xml.internal.ws.org.objectweb.asm; + +/** + * A non standard class, field, method or code attribute. + * + * @author Eric Bruneton + * @author Eugene Kuleshov + */ +public class Attribute { + + /** + * The type of this attribute. + */ + public final String type; + + /** + * The raw value of this attribute, used only for unknown attributes. + */ + byte[] value; + + /** + * The next attribute in this attribute list. May be <tt>null</tt>. + */ + Attribute next; + + /** + * Constructs a new empty attribute. + * + * @param type the type of the attribute. + */ + protected Attribute(final String type) { + this.type = type; + } + + /** + * Returns <tt>true</tt> if this type of attribute is unknown. The default + * implementation of this method always returns <tt>true</tt>. + * + * @return <tt>true</tt> if this type of attribute is unknown. + */ + public boolean isUnknown() { + return true; + } + + /** + * Returns <tt>true</tt> if this type of attribute is a code attribute. + * + * @return <tt>true</tt> if this type of attribute is a code attribute. + */ + public boolean isCodeAttribute() { + return false; + } + + /** + * Returns the labels corresponding to this attribute. + * + * @return the labels corresponding to this attribute, or <tt>null</tt> if + * this attribute is not a code attribute that contains labels. + */ + protected Label[] getLabels() { + return null; + } + + /** + * Reads a {@link #type type} attribute. This method must return a <i>new</i> + * {@link Attribute} object, of type {@link #type type}, corresponding to + * the <tt>len</tt> bytes starting at the given offset, in the given class + * reader. + * + * @param cr the class that contains the attribute to be read. + * @param off index of the first byte of the attribute's content in {@link + * ClassReader#b cr.b}. The 6 attribute header bytes, containing the + * type and the length of the attribute, are not taken into account + * here. + * @param len the length of the attribute's content. + * @param buf buffer to be used to call + * {@link ClassReader#readUTF8 readUTF8}, + * {@link ClassReader#readClass(int,char[]) readClass} or + * {@link ClassReader#readConst readConst}. + * @param codeOff index of the first byte of code's attribute content in + * {@link ClassReader#b cr.b}, or -1 if the attribute to be read is + * not a code attribute. The 6 attribute header bytes, containing the + * type and the length of the attribute, are not taken into account + * here. + * @param labels the labels of the method's code, or <tt>null</tt> if the + * attribute to be read is not a code attribute. + * @return a <i>new</i> {@link Attribute} object corresponding to the given + * bytes. + */ + protected Attribute read( + final ClassReader cr, + final int off, + final int len, + final char[] buf, + final int codeOff, + final Label[] labels) + { + Attribute attr = new Attribute(type); + attr.value = new byte[len]; + System.arraycopy(cr.b, off, attr.value, 0, len); + return attr; + } + + /** + * Returns the byte array form of this attribute. + * + * @param cw the class to which this attribute must be added. This parameter + * can be used to add to the constant pool of this class the items + * that corresponds to this attribute. + * @param code the bytecode of the method corresponding to this code + * attribute, or <tt>null</tt> if this attribute is not a code + * attributes. + * @param len the length of the bytecode of the method corresponding to this + * code attribute, or <tt>null</tt> if this attribute is not a code + * attribute. + * @param maxStack the maximum stack size of the method corresponding to + * this code attribute, or -1 if this attribute is not a code + * attribute. + * @param maxLocals the maximum number of local variables of the method + * corresponding to this code attribute, or -1 if this attribute is + * not a code attribute. + * @return the byte array form of this attribute. + */ + protected ByteVector write( + final ClassWriter cw, + final byte[] code, + final int len, + final int maxStack, + final int maxLocals) + { + ByteVector v = new ByteVector(); + v.data = value; + v.length = value.length; + return v; + } + + /** + * Returns the length of the attribute list that begins with this attribute. + * + * @return the length of the attribute list that begins with this attribute. + */ + final int getCount() { + int count = 0; + Attribute attr = this; + while (attr != null) { + count += 1; + attr = attr.next; + } + return count; + } + + /** + * Returns the size of all the attributes in this attribute list. + * + * @param cw the class writer to be used to convert the attributes into byte + * arrays, with the {@link #write write} method. + * @param code the bytecode of the method corresponding to these code + * attributes, or <tt>null</tt> if these attributes are not code + * attributes. + * @param len the length of the bytecode of the method corresponding to + * these code attributes, or <tt>null</tt> if these attributes are + * not code attributes. + * @param maxStack the maximum stack size of the method corresponding to + * these code attributes, or -1 if these attributes are not code + * attributes. + * @param maxLocals the maximum number of local variables of the method + * corresponding to these code attributes, or -1 if these attributes + * are not code attributes. + * @return the size of all the attributes in this attribute list. This size + * includes the size of the attribute headers. + */ + final int getSize( + final ClassWriter cw, + final byte[] code, + final int len, + final int maxStack, + final int maxLocals) + { + Attribute attr = this; + int size = 0; + while (attr != null) { + cw.newUTF8(attr.type); + size += attr.write(cw, code, len, maxStack, maxLocals).length + 6; + attr = attr.next; + } + return size; + } + + /** + * Writes all the attributes of this attribute list in the given byte + * vector. + * + * @param cw the class writer to be used to convert the attributes into byte + * arrays, with the {@link #write write} method. + * @param code the bytecode of the method corresponding to these code + * attributes, or <tt>null</tt> if these attributes are not code + * attributes. + * @param len the length of the bytecode of the method corresponding to + * these code attributes, or <tt>null</tt> if these attributes are + * not code attributes. + * @param maxStack the maximum stack size of the method corresponding to + * these code attributes, or -1 if these attributes are not code + * attributes. + * @param maxLocals the maximum number of local variables of the method + * corresponding to these code attributes, or -1 if these attributes + * are not code attributes. + * @param out where the attributes must be written. + */ + final void put( + final ClassWriter cw, + final byte[] code, + final int len, + final int maxStack, + final int maxLocals, + final ByteVector out) + { + Attribute attr = this; + while (attr != null) { + ByteVector b = attr.write(cw, code, len, maxStack, maxLocals); + out.putShort(cw.newUTF8(attr.type)).putInt(b.length); + out.putByteArray(b.data, 0, b.length); + attr = attr.next; + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/ws/org/objectweb/asm/ByteVector.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,323 @@ +/* + * Copyright 2005-2009 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2007 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.sun.xml.internal.ws.org.objectweb.asm; + +/** + * A dynamically extensible vector of bytes. This class is roughly equivalent to + * a DataOutputStream on top of a ByteArrayOutputStream, but is more efficient. + * + * @author Eric Bruneton + */ +public class ByteVector { + + /** + * The content of this vector. + */ + byte[] data; + + /** + * Actual number of bytes in this vector. + */ + int length; + + /** + * Constructs a new {@link ByteVector ByteVector} with a default initial + * size. + */ + public ByteVector() { + data = new byte[64]; + } + + /** + * Constructs a new {@link ByteVector ByteVector} with the given initial + * size. + * + * @param initialSize the initial size of the byte vector to be constructed. + */ + public ByteVector(final int initialSize) { + data = new byte[initialSize]; + } + + /** + * Puts a byte into this byte vector. The byte vector is automatically + * enlarged if necessary. + * + * @param b a byte. + * @return this byte vector. + */ + public ByteVector putByte(final int b) { + int length = this.length; + if (length + 1 > data.length) { + enlarge(1); + } + data[length++] = (byte) b; + this.length = length; + return this; + } + + /** + * Puts two bytes into this byte vector. The byte vector is automatically + * enlarged if necessary. + * + * @param b1 a byte. + * @param b2 another byte. + * @return this byte vector. + */ + ByteVector put11(final int b1, final int b2) { + int length = this.length; + if (length + 2 > data.length) { + enlarge(2); + } + byte[] data = this.data; + data[length++] = (byte) b1; + data[length++] = (byte) b2; + this.length = length; + return this; + } + + /** + * Puts a short into this byte vector. The byte vector is automatically + * enlarged if necessary. + * + * @param s a short. + * @return this byte vector. + */ + public ByteVector putShort(final int s) { + int length = this.length; + if (length + 2 > data.length) { + enlarge(2); + } + byte[] data = this.data; + data[length++] = (byte) (s >>> 8); + data[length++] = (byte) s; + this.length = length; + return this; + } + + /** + * Puts a byte and a short into this byte vector. The byte vector is + * automatically enlarged if necessary. + * + * @param b a byte. + * @param s a short. + * @return this byte vector. + */ + ByteVector put12(final int b, final int s) { + int length = this.length; + if (length + 3 > data.length) { + enlarge(3); + } + byte[] data = this.data; + data[length++] = (byte) b; + data[length++] = (byte) (s >>> 8); + data[length++] = (byte) s; + this.length = length; + return this; + } + + /** + * Puts an int into this byte vector. The byte vector is automatically + * enlarged if necessary. + * + * @param i an int. + * @return this byte vector. + */ + public ByteVector putInt(final int i) { + int length = this.length; + if (length + 4 > data.length) { + enlarge(4); + } + byte[] data = this.data; + data[length++] = (byte) (i >>> 24); + data[length++] = (byte) (i >>> 16); + data[length++] = (byte) (i >>> 8); + data[length++] = (byte) i; + this.length = length; + return this; + } + + /** + * Puts a long into this byte vector. The byte vector is automatically + * enlarged if necessary. + * + * @param l a long. + * @return this byte vector. + */ + public ByteVector putLong(final long l) { + int length = this.length; + if (length + 8 > data.length) { + enlarge(8); + } + byte[] data = this.data; + int i = (int) (l >>> 32); + data[length++] = (byte) (i >>> 24); + data[length++] = (byte) (i >>> 16); + data[length++] = (byte) (i >>> 8); + data[length++] = (byte) i; + i = (int) l; + data[length++] = (byte) (i >>> 24); + data[length++] = (byte) (i >>> 16); + data[length++] = (byte) (i >>> 8); + data[length++] = (byte) i; + this.length = length; + return this; + } + + /** + * Puts an UTF8 string into this byte vector. The byte vector is + * automatically enlarged if necessary. + * + * @param s a String. + * @return this byte vector. + */ + public ByteVector putUTF8(final String s) { + int charLength = s.length(); + if (length + 2 + charLength > data.length) { + enlarge(2 + charLength); + } + int len = length; + byte[] data = this.data; + // optimistic algorithm: instead of computing the byte length and then + // serializing the string (which requires two loops), we assume the byte + // length is equal to char length (which is the most frequent case), and + // we start serializing the string right away. During the serialization, + // if we find that this assumption is wrong, we continue with the + // general method. + data[len++] = (byte) (charLength >>> 8); + data[len++] = (byte) charLength; + for (int i = 0; i < charLength; ++i) { + char c = s.charAt(i); + if (c >= '\001' && c <= '\177') { + data[len++] = (byte) c; + } else { + int byteLength = i; + for (int j = i; j < charLength; ++j) { + c = s.charAt(j); + if (c >= '\001' && c <= '\177') { + byteLength++; + } else if (c > '\u07FF') { + byteLength += 3; + } else { + byteLength += 2; + } + } + data[length] = (byte) (byteLength >>> 8); + data[length + 1] = (byte) byteLength; + if (length + 2 + byteLength > data.length) { + length = len; + enlarge(2 + byteLength); + data = this.data; + } + for (int j = i; j < charLength; ++j) { + c = s.charAt(j); + if (c >= '\001' && c <= '\177') { + data[len++] = (byte) c; + } else if (c > '\u07FF') { + data[len++] = (byte) (0xE0 | c >> 12 & 0xF); + data[len++] = (byte) (0x80 | c >> 6 & 0x3F); + data[len++] = (byte) (0x80 | c & 0x3F); + } else { + data[len++] = (byte) (0xC0 | c >> 6 & 0x1F); + data[len++] = (byte) (0x80 | c & 0x3F); + } + } + break; + } + } + length = len; + return this; + } + + /** + * Puts an array of bytes into this byte vector. The byte vector is + * automatically enlarged if necessary. + * + * @param b an array of bytes. May be <tt>null</tt> to put <tt>len</tt> + * null bytes into this byte vector. + * @param off index of the fist byte of b that must be copied. + * @param len number of bytes of b that must be copied. + * @return this byte vector. + */ + public ByteVector putByteArray(final byte[] b, final int off, final int len) + { + if (length + len > data.length) { + enlarge(len); + } + if (b != null) { + System.arraycopy(b, off, data, length, len); + } + length += len; + return this; + } + + /** + * Enlarge this byte vector so that it can receive n more bytes. + * + * @param size number of additional bytes that this byte vector should be + * able to receive. + */ + private void enlarge(final int size) { + int length1 = 2 * data.length; + int length2 = length + size; + byte[] newData = new byte[length1 > length2 ? length1 : length2]; + System.arraycopy(data, 0, newData, 0, length); + data = newData; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/ws/org/objectweb/asm/ClassReader.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,2039 @@ +/* + * Copyright 2005-2009 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2007 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.sun.xml.internal.ws.org.objectweb.asm; + +import java.io.InputStream; +import java.io.IOException; + +/** + * A Java class parser to make a {@link ClassVisitor} visit an existing class. + * This class parses a byte array conforming to the Java class file format and + * calls the appropriate visit methods of a given class visitor for each field, + * method and bytecode instruction encountered. + * + * @author Eric Bruneton + * @author Eugene Kuleshov + */ +public class ClassReader { + + /** + * True to enable signatures support. + */ + static final boolean SIGNATURES = true; + + /** + * True to enable annotations support. + */ + static final boolean ANNOTATIONS = true; + + /** + * True to enable stack map frames support. + */ + static final boolean FRAMES = true; + + /** + * True to enable bytecode writing support. + */ + static final boolean WRITER = true; + + /** + * True to enable JSR_W and GOTO_W support. + */ + static final boolean RESIZE = true; + + /** + * Flag to skip method code. If this class is set <code>CODE</code> + * attribute won't be visited. This can be used, for example, to retrieve + * annotations for methods and method parameters. + */ + public static final int SKIP_CODE = 1; + + /** + * Flag to skip the debug information in the class. If this flag is set the + * debug information of the class is not visited, i.e. the + * {@link MethodVisitor#visitLocalVariable visitLocalVariable} and + * {@link MethodVisitor#visitLineNumber visitLineNumber} methods will not be + * called. + */ + public static final int SKIP_DEBUG = 2; + + /** + * Flag to skip the stack map frames in the class. If this flag is set the + * stack map frames of the class is not visited, i.e. the + * {@link MethodVisitor#visitFrame visitFrame} method will not be called. + * This flag is useful when the {@link ClassWriter#COMPUTE_FRAMES} option is + * used: it avoids visiting frames that will be ignored and recomputed from + * scratch in the class writer. + */ + public static final int SKIP_FRAMES = 4; + + /** + * Flag to expand the stack map frames. By default stack map frames are + * visited in their original format (i.e. "expanded" for classes whose + * version is less than V1_6, and "compressed" for the other classes). If + * this flag is set, stack map frames are always visited in expanded format + * (this option adds a decompression/recompression step in ClassReader and + * ClassWriter which degrades performances quite a lot). + */ + public static final int EXPAND_FRAMES = 8; + + /** + * The class to be parsed. <i>The content of this array must not be + * modified. This field is intended for {@link Attribute} sub classes, and + * is normally not needed by class generators or adapters.</i> + */ + public final byte[] b; + + /** + * The start index of each constant pool item in {@link #b b}, plus one. + * The one byte offset skips the constant pool item tag that indicates its + * type. + */ + private final int[] items; + + /** + * The String objects corresponding to the CONSTANT_Utf8 items. This cache + * avoids multiple parsing of a given CONSTANT_Utf8 constant pool item, + * which GREATLY improves performances (by a factor 2 to 3). This caching + * strategy could be extended to all constant pool items, but its benefit + * would not be so great for these items (because they are much less + * expensive to parse than CONSTANT_Utf8 items). + */ + private final String[] strings; + + /** + * Maximum length of the strings contained in the constant pool of the + * class. + */ + private final int maxStringLength; + + /** + * Start index of the class header information (access, name...) in + * {@link #b b}. + */ + public final int header; + + // ------------------------------------------------------------------------ + // Constructors + // ------------------------------------------------------------------------ + + /** + * Constructs a new {@link ClassReader} object. + * + * @param b the bytecode of the class to be read. + */ + public ClassReader(final byte[] b) { + this(b, 0, b.length); + } + + /** + * Constructs a new {@link ClassReader} object. + * + * @param b the bytecode of the class to be read. + * @param off the start offset of the class data. + * @param len the length of the class data. + */ + public ClassReader(final byte[] b, final int off, final int len) { + this.b = b; + // parses the constant pool + items = new int[readUnsignedShort(off + 8)]; + int n = items.length; + strings = new String[n]; + int max = 0; + int index = off + 10; + for (int i = 1; i < n; ++i) { + items[i] = index + 1; + int size; + switch (b[index]) { + case ClassWriter.FIELD: + case ClassWriter.METH: + case ClassWriter.IMETH: + case ClassWriter.INT: + case ClassWriter.FLOAT: + case ClassWriter.NAME_TYPE: + size = 5; + break; + case ClassWriter.LONG: + case ClassWriter.DOUBLE: + size = 9; + ++i; + break; + case ClassWriter.UTF8: + size = 3 + readUnsignedShort(index + 1); + if (size > max) { + max = size; + } + break; + // case ClassWriter.CLASS: + // case ClassWriter.STR: + default: + size = 3; + break; + } + index += size; + } + maxStringLength = max; + // the class header information starts just after the constant pool + header = index; + } + + /** + * Returns the class's access flags (see {@link Opcodes}). This value may + * not reflect Deprecated and Synthetic flags when bytecode is before 1.5 + * and those flags are represented by attributes. + * + * @return the class access flags + * + * @see ClassVisitor#visit(int, int, String, String, String, String[]) + */ + public int getAccess() { + return readUnsignedShort(header); + } + + /** + * Returns the internal name of the class (see + * {@link Type#getInternalName() getInternalName}). + * + * @return the internal class name + * + * @see ClassVisitor#visit(int, int, String, String, String, String[]) + */ + public String getClassName() { + return readClass(header + 2, new char[maxStringLength]); + } + + /** + * Returns the internal of name of the super class (see + * {@link Type#getInternalName() getInternalName}). For interfaces, the + * super class is {@link Object}. + * + * @return the internal name of super class, or <tt>null</tt> for + * {@link Object} class. + * + * @see ClassVisitor#visit(int, int, String, String, String, String[]) + */ + public String getSuperName() { + int n = items[readUnsignedShort(header + 4)]; + return n == 0 ? null : readUTF8(n, new char[maxStringLength]); + } + + /** + * Returns the internal names of the class's interfaces (see + * {@link Type#getInternalName() getInternalName}). + * + * @return the array of internal names for all implemented interfaces or + * <tt>null</tt>. + * + * @see ClassVisitor#visit(int, int, String, String, String, String[]) + */ + public String[] getInterfaces() { + int index = header + 6; + int n = readUnsignedShort(index); + String[] interfaces = new String[n]; + if (n > 0) { + char[] buf = new char[maxStringLength]; + for (int i = 0; i < n; ++i) { + index += 2; + interfaces[i] = readClass(index, buf); + } + } + return interfaces; + } + + /** + * Copies the constant pool data into the given {@link ClassWriter}. Should + * be called before the {@link #accept(ClassVisitor,int)} method. + * + * @param classWriter the {@link ClassWriter} to copy constant pool into. + */ + void copyPool(final ClassWriter classWriter) { + char[] buf = new char[maxStringLength]; + int ll = items.length; + Item[] items2 = new Item[ll]; + for (int i = 1; i < ll; i++) { + int index = items[i]; + int tag = b[index - 1]; + Item item = new Item(i); + int nameType; + switch (tag) { + case ClassWriter.FIELD: + case ClassWriter.METH: + case ClassWriter.IMETH: + nameType = items[readUnsignedShort(index + 2)]; + item.set(tag, + readClass(index, buf), + readUTF8(nameType, buf), + readUTF8(nameType + 2, buf)); + break; + + case ClassWriter.INT: + item.set(readInt(index)); + break; + + case ClassWriter.FLOAT: + item.set(Float.intBitsToFloat(readInt(index))); + break; + + case ClassWriter.NAME_TYPE: + item.set(tag, + readUTF8(index, buf), + readUTF8(index + 2, buf), + null); + break; + + case ClassWriter.LONG: + item.set(readLong(index)); + ++i; + break; + + case ClassWriter.DOUBLE: + item.set(Double.longBitsToDouble(readLong(index))); + ++i; + break; + + case ClassWriter.UTF8: { + String s = strings[i]; + if (s == null) { + index = items[i]; + s = strings[i] = readUTF(index + 2, + readUnsignedShort(index), + buf); + } + item.set(tag, s, null, null); + } + break; + + // case ClassWriter.STR: + // case ClassWriter.CLASS: + default: + item.set(tag, readUTF8(index, buf), null, null); + break; + } + + int index2 = item.hashCode % items2.length; + item.next = items2[index2]; + items2[index2] = item; + } + + int off = items[1] - 1; + classWriter.pool.putByteArray(b, off, header - off); + classWriter.items = items2; + classWriter.threshold = (int) (0.75d * ll); + classWriter.index = ll; + } + + /** + * Constructs a new {@link ClassReader} object. + * + * @param is an input stream from which to read the class. + * @throws IOException if a problem occurs during reading. + */ + public ClassReader(final InputStream is) throws IOException { + this(readClass(is)); + } + + /** + * Constructs a new {@link ClassReader} object. + * + * @param name the fully qualified name of the class to be read. + * @throws IOException if an exception occurs during reading. + */ + public ClassReader(final String name) throws IOException { + this(ClassLoader.getSystemResourceAsStream(name.replace('.', '/') + + ".class")); + } + + /** + * Reads the bytecode of a class. + * + * @param is an input stream from which to read the class. + * @return the bytecode read from the given input stream. + * @throws IOException if a problem occurs during reading. + */ + private static byte[] readClass(final InputStream is) throws IOException { + if (is == null) { + throw new IOException("Class not found"); + } + byte[] b = new byte[is.available()]; + int len = 0; + while (true) { + int n = is.read(b, len, b.length - len); + if (n == -1) { + if (len < b.length) { + byte[] c = new byte[len]; + System.arraycopy(b, 0, c, 0, len); + b = c; + } + return b; + } + len += n; + if (len == b.length) { + byte[] c = new byte[b.length + 1000]; + System.arraycopy(b, 0, c, 0, len); + b = c; + } + } + } + + // ------------------------------------------------------------------------ + // Public methods + // ------------------------------------------------------------------------ + + /** + * Makes the given visitor visit the Java class of this {@link ClassReader}. + * This class is the one specified in the constructor (see + * {@link #ClassReader(byte[]) ClassReader}). + * + * @param classVisitor the visitor that must visit this class. + * @param flags option flags that can be used to modify the default behavior + * of this class. See {@link #SKIP_DEBUG}, {@link #EXPAND_FRAMES}, + * {@link #SKIP_FRAMES}, {@link #SKIP_CODE}. + */ + public void accept(final ClassVisitor classVisitor, final int flags) { + accept(classVisitor, new Attribute[0], flags); + } + + /** + * Makes the given visitor visit the Java class of this {@link ClassReader}. + * This class is the one specified in the constructor (see + * {@link #ClassReader(byte[]) ClassReader}). + * + * @param classVisitor the visitor that must visit this class. + * @param attrs prototypes of the attributes that must be parsed during the + * visit of the class. Any attribute whose type is not equal to the + * type of one the prototypes will not be parsed: its byte array + * value will be passed unchanged to the ClassWriter. <i>This may + * corrupt it if this value contains references to the constant pool, + * or has syntactic or semantic links with a class element that has + * been transformed by a class adapter between the reader and the + * writer</i>. + * @param flags option flags that can be used to modify the default behavior + * of this class. See {@link #SKIP_DEBUG}, {@link #EXPAND_FRAMES}, + * {@link #SKIP_FRAMES}, {@link #SKIP_CODE}. + */ + public void accept( + final ClassVisitor classVisitor, + final Attribute[] attrs, + final int flags) + { + byte[] b = this.b; // the bytecode array + char[] c = new char[maxStringLength]; // buffer used to read strings + int i, j, k; // loop variables + int u, v, w; // indexes in b + Attribute attr; + + int access; + String name; + String desc; + String attrName; + String signature; + int anns = 0; + int ianns = 0; + Attribute cattrs = null; + + // visits the header + u = header; + access = readUnsignedShort(u); + name = readClass(u + 2, c); + v = items[readUnsignedShort(u + 4)]; + String superClassName = v == 0 ? null : readUTF8(v, c); + String[] implementedItfs = new String[readUnsignedShort(u + 6)]; + w = 0; + u += 8; + for (i = 0; i < implementedItfs.length; ++i) { + implementedItfs[i] = readClass(u, c); + u += 2; + } + + boolean skipCode = (flags & SKIP_CODE) != 0; + boolean skipDebug = (flags & SKIP_DEBUG) != 0; + boolean unzip = (flags & EXPAND_FRAMES) != 0; + + // skips fields and methods + v = u; + i = readUnsignedShort(v); + v += 2; + for (; i > 0; --i) { + j = readUnsignedShort(v + 6); + v += 8; + for (; j > 0; --j) { + v += 6 + readInt(v + 2); + } + } + i = readUnsignedShort(v); + v += 2; + for (; i > 0; --i) { + j = readUnsignedShort(v + 6); + v += 8; + for (; j > 0; --j) { + v += 6 + readInt(v + 2); + } + } + // reads the class's attributes + signature = null; + String sourceFile = null; + String sourceDebug = null; + String enclosingOwner = null; + String enclosingName = null; + String enclosingDesc = null; + + i = readUnsignedShort(v); + v += 2; + for (; i > 0; --i) { + attrName = readUTF8(v, c); + // tests are sorted in decreasing frequency order + // (based on frequencies observed on typical classes) + if ("SourceFile".equals(attrName)) { + sourceFile = readUTF8(v + 6, c); + } else if ("InnerClasses".equals(attrName)) { + w = v + 6; + } else if ("EnclosingMethod".equals(attrName)) { + enclosingOwner = readClass(v + 6, c); + int item = readUnsignedShort(v + 8); + if (item != 0) { + enclosingName = readUTF8(items[item], c); + enclosingDesc = readUTF8(items[item] + 2, c); + } + } else if (SIGNATURES && "Signature".equals(attrName)) { + signature = readUTF8(v + 6, c); + } else if (ANNOTATIONS && "RuntimeVisibleAnnotations".equals(attrName)) { + anns = v + 6; + } else if ("Deprecated".equals(attrName)) { + access |= Opcodes.ACC_DEPRECATED; + } else if ("Synthetic".equals(attrName)) { + access |= Opcodes.ACC_SYNTHETIC; + } else if ("SourceDebugExtension".equals(attrName)) { + int len = readInt(v + 2); + sourceDebug = readUTF(v + 6, len, new char[len]); + } else if (ANNOTATIONS && "RuntimeInvisibleAnnotations".equals(attrName)) { + ianns = v + 6; + } else { + attr = readAttribute(attrs, + attrName, + v + 6, + readInt(v + 2), + c, + -1, + null); + if (attr != null) { + attr.next = cattrs; + cattrs = attr; + } + } + v += 6 + readInt(v + 2); + } + // calls the visit method + classVisitor.visit(readInt(4), + access, + name, + signature, + superClassName, + implementedItfs); + + // calls the visitSource method + if (!skipDebug && (sourceFile != null || sourceDebug != null)) { + classVisitor.visitSource(sourceFile, sourceDebug); + } + + // calls the visitOuterClass method + if (enclosingOwner != null) { + classVisitor.visitOuterClass(enclosingOwner, + enclosingName, + enclosingDesc); + } + + // visits the class annotations + if (ANNOTATIONS) { + for (i = 1; i >= 0; --i) { + v = i == 0 ? ianns : anns; + if (v != 0) { + j = readUnsignedShort(v); + v += 2; + for (; j > 0; --j) { + v = readAnnotationValues(v + 2, + c, + true, + classVisitor.visitAnnotation(readUTF8(v, c), i != 0)); + } + } + } + } + + // visits the class attributes + while (cattrs != null) { + attr = cattrs.next; + cattrs.next = null; + classVisitor.visitAttribute(cattrs); + cattrs = attr; + } + + // calls the visitInnerClass method + if (w != 0) { + i = readUnsignedShort(w); + w += 2; + for (; i > 0; --i) { + classVisitor.visitInnerClass(readUnsignedShort(w) == 0 + ? null + : readClass(w, c), readUnsignedShort(w + 2) == 0 + ? null + : readClass(w + 2, c), readUnsignedShort(w + 4) == 0 + ? null + : readUTF8(w + 4, c), readUnsignedShort(w + 6)); + w += 8; + } + } + + // visits the fields + i = readUnsignedShort(u); + u += 2; + for (; i > 0; --i) { + access = readUnsignedShort(u); + name = readUTF8(u + 2, c); + desc = readUTF8(u + 4, c); + // visits the field's attributes and looks for a ConstantValue + // attribute + int fieldValueItem = 0; + signature = null; + anns = 0; + ianns = 0; + cattrs = null; + + j = readUnsignedShort(u + 6); + u += 8; + for (; j > 0; --j) { + attrName = readUTF8(u, c); + // tests are sorted in decreasing frequency order + // (based on frequencies observed on typical classes) + if ("ConstantValue".equals(attrName)) { + fieldValueItem = readUnsignedShort(u + 6); + } else if (SIGNATURES && "Signature".equals(attrName)) { + signature = readUTF8(u + 6, c); + } else if ("Deprecated".equals(attrName)) { + access |= Opcodes.ACC_DEPRECATED; + } else if ("Synthetic".equals(attrName)) { + access |= Opcodes.ACC_SYNTHETIC; + } else if (ANNOTATIONS && "RuntimeVisibleAnnotations".equals(attrName)) { + anns = u + 6; + } else if (ANNOTATIONS && "RuntimeInvisibleAnnotations".equals(attrName)) { + ianns = u + 6; + } else { + attr = readAttribute(attrs, + attrName, + u + 6, + readInt(u + 2), + c, + -1, + null); + if (attr != null) { + attr.next = cattrs; + cattrs = attr; + } + } + u += 6 + readInt(u + 2); + } + // visits the field + FieldVisitor fv = classVisitor.visitField(access, + name, + desc, + signature, + fieldValueItem == 0 ? null : readConst(fieldValueItem, c)); + // visits the field annotations and attributes + if (fv != null) { + if (ANNOTATIONS) { + for (j = 1; j >= 0; --j) { + v = j == 0 ? ianns : anns; + if (v != 0) { + k = readUnsignedShort(v); + v += 2; + for (; k > 0; --k) { + v = readAnnotationValues(v + 2, + c, + true, + fv.visitAnnotation(readUTF8(v, c), j != 0)); + } + } + } + } + while (cattrs != null) { + attr = cattrs.next; + cattrs.next = null; + fv.visitAttribute(cattrs); + cattrs = attr; + } + fv.visitEnd(); + } + } + + // visits the methods + i = readUnsignedShort(u); + u += 2; + for (; i > 0; --i) { + int u0 = u + 6; + access = readUnsignedShort(u); + name = readUTF8(u + 2, c); + desc = readUTF8(u + 4, c); + signature = null; + anns = 0; + ianns = 0; + int dann = 0; + int mpanns = 0; + int impanns = 0; + cattrs = null; + v = 0; + w = 0; + + // looks for Code and Exceptions attributes + j = readUnsignedShort(u + 6); + u += 8; + for (; j > 0; --j) { + attrName = readUTF8(u, c); + int attrSize = readInt(u + 2); + u += 6; + // tests are sorted in decreasing frequency order + // (based on frequencies observed on typical classes) + if ("Code".equals(attrName)) { + if (!skipCode) { + v = u; + } + } else if ("Exceptions".equals(attrName)) { + w = u; + } else if (SIGNATURES && "Signature".equals(attrName)) { + signature = readUTF8(u, c); + } else if ("Deprecated".equals(attrName)) { + access |= Opcodes.ACC_DEPRECATED; + } else if (ANNOTATIONS && "RuntimeVisibleAnnotations".equals(attrName)) { + anns = u; + } else if (ANNOTATIONS && "AnnotationDefault".equals(attrName)) { + dann = u; + } else if ("Synthetic".equals(attrName)) { + access |= Opcodes.ACC_SYNTHETIC; + } else if (ANNOTATIONS && "RuntimeInvisibleAnnotations".equals(attrName)) { + ianns = u; + } else if (ANNOTATIONS && "RuntimeVisibleParameterAnnotations".equals(attrName)) + { + mpanns = u; + } else if (ANNOTATIONS && "RuntimeInvisibleParameterAnnotations".equals(attrName)) + { + impanns = u; + } else { + attr = readAttribute(attrs, + attrName, + u, + attrSize, + c, + -1, + null); + if (attr != null) { + attr.next = cattrs; + cattrs = attr; + } + } + u += attrSize; + } + // reads declared exceptions + String[] exceptions; + if (w == 0) { + exceptions = null; + } else { + exceptions = new String[readUnsignedShort(w)]; + w += 2; + for (j = 0; j < exceptions.length; ++j) { + exceptions[j] = readClass(w, c); + w += 2; + } + } + + // visits the method's code, if any + MethodVisitor mv = classVisitor.visitMethod(access, + name, + desc, + signature, + exceptions); + + if (mv != null) { + /* + * if the returned MethodVisitor is in fact a MethodWriter, it + * means there is no method adapter between the reader and the + * writer. If, in addition, the writer's constant pool was + * copied from this reader (mw.cw.cr == this), and the signature + * and exceptions of the method have not been changed, then it + * is possible to skip all visit events and just copy the + * original code of the method to the writer (the access, name + * and descriptor can have been changed, this is not important + * since they are not copied as is from the reader). + */ + if (WRITER && mv instanceof MethodWriter) { + MethodWriter mw = (MethodWriter) mv; + if (mw.cw.cr == this) { + if (signature == mw.signature) { + boolean sameExceptions = false; + if (exceptions == null) { + sameExceptions = mw.exceptionCount == 0; + } else { + if (exceptions.length == mw.exceptionCount) { + sameExceptions = true; + for (j = exceptions.length - 1; j >= 0; --j) + { + w -= 2; + if (mw.exceptions[j] != readUnsignedShort(w)) + { + sameExceptions = false; + break; + } + } + } + } + if (sameExceptions) { + /* + * we do not copy directly the code into + * MethodWriter to save a byte array copy + * operation. The real copy will be done in + * ClassWriter.toByteArray(). + */ + mw.classReaderOffset = u0; + mw.classReaderLength = u - u0; + continue; + } + } + } + } + + if (ANNOTATIONS && dann != 0) { + AnnotationVisitor dv = mv.visitAnnotationDefault(); + readAnnotationValue(dann, c, null, dv); + if (dv != null) { + dv.visitEnd(); + } + } + if (ANNOTATIONS) { + for (j = 1; j >= 0; --j) { + w = j == 0 ? ianns : anns; + if (w != 0) { + k = readUnsignedShort(w); + w += 2; + for (; k > 0; --k) { + w = readAnnotationValues(w + 2, + c, + true, + mv.visitAnnotation(readUTF8(w, c), j != 0)); + } + } + } + } + if (ANNOTATIONS && mpanns != 0) { + readParameterAnnotations(mpanns, desc, c, true, mv); + } + if (ANNOTATIONS && impanns != 0) { + readParameterAnnotations(impanns, desc, c, false, mv); + } + while (cattrs != null) { + attr = cattrs.next; + cattrs.next = null; + mv.visitAttribute(cattrs); + cattrs = attr; + } + } + + if (mv != null && v != 0) { + int maxStack = readUnsignedShort(v); + int maxLocals = readUnsignedShort(v + 2); + int codeLength = readInt(v + 4); + v += 8; + + int codeStart = v; + int codeEnd = v + codeLength; + + mv.visitCode(); + + // 1st phase: finds the labels + int label; + Label[] labels = new Label[codeLength + 2]; + readLabel(codeLength + 1, labels); + while (v < codeEnd) { + w = v - codeStart; + int opcode = b[v] & 0xFF; + switch (ClassWriter.TYPE[opcode]) { + case ClassWriter.NOARG_INSN: + case ClassWriter.IMPLVAR_INSN: + v += 1; + break; + case ClassWriter.LABEL_INSN: + readLabel(w + readShort(v + 1), labels); + v += 3; + break; + case ClassWriter.LABELW_INSN: + readLabel(w + readInt(v + 1), labels); + v += 5; + break; + case ClassWriter.WIDE_INSN: + opcode = b[v + 1] & 0xFF; + if (opcode == Opcodes.IINC) { + v += 6; + } else { + v += 4; + } + break; + case ClassWriter.TABL_INSN: + // skips 0 to 3 padding bytes* + v = v + 4 - (w & 3); + // reads instruction + readLabel(w + readInt(v), labels); + j = readInt(v + 8) - readInt(v + 4) + 1; + v += 12; + for (; j > 0; --j) { + readLabel(w + readInt(v), labels); + v += 4; + } + break; + case ClassWriter.LOOK_INSN: + // skips 0 to 3 padding bytes* + v = v + 4 - (w & 3); + // reads instruction + readLabel(w + readInt(v), labels); + j = readInt(v + 4); + v += 8; + for (; j > 0; --j) { + readLabel(w + readInt(v + 4), labels); + v += 8; + } + break; + case ClassWriter.VAR_INSN: + case ClassWriter.SBYTE_INSN: + case ClassWriter.LDC_INSN: + v += 2; + break; + case ClassWriter.SHORT_INSN: + case ClassWriter.LDCW_INSN: + case ClassWriter.FIELDORMETH_INSN: + case ClassWriter.TYPE_INSN: + case ClassWriter.IINC_INSN: + v += 3; + break; + case ClassWriter.ITFMETH_INSN: + v += 5; + break; + // case MANA_INSN: + default: + v += 4; + break; + } + } + // parses the try catch entries + j = readUnsignedShort(v); + v += 2; + for (; j > 0; --j) { + Label start = readLabel(readUnsignedShort(v), labels); + Label end = readLabel(readUnsignedShort(v + 2), labels); + Label handler = readLabel(readUnsignedShort(v + 4), labels); + int type = readUnsignedShort(v + 6); + if (type == 0) { + mv.visitTryCatchBlock(start, end, handler, null); + } else { + mv.visitTryCatchBlock(start, + end, + handler, + readUTF8(items[type], c)); + } + v += 8; + } + // parses the local variable, line number tables, and code + // attributes + int varTable = 0; + int varTypeTable = 0; + int stackMap = 0; + int frameCount = 0; + int frameMode = 0; + int frameOffset = 0; + int frameLocalCount = 0; + int frameLocalDiff = 0; + int frameStackCount = 0; + Object[] frameLocal = null; + Object[] frameStack = null; + boolean zip = true; + cattrs = null; + j = readUnsignedShort(v); + v += 2; + for (; j > 0; --j) { + attrName = readUTF8(v, c); + if ("LocalVariableTable".equals(attrName)) { + if (!skipDebug) { + varTable = v + 6; + k = readUnsignedShort(v + 6); + w = v + 8; + for (; k > 0; --k) { + label = readUnsignedShort(w); + if (labels[label] == null) { + readLabel(label, labels).status |= Label.DEBUG; + } + label += readUnsignedShort(w + 2); + if (labels[label] == null) { + readLabel(label, labels).status |= Label.DEBUG; + } + w += 10; + } + } + } else if ("LocalVariableTypeTable".equals(attrName)) { + varTypeTable = v + 6; + } else if ("LineNumberTable".equals(attrName)) { + if (!skipDebug) { + k = readUnsignedShort(v + 6); + w = v + 8; + for (; k > 0; --k) { + label = readUnsignedShort(w); + if (labels[label] == null) { + readLabel(label, labels).status |= Label.DEBUG; + } + labels[label].line = readUnsignedShort(w + 2); + w += 4; + } + } + } else if (FRAMES && "StackMapTable".equals(attrName)) { + if ((flags & SKIP_FRAMES) == 0) { + stackMap = v + 8; + frameCount = readUnsignedShort(v + 6); + } + /* + * here we do not extract the labels corresponding to + * the attribute content. This would require a full + * parsing of the attribute, which would need to be + * repeated in the second phase (see below). Instead the + * content of the attribute is read one frame at a time + * (i.e. after a frame has been visited, the next frame + * is read), and the labels it contains are also + * extracted one frame at a time. Thanks to the ordering + * of frames, having only a "one frame lookahead" is not + * a problem, i.e. it is not possible to see an offset + * smaller than the offset of the current insn and for + * which no Label exist. + */ + // TODO true for frame offsets, + // but for UNINITIALIZED type offsets? + } else if (FRAMES && "StackMap".equals(attrName)) { + if ((flags & SKIP_FRAMES) == 0) { + stackMap = v + 8; + frameCount = readUnsignedShort(v + 6); + zip = false; + } + /* + * IMPORTANT! here we assume that the frames are + * ordered, as in the StackMapTable attribute, although + * this is not guaranteed by the attribute format. + */ + } else { + for (k = 0; k < attrs.length; ++k) { + if (attrs[k].type.equals(attrName)) { + attr = attrs[k].read(this, + v + 6, + readInt(v + 2), + c, + codeStart - 8, + labels); + if (attr != null) { + attr.next = cattrs; + cattrs = attr; + } + } + } + } + v += 6 + readInt(v + 2); + } + + // 2nd phase: visits each instruction + if (FRAMES && stackMap != 0) { + // creates the very first (implicit) frame from the method + // descriptor + frameLocal = new Object[maxLocals]; + frameStack = new Object[maxStack]; + if (unzip) { + int local = 0; + if ((access & Opcodes.ACC_STATIC) == 0) { + if ("<init>".equals(name)) { + frameLocal[local++] = Opcodes.UNINITIALIZED_THIS; + } else { + frameLocal[local++] = readClass(header + 2, c); + } + } + j = 1; + loop: while (true) { + k = j; + switch (desc.charAt(j++)) { + case 'Z': + case 'C': + case 'B': + case 'S': + case 'I': + frameLocal[local++] = Opcodes.INTEGER; + break; + case 'F': + frameLocal[local++] = Opcodes.FLOAT; + break; + case 'J': + frameLocal[local++] = Opcodes.LONG; + break; + case 'D': + frameLocal[local++] = Opcodes.DOUBLE; + break; + case '[': + while (desc.charAt(j) == '[') { + ++j; + } + if (desc.charAt(j) == 'L') { + ++j; + while (desc.charAt(j) != ';') { + ++j; + } + } + frameLocal[local++] = desc.substring(k, ++j); + break; + case 'L': + while (desc.charAt(j) != ';') { + ++j; + } + frameLocal[local++] = desc.substring(k + 1, + j++); + break; + default: + break loop; + } + } + frameLocalCount = local; + } + /* + * for the first explicit frame the offset is not + * offset_delta + 1 but only offset_delta; setting the + * implicit frame offset to -1 allow the use of the + * "offset_delta + 1" rule in all cases + */ + frameOffset = -1; + } + v = codeStart; + Label l; + while (v < codeEnd) { + w = v - codeStart; + + l = labels[w]; + if (l != null) { + mv.visitLabel(l); + if (!skipDebug && l.line > 0) { + mv.visitLineNumber(l.line, l); + } + } + + while (FRAMES && frameLocal != null + && (frameOffset == w || frameOffset == -1)) + { + // if there is a frame for this offset, + // makes the visitor visit it, + // and reads the next frame if there is one. + if (!zip || unzip) { + mv.visitFrame(Opcodes.F_NEW, + frameLocalCount, + frameLocal, + frameStackCount, + frameStack); + } else if (frameOffset != -1) { + mv.visitFrame(frameMode, + frameLocalDiff, + frameLocal, + frameStackCount, + frameStack); + } + + if (frameCount > 0) { + int tag, delta, n; + if (zip) { + tag = b[stackMap++] & 0xFF; + } else { + tag = MethodWriter.FULL_FRAME; + frameOffset = -1; + } + frameLocalDiff = 0; + if (tag < MethodWriter.SAME_LOCALS_1_STACK_ITEM_FRAME) + { + delta = tag; + frameMode = Opcodes.F_SAME; + frameStackCount = 0; + } else if (tag < MethodWriter.RESERVED) { + delta = tag + - MethodWriter.SAME_LOCALS_1_STACK_ITEM_FRAME; + stackMap = readFrameType(frameStack, + 0, + stackMap, + c, + labels); + frameMode = Opcodes.F_SAME1; + frameStackCount = 1; + } else { + delta = readUnsignedShort(stackMap); + stackMap += 2; + if (tag == MethodWriter.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED) + { + stackMap = readFrameType(frameStack, + 0, + stackMap, + c, + labels); + frameMode = Opcodes.F_SAME1; + frameStackCount = 1; + } else if (tag >= MethodWriter.CHOP_FRAME + && tag < MethodWriter.SAME_FRAME_EXTENDED) + { + frameMode = Opcodes.F_CHOP; + frameLocalDiff = MethodWriter.SAME_FRAME_EXTENDED + - tag; + frameLocalCount -= frameLocalDiff; + frameStackCount = 0; + } else if (tag == MethodWriter.SAME_FRAME_EXTENDED) + { + frameMode = Opcodes.F_SAME; + frameStackCount = 0; + } else if (tag < MethodWriter.FULL_FRAME) { + j = unzip ? frameLocalCount : 0; + for (k = tag + - MethodWriter.SAME_FRAME_EXTENDED; k > 0; k--) + { + stackMap = readFrameType(frameLocal, + j++, + stackMap, + c, + labels); + } + frameMode = Opcodes.F_APPEND; + frameLocalDiff = tag + - MethodWriter.SAME_FRAME_EXTENDED; + frameLocalCount += frameLocalDiff; + frameStackCount = 0; + } else { // if (tag == FULL_FRAME) { + frameMode = Opcodes.F_FULL; + n = frameLocalDiff = frameLocalCount = readUnsignedShort(stackMap); + stackMap += 2; + for (j = 0; n > 0; n--) { + stackMap = readFrameType(frameLocal, + j++, + stackMap, + c, + labels); + } + n = frameStackCount = readUnsignedShort(stackMap); + stackMap += 2; + for (j = 0; n > 0; n--) { + stackMap = readFrameType(frameStack, + j++, + stackMap, + c, + labels); + } + } + } + frameOffset += delta + 1; + readLabel(frameOffset, labels); + + --frameCount; + } else { + frameLocal = null; + } + } + + int opcode = b[v] & 0xFF; + switch (ClassWriter.TYPE[opcode]) { + case ClassWriter.NOARG_INSN: + mv.visitInsn(opcode); + v += 1; + break; + case ClassWriter.IMPLVAR_INSN: + if (opcode > Opcodes.ISTORE) { + opcode -= 59; // ISTORE_0 + mv.visitVarInsn(Opcodes.ISTORE + (opcode >> 2), + opcode & 0x3); + } else { + opcode -= 26; // ILOAD_0 + mv.visitVarInsn(Opcodes.ILOAD + (opcode >> 2), + opcode & 0x3); + } + v += 1; + break; + case ClassWriter.LABEL_INSN: + mv.visitJumpInsn(opcode, labels[w + + readShort(v + 1)]); + v += 3; + break; + case ClassWriter.LABELW_INSN: + mv.visitJumpInsn(opcode - 33, labels[w + + readInt(v + 1)]); + v += 5; + break; + case ClassWriter.WIDE_INSN: + opcode = b[v + 1] & 0xFF; + if (opcode == Opcodes.IINC) { + mv.visitIincInsn(readUnsignedShort(v + 2), + readShort(v + 4)); + v += 6; + } else { + mv.visitVarInsn(opcode, + readUnsignedShort(v + 2)); + v += 4; + } + break; + case ClassWriter.TABL_INSN: + // skips 0 to 3 padding bytes + v = v + 4 - (w & 3); + // reads instruction + label = w + readInt(v); + int min = readInt(v + 4); + int max = readInt(v + 8); + v += 12; + Label[] table = new Label[max - min + 1]; + for (j = 0; j < table.length; ++j) { + table[j] = labels[w + readInt(v)]; + v += 4; + } + mv.visitTableSwitchInsn(min, + max, + labels[label], + table); + break; + case ClassWriter.LOOK_INSN: + // skips 0 to 3 padding bytes + v = v + 4 - (w & 3); + // reads instruction + label = w + readInt(v); + j = readInt(v + 4); + v += 8; + int[] keys = new int[j]; + Label[] values = new Label[j]; + for (j = 0; j < keys.length; ++j) { + keys[j] = readInt(v); + values[j] = labels[w + readInt(v + 4)]; + v += 8; + } + mv.visitLookupSwitchInsn(labels[label], + keys, + values); + break; + case ClassWriter.VAR_INSN: + mv.visitVarInsn(opcode, b[v + 1] & 0xFF); + v += 2; + break; + case ClassWriter.SBYTE_INSN: + mv.visitIntInsn(opcode, b[v + 1]); + v += 2; + break; + case ClassWriter.SHORT_INSN: + mv.visitIntInsn(opcode, readShort(v + 1)); + v += 3; + break; + case ClassWriter.LDC_INSN: + mv.visitLdcInsn(readConst(b[v + 1] & 0xFF, c)); + v += 2; + break; + case ClassWriter.LDCW_INSN: + mv.visitLdcInsn(readConst(readUnsignedShort(v + 1), + c)); + v += 3; + break; + case ClassWriter.FIELDORMETH_INSN: + case ClassWriter.ITFMETH_INSN: + int cpIndex = items[readUnsignedShort(v + 1)]; + String iowner = readClass(cpIndex, c); + cpIndex = items[readUnsignedShort(cpIndex + 2)]; + String iname = readUTF8(cpIndex, c); + String idesc = readUTF8(cpIndex + 2, c); + if (opcode < Opcodes.INVOKEVIRTUAL) { + mv.visitFieldInsn(opcode, iowner, iname, idesc); + } else { + mv.visitMethodInsn(opcode, iowner, iname, idesc); + } + if (opcode == Opcodes.INVOKEINTERFACE) { + v += 5; + } else { + v += 3; + } + break; + case ClassWriter.TYPE_INSN: + mv.visitTypeInsn(opcode, readClass(v + 1, c)); + v += 3; + break; + case ClassWriter.IINC_INSN: + mv.visitIincInsn(b[v + 1] & 0xFF, b[v + 2]); + v += 3; + break; + // case MANA_INSN: + default: + mv.visitMultiANewArrayInsn(readClass(v + 1, c), + b[v + 3] & 0xFF); + v += 4; + break; + } + } + l = labels[codeEnd - codeStart]; + if (l != null) { + mv.visitLabel(l); + } + // visits the local variable tables + if (!skipDebug && varTable != 0) { + int[] typeTable = null; + if (varTypeTable != 0) { + k = readUnsignedShort(varTypeTable) * 3; + w = varTypeTable + 2; + typeTable = new int[k]; + while (k > 0) { + typeTable[--k] = w + 6; // signature + typeTable[--k] = readUnsignedShort(w + 8); // index + typeTable[--k] = readUnsignedShort(w); // start + w += 10; + } + } + k = readUnsignedShort(varTable); + w = varTable + 2; + for (; k > 0; --k) { + int start = readUnsignedShort(w); + int length = readUnsignedShort(w + 2); + int index = readUnsignedShort(w + 8); + String vsignature = null; + if (typeTable != null) { + for (int a = 0; a < typeTable.length; a += 3) { + if (typeTable[a] == start + && typeTable[a + 1] == index) + { + vsignature = readUTF8(typeTable[a + 2], c); + break; + } + } + } + mv.visitLocalVariable(readUTF8(w + 4, c), + readUTF8(w + 6, c), + vsignature, + labels[start], + labels[start + length], + index); + w += 10; + } + } + // visits the other attributes + while (cattrs != null) { + attr = cattrs.next; + cattrs.next = null; + mv.visitAttribute(cattrs); + cattrs = attr; + } + // visits the max stack and max locals values + mv.visitMaxs(maxStack, maxLocals); + } + + if (mv != null) { + mv.visitEnd(); + } + } + + // visits the end of the class + classVisitor.visitEnd(); + } + + /** + * Reads parameter annotations and makes the given visitor visit them. + * + * @param v start offset in {@link #b b} of the annotations to be read. + * @param desc the method descriptor. + * @param buf buffer to be used to call {@link #readUTF8 readUTF8}, + * {@link #readClass(int,char[]) readClass} or + * {@link #readConst readConst}. + * @param visible <tt>true</tt> if the annotations to be read are visible + * at runtime. + * @param mv the visitor that must visit the annotations. + */ + private void readParameterAnnotations( + int v, + final String desc, + final char[] buf, + final boolean visible, + final MethodVisitor mv) + { + int i; + int n = b[v++] & 0xFF; + // workaround for a bug in javac (javac compiler generates a parameter + // annotation array whose size is equal to the number of parameters in + // the Java source file, while it should generate an array whose size is + // equal to the number of parameters in the method descriptor - which + // includes the synthetic parameters added by the compiler). This work- + // around supposes that the synthetic parameters are the first ones. + int synthetics = Type.getArgumentTypes(desc).length - n; + AnnotationVisitor av; + for (i = 0; i < synthetics; ++i) { + // virtual annotation to detect synthetic parameters in MethodWriter + av = mv.visitParameterAnnotation(i, "Ljava/lang/Synthetic;", false); + if (av != null) { + av.visitEnd(); + } + } + for (; i < n + synthetics; ++i) { + int j = readUnsignedShort(v); + v += 2; + for (; j > 0; --j) { + av = mv.visitParameterAnnotation(i, readUTF8(v, buf), visible); + v = readAnnotationValues(v + 2, buf, true, av); + } + } + } + + /** + * Reads the values of an annotation and makes the given visitor visit them. + * + * @param v the start offset in {@link #b b} of the values to be read + * (including the unsigned short that gives the number of values). + * @param buf buffer to be used to call {@link #readUTF8 readUTF8}, + * {@link #readClass(int,char[]) readClass} or + * {@link #readConst readConst}. + * @param named if the annotation values are named or not. + * @param av the visitor that must visit the values. + * @return the end offset of the annotation values. + */ + private int readAnnotationValues( + int v, + final char[] buf, + final boolean named, + final AnnotationVisitor av) + { + int i = readUnsignedShort(v); + v += 2; + if (named) { + for (; i > 0; --i) { + v = readAnnotationValue(v + 2, buf, readUTF8(v, buf), av); + } + } else { + for (; i > 0; --i) { + v = readAnnotationValue(v, buf, null, av); + } + } + if (av != null) { + av.visitEnd(); + } + return v; + } + + /** + * Reads a value of an annotation and makes the given visitor visit it. + * + * @param v the start offset in {@link #b b} of the value to be read (<i>not + * including the value name constant pool index</i>). + * @param buf buffer to be used to call {@link #readUTF8 readUTF8}, + * {@link #readClass(int,char[]) readClass} or + * {@link #readConst readConst}. + * @param name the name of the value to be read. + * @param av the visitor that must visit the value. + * @return the end offset of the annotation value. + */ + private int readAnnotationValue( + int v, + final char[] buf, + final String name, + final AnnotationVisitor av) + { + int i; + if (av == null) { + switch (b[v] & 0xFF) { + case 'e': // enum_const_value + return v + 5; + case '@': // annotation_value + return readAnnotationValues(v + 3, buf, true, null); + case '[': // array_value + return readAnnotationValues(v + 1, buf, false, null); + default: + return v + 3; + } + } + switch (b[v++] & 0xFF) { + case 'I': // pointer to CONSTANT_Integer + case 'J': // pointer to CONSTANT_Long + case 'F': // pointer to CONSTANT_Float + case 'D': // pointer to CONSTANT_Double + av.visit(name, readConst(readUnsignedShort(v), buf)); + v += 2; + break; + case 'B': // pointer to CONSTANT_Byte + av.visit(name, + new Byte((byte) readInt(items[readUnsignedShort(v)]))); + v += 2; + break; + case 'Z': // pointer to CONSTANT_Boolean + av.visit(name, readInt(items[readUnsignedShort(v)]) == 0 + ? Boolean.FALSE + : Boolean.TRUE); + v += 2; + break; + case 'S': // pointer to CONSTANT_Short + av.visit(name, + new Short((short) readInt(items[readUnsignedShort(v)]))); + v += 2; + break; + case 'C': // pointer to CONSTANT_Char + av.visit(name, + new Character((char) readInt(items[readUnsignedShort(v)]))); + v += 2; + break; + case 's': // pointer to CONSTANT_Utf8 + av.visit(name, readUTF8(v, buf)); + v += 2; + break; + case 'e': // enum_const_value + av.visitEnum(name, readUTF8(v, buf), readUTF8(v + 2, buf)); + v += 4; + break; + case 'c': // class_info + av.visit(name, Type.getType(readUTF8(v, buf))); + v += 2; + break; + case '@': // annotation_value + v = readAnnotationValues(v + 2, + buf, + true, + av.visitAnnotation(name, readUTF8(v, buf))); + break; + case '[': // array_value + int size = readUnsignedShort(v); + v += 2; + if (size == 0) { + return readAnnotationValues(v - 2, + buf, + false, + av.visitArray(name)); + } + switch (this.b[v++] & 0xFF) { + case 'B': + byte[] bv = new byte[size]; + for (i = 0; i < size; i++) { + bv[i] = (byte) readInt(items[readUnsignedShort(v)]); + v += 3; + } + av.visit(name, bv); + --v; + break; + case 'Z': + boolean[] zv = new boolean[size]; + for (i = 0; i < size; i++) { + zv[i] = readInt(items[readUnsignedShort(v)]) != 0; + v += 3; + } + av.visit(name, zv); + --v; + break; + case 'S': + short[] sv = new short[size]; + for (i = 0; i < size; i++) { + sv[i] = (short) readInt(items[readUnsignedShort(v)]); + v += 3; + } + av.visit(name, sv); + --v; + break; + case 'C': + char[] cv = new char[size]; + for (i = 0; i < size; i++) { + cv[i] = (char) readInt(items[readUnsignedShort(v)]); + v += 3; + } + av.visit(name, cv); + --v; + break; + case 'I': + int[] iv = new int[size]; + for (i = 0; i < size; i++) { + iv[i] = readInt(items[readUnsignedShort(v)]); + v += 3; + } + av.visit(name, iv); + --v; + break; + case 'J': + long[] lv = new long[size]; + for (i = 0; i < size; i++) { + lv[i] = readLong(items[readUnsignedShort(v)]); + v += 3; + } + av.visit(name, lv); + --v; + break; + case 'F': + float[] fv = new float[size]; + for (i = 0; i < size; i++) { + fv[i] = Float.intBitsToFloat(readInt(items[readUnsignedShort(v)])); + v += 3; + } + av.visit(name, fv); + --v; + break; + case 'D': + double[] dv = new double[size]; + for (i = 0; i < size; i++) { + dv[i] = Double.longBitsToDouble(readLong(items[readUnsignedShort(v)])); + v += 3; + } + av.visit(name, dv); + --v; + break; + default: + v = readAnnotationValues(v - 3, + buf, + false, + av.visitArray(name)); + } + } + return v; + } + + private int readFrameType( + final Object[] frame, + final int index, + int v, + final char[] buf, + final Label[] labels) + { + int type = b[v++] & 0xFF; + switch (type) { + case 0: + frame[index] = Opcodes.TOP; + break; + case 1: + frame[index] = Opcodes.INTEGER; + break; + case 2: + frame[index] = Opcodes.FLOAT; + break; + case 3: + frame[index] = Opcodes.DOUBLE; + break; + case 4: + frame[index] = Opcodes.LONG; + break; + case 5: + frame[index] = Opcodes.NULL; + break; + case 6: + frame[index] = Opcodes.UNINITIALIZED_THIS; + break; + case 7: // Object + frame[index] = readClass(v, buf); + v += 2; + break; + default: // Uninitialized + frame[index] = readLabel(readUnsignedShort(v), labels); + v += 2; + } + return v; + } + + /** + * Returns the label corresponding to the given offset. The default + * implementation of this method creates a label for the given offset if it + * has not been already created. + * + * @param offset a bytecode offset in a method. + * @param labels the already created labels, indexed by their offset. If a + * label already exists for offset this method must not create a new + * one. Otherwise it must store the new label in this array. + * @return a non null Label, which must be equal to labels[offset]. + */ + protected Label readLabel(int offset, Label[] labels) { + if (labels[offset] == null) { + labels[offset] = new Label(); + } + return labels[offset]; + } + + /** + * Reads an attribute in {@link #b b}. + * + * @param attrs prototypes of the attributes that must be parsed during the + * visit of the class. Any attribute whose type is not equal to the + * type of one the prototypes is ignored (i.e. an empty + * {@link Attribute} instance is returned). + * @param type the type of the attribute. + * @param off index of the first byte of the attribute's content in + * {@link #b b}. The 6 attribute header bytes, containing the type + * and the length of the attribute, are not taken into account here + * (they have already been read). + * @param len the length of the attribute's content. + * @param buf buffer to be used to call {@link #readUTF8 readUTF8}, + * {@link #readClass(int,char[]) readClass} or + * {@link #readConst readConst}. + * @param codeOff index of the first byte of code's attribute content in + * {@link #b b}, or -1 if the attribute to be read is not a code + * attribute. The 6 attribute header bytes, containing the type and + * the length of the attribute, are not taken into account here. + * @param labels the labels of the method's code, or <tt>null</tt> if the + * attribute to be read is not a code attribute. + * @return the attribute that has been read, or <tt>null</tt> to skip this + * attribute. + */ + private Attribute readAttribute( + final Attribute[] attrs, + final String type, + final int off, + final int len, + final char[] buf, + final int codeOff, + final Label[] labels) + { + for (int i = 0; i < attrs.length; ++i) { + if (attrs[i].type.equals(type)) { + return attrs[i].read(this, off, len, buf, codeOff, labels); + } + } + return new Attribute(type).read(this, off, len, null, -1, null); + } + + // ------------------------------------------------------------------------ + // Utility methods: low level parsing + // ------------------------------------------------------------------------ + + /** + * Returns the start index of the constant pool item in {@link #b b}, plus + * one. <i>This method is intended for {@link Attribute} sub classes, and is + * normally not needed by class generators or adapters.</i> + * + * @param item the index a constant pool item. + * @return the start index of the constant pool item in {@link #b b}, plus + * one. + */ + public int getItem(final int item) { + return items[item]; + } + + /** + * Reads a byte value in {@link #b b}. <i>This method is intended for + * {@link Attribute} sub classes, and is normally not needed by class + * generators or adapters.</i> + * + * @param index the start index of the value to be read in {@link #b b}. + * @return the read value. + */ + public int readByte(final int index) { + return b[index] & 0xFF; + } + + /** + * Reads an unsigned short value in {@link #b b}. <i>This method is + * intended for {@link Attribute} sub classes, and is normally not needed by + * class generators or adapters.</i> + * + * @param index the start index of the value to be read in {@link #b b}. + * @return the read value. + */ + public int readUnsignedShort(final int index) { + byte[] b = this.b; + return ((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF); + } + + /** + * Reads a signed short value in {@link #b b}. <i>This method is intended + * for {@link Attribute} sub classes, and is normally not needed by class + * generators or adapters.</i> + * + * @param index the start index of the value to be read in {@link #b b}. + * @return the read value. + */ + public short readShort(final int index) { + byte[] b = this.b; + return (short) (((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF)); + } + + /** + * Reads a signed int value in {@link #b b}. <i>This method is intended for + * {@link Attribute} sub classes, and is normally not needed by class + * generators or adapters.</i> + * + * @param index the start index of the value to be read in {@link #b b}. + * @return the read value. + */ + public int readInt(final int index) { + byte[] b = this.b; + return ((b[index] & 0xFF) << 24) | ((b[index + 1] & 0xFF) << 16) + | ((b[index + 2] & 0xFF) << 8) | (b[index + 3] & 0xFF); + } + + /** + * Reads a signed long value in {@link #b b}. <i>This method is intended + * for {@link Attribute} sub classes, and is normally not needed by class + * generators or adapters.</i> + * + * @param index the start index of the value to be read in {@link #b b}. + * @return the read value. + */ + public long readLong(final int index) { + long l1 = readInt(index); + long l0 = readInt(index + 4) & 0xFFFFFFFFL; + return (l1 << 32) | l0; + } + + /** + * Reads an UTF8 string constant pool item in {@link #b b}. <i>This method + * is intended for {@link Attribute} sub classes, and is normally not needed + * by class generators or adapters.</i> + * + * @param index the start index of an unsigned short value in {@link #b b}, + * whose value is the index of an UTF8 constant pool item. + * @param buf buffer to be used to read the item. This buffer must be + * sufficiently large. It is not automatically resized. + * @return the String corresponding to the specified UTF8 item. + */ + public String readUTF8(int index, final char[] buf) { + int item = readUnsignedShort(index); + String s = strings[item]; + if (s != null) { + return s; + } + index = items[item]; + return strings[item] = readUTF(index + 2, readUnsignedShort(index), buf); + } + + /** + * Reads UTF8 string in {@link #b b}. + * + * @param index start offset of the UTF8 string to be read. + * @param utfLen length of the UTF8 string to be read. + * @param buf buffer to be used to read the string. This buffer must be + * sufficiently large. It is not automatically resized. + * @return the String corresponding to the specified UTF8 string. + */ + private String readUTF(int index, final int utfLen, final char[] buf) { + int endIndex = index + utfLen; + byte[] b = this.b; + int strLen = 0; + int c, d, e; + while (index < endIndex) { + c = b[index++] & 0xFF; + switch (c >> 4) { + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + // 0xxxxxxx + buf[strLen++] = (char) c; + break; + case 12: + case 13: + // 110x xxxx 10xx xxxx + d = b[index++]; + buf[strLen++] = (char) (((c & 0x1F) << 6) | (d & 0x3F)); + break; + default: + // 1110 xxxx 10xx xxxx 10xx xxxx + d = b[index++]; + e = b[index++]; + buf[strLen++] = (char) (((c & 0x0F) << 12) + | ((d & 0x3F) << 6) | (e & 0x3F)); + break; + } + } + return new String(buf, 0, strLen); + } + + /** + * Reads a class constant pool item in {@link #b b}. <i>This method is + * intended for {@link Attribute} sub classes, and is normally not needed by + * class generators or adapters.</i> + * + * @param index the start index of an unsigned short value in {@link #b b}, + * whose value is the index of a class constant pool item. + * @param buf buffer to be used to read the item. This buffer must be + * sufficiently large. It is not automatically resized. + * @return the String corresponding to the specified class item. + */ + public String readClass(final int index, final char[] buf) { + // computes the start index of the CONSTANT_Class item in b + // and reads the CONSTANT_Utf8 item designated by + // the first two bytes of this CONSTANT_Class item + return readUTF8(items[readUnsignedShort(index)], buf); + } + + /** + * Reads a numeric or string constant pool item in {@link #b b}. <i>This + * method is intended for {@link Attribute} sub classes, and is normally not + * needed by class generators or adapters.</i> + * + * @param item the index of a constant pool item. + * @param buf buffer to be used to read the item. This buffer must be + * sufficiently large. It is not automatically resized. + * @return the {@link Integer}, {@link Float}, {@link Long}, + * {@link Double}, {@link String} or {@link Type} corresponding to + * the given constant pool item. + */ + public Object readConst(final int item, final char[] buf) { + int index = items[item]; + switch (b[index - 1]) { + case ClassWriter.INT: + return new Integer(readInt(index)); + case ClassWriter.FLOAT: + return new Float(Float.intBitsToFloat(readInt(index))); + case ClassWriter.LONG: + return new Long(readLong(index)); + case ClassWriter.DOUBLE: + return new Double(Double.longBitsToDouble(readLong(index))); + case ClassWriter.CLASS: + return Type.getObjectType(readUTF8(index, buf)); + // case ClassWriter.STR: + default: + return readUTF8(index, buf); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/ws/org/objectweb/asm/ClassVisitor.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,226 @@ +/* + * Copyright 2005-2009 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2007 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.sun.xml.internal.ws.org.objectweb.asm; + +/** + * A visitor to visit a Java class. The methods of this interface must be called + * in the following order: <tt>visit</tt> [ <tt>visitSource</tt> ] [ + * <tt>visitOuterClass</tt> ] ( <tt>visitAnnotation</tt> | + * <tt>visitAttribute</tt> )* (<tt>visitInnerClass</tt> | + * <tt>visitField</tt> | <tt>visitMethod</tt> )* <tt>visitEnd</tt>. + * + * @author Eric Bruneton + */ +public interface ClassVisitor { + + /** + * Visits the header of the class. + * + * @param version the class version. + * @param access the class's access flags (see {@link Opcodes}). This + * parameter also indicates if the class is deprecated. + * @param name the internal name of the class (see + * {@link Type#getInternalName() getInternalName}). + * @param signature the signature of this class. May be <tt>null</tt> if + * the class is not a generic one, and does not extend or implement + * generic classes or interfaces. + * @param superName the internal of name of the super class (see + * {@link Type#getInternalName() getInternalName}). For interfaces, + * the super class is {@link Object}. May be <tt>null</tt>, but + * only for the {@link Object} class. + * @param interfaces the internal names of the class's interfaces (see + * {@link Type#getInternalName() getInternalName}). May be + * <tt>null</tt>. + */ + void visit( + int version, + int access, + String name, + String signature, + String superName, + String[] interfaces); + + /** + * Visits the source of the class. + * + * @param source the name of the source file from which the class was + * compiled. May be <tt>null</tt>. + * @param debug additional debug information to compute the correspondance + * between source and compiled elements of the class. May be + * <tt>null</tt>. + */ + void visitSource(String source, String debug); + + /** + * Visits the enclosing class of the class. This method must be called only + * if the class has an enclosing class. + * + * @param owner internal name of the enclosing class of the class. + * @param name the name of the method that contains the class, or + * <tt>null</tt> if the class is not enclosed in a method of its + * enclosing class. + * @param desc the descriptor of the method that contains the class, or + * <tt>null</tt> if the class is not enclosed in a method of its + * enclosing class. + */ + void visitOuterClass(String owner, String name, String desc); + + /** + * Visits an annotation of the class. + * + * @param desc the class descriptor of the annotation class. + * @param visible <tt>true</tt> if the annotation is visible at runtime. + * @return a visitor to visit the annotation values, or <tt>null</tt> if + * this visitor is not interested in visiting this annotation. + */ + AnnotationVisitor visitAnnotation(String desc, boolean visible); + + /** + * Visits a non standard attribute of the class. + * + * @param attr an attribute. + */ + void visitAttribute(Attribute attr); + + /** + * Visits information about an inner class. This inner class is not + * necessarily a member of the class being visited. + * + * @param name the internal name of an inner class (see + * {@link Type#getInternalName() getInternalName}). + * @param outerName the internal name of the class to which the inner class + * belongs (see {@link Type#getInternalName() getInternalName}). May + * be <tt>null</tt> for not member classes. + * @param innerName the (simple) name of the inner class inside its + * enclosing class. May be <tt>null</tt> for anonymous inner + * classes. + * @param access the access flags of the inner class as originally declared + * in the enclosing class. + */ + void visitInnerClass( + String name, + String outerName, + String innerName, + int access); + + /** + * Visits a field of the class. + * + * @param access the field's access flags (see {@link Opcodes}). This + * parameter also indicates if the field is synthetic and/or + * deprecated. + * @param name the field's name. + * @param desc the field's descriptor (see {@link Type Type}). + * @param signature the field's signature. May be <tt>null</tt> if the + * field's type does not use generic types. + * @param value the field's initial value. This parameter, which may be + * <tt>null</tt> if the field does not have an initial value, must + * be an {@link Integer}, a {@link Float}, a {@link Long}, a + * {@link Double} or a {@link String} (for <tt>int</tt>, + * <tt>float</tt>, <tt>long</tt> or <tt>String</tt> fields + * respectively). <i>This parameter is only used for static fields</i>. + * Its value is ignored for non static fields, which must be + * initialized through bytecode instructions in constructors or + * methods. + * @return a visitor to visit field annotations and attributes, or + * <tt>null</tt> if this class visitor is not interested in + * visiting these annotations and attributes. + */ + FieldVisitor visitField( + int access, + String name, + String desc, + String signature, + Object value); + + /** + * Visits a method of the class. This method <i>must</i> return a new + * {@link MethodVisitor} instance (or <tt>null</tt>) each time it is + * called, i.e., it should not return a previously returned visitor. + * + * @param access the method's access flags (see {@link Opcodes}). This + * parameter also indicates if the method is synthetic and/or + * deprecated. + * @param name the method's name. + * @param desc the method's descriptor (see {@link Type Type}). + * @param signature the method's signature. May be <tt>null</tt> if the + * method parameters, return type and exceptions do not use generic + * types. + * @param exceptions the internal names of the method's exception classes + * (see {@link Type#getInternalName() getInternalName}). May be + * <tt>null</tt>. + * @return an object to visit the byte code of the method, or <tt>null</tt> + * if this class visitor is not interested in visiting the code of + * this method. + */ + MethodVisitor visitMethod( + int access, + String name, + String desc, + String signature, + String[] exceptions); + + /** + * Visits the end of the class. This method, which is the last one to be + * called, is used to inform the visitor that all the fields and methods of + * the class have been visited. + */ + void visitEnd(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/ws/org/objectweb/asm/ClassWriter.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,1374 @@ +/* + * Copyright 2005-2009 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2007 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.sun.xml.internal.ws.org.objectweb.asm; + +/** + * A {@link ClassVisitor} that generates classes in bytecode form. More + * precisely this visitor generates a byte array conforming to the Java class + * file format. It can be used alone, to generate a Java class "from scratch", + * or with one or more {@link ClassReader ClassReader} and adapter class visitor + * to generate a modified class from one or more existing Java classes. + * + * @author Eric Bruneton + */ +public class ClassWriter implements ClassVisitor { + + /** + * Flag to automatically compute the maximum stack size and the maximum + * number of local variables of methods. If this flag is set, then the + * arguments of the {@link MethodVisitor#visitMaxs visitMaxs} method of the + * {@link MethodVisitor} returned by the {@link #visitMethod visitMethod} + * method will be ignored, and computed automatically from the signature and + * the bytecode of each method. + * + * @see #ClassWriter(int) + */ + public static final int COMPUTE_MAXS = 1; + + /** + * Flag to automatically compute the stack map frames of methods from + * scratch. If this flag is set, then the calls to the + * {@link MethodVisitor#visitFrame} method are ignored, and the stack map + * frames are recomputed from the methods bytecode. The arguments of the + * {@link MethodVisitor#visitMaxs visitMaxs} method are also ignored and + * recomputed from the bytecode. In other words, computeFrames implies + * computeMaxs. + * + * @see #ClassWriter(int) + */ + public static final int COMPUTE_FRAMES = 2; + + /** + * The type of instructions without any argument. + */ + static final int NOARG_INSN = 0; + + /** + * The type of instructions with an signed byte argument. + */ + static final int SBYTE_INSN = 1; + + /** + * The type of instructions with an signed short argument. + */ + static final int SHORT_INSN = 2; + + /** + * The type of instructions with a local variable index argument. + */ + static final int VAR_INSN = 3; + + /** + * The type of instructions with an implicit local variable index argument. + */ + static final int IMPLVAR_INSN = 4; + + /** + * The type of instructions with a type descriptor argument. + */ + static final int TYPE_INSN = 5; + + /** + * The type of field and method invocations instructions. + */ + static final int FIELDORMETH_INSN = 6; + + /** + * The type of the INVOKEINTERFACE instruction. + */ + static final int ITFMETH_INSN = 7; + + /** + * The type of instructions with a 2 bytes bytecode offset label. + */ + static final int LABEL_INSN = 8; + + /** + * The type of instructions with a 4 bytes bytecode offset label. + */ + static final int LABELW_INSN = 9; + + /** + * The type of the LDC instruction. + */ + static final int LDC_INSN = 10; + + /** + * The type of the LDC_W and LDC2_W instructions. + */ + static final int LDCW_INSN = 11; + + /** + * The type of the IINC instruction. + */ + static final int IINC_INSN = 12; + + /** + * The type of the TABLESWITCH instruction. + */ + static final int TABL_INSN = 13; + + /** + * The type of the LOOKUPSWITCH instruction. + */ + static final int LOOK_INSN = 14; + + /** + * The type of the MULTIANEWARRAY instruction. + */ + static final int MANA_INSN = 15; + + /** + * The type of the WIDE instruction. + */ + static final int WIDE_INSN = 16; + + /** + * The instruction types of all JVM opcodes. + */ + static final byte[] TYPE; + + /** + * The type of CONSTANT_Class constant pool items. + */ + static final int CLASS = 7; + + /** + * The type of CONSTANT_Fieldref constant pool items. + */ + static final int FIELD = 9; + + /** + * The type of CONSTANT_Methodref constant pool items. + */ + static final int METH = 10; + + /** + * The type of CONSTANT_InterfaceMethodref constant pool items. + */ + static final int IMETH = 11; + + /** + * The type of CONSTANT_String constant pool items. + */ + static final int STR = 8; + + /** + * The type of CONSTANT_Integer constant pool items. + */ + static final int INT = 3; + + /** + * The type of CONSTANT_Float constant pool items. + */ + static final int FLOAT = 4; + + /** + * The type of CONSTANT_Long constant pool items. + */ + static final int LONG = 5; + + /** + * The type of CONSTANT_Double constant pool items. + */ + static final int DOUBLE = 6; + + /** + * The type of CONSTANT_NameAndType constant pool items. + */ + static final int NAME_TYPE = 12; + + /** + * The type of CONSTANT_Utf8 constant pool items. + */ + static final int UTF8 = 1; + + /** + * Normal type Item stored in the ClassWriter {@link ClassWriter#typeTable}, + * instead of the constant pool, in order to avoid clashes with normal + * constant pool items in the ClassWriter constant pool's hash table. + */ + static final int TYPE_NORMAL = 13; + + /** + * Uninitialized type Item stored in the ClassWriter + * {@link ClassWriter#typeTable}, instead of the constant pool, in order to + * avoid clashes with normal constant pool items in the ClassWriter constant + * pool's hash table. + */ + static final int TYPE_UNINIT = 14; + + /** + * Merged type Item stored in the ClassWriter {@link ClassWriter#typeTable}, + * instead of the constant pool, in order to avoid clashes with normal + * constant pool items in the ClassWriter constant pool's hash table. + */ + static final int TYPE_MERGED = 15; + + /** + * The class reader from which this class writer was constructed, if any. + */ + ClassReader cr; + + /** + * Minor and major version numbers of the class to be generated. + */ + int version; + + /** + * Index of the next item to be added in the constant pool. + */ + int index; + + /** + * The constant pool of this class. + */ + final ByteVector pool; + + /** + * The constant pool's hash table data. + */ + Item[] items; + + /** + * The threshold of the constant pool's hash table. + */ + int threshold; + + /** + * A reusable key used to look for items in the {@link #items} hash table. + */ + final Item key; + + /** + * A reusable key used to look for items in the {@link #items} hash table. + */ + final Item key2; + + /** + * A reusable key used to look for items in the {@link #items} hash table. + */ + final Item key3; + + /** + * A type table used to temporarily store internal names that will not + * necessarily be stored in the constant pool. This type table is used by + * the control flow and data flow analysis algorithm used to compute stack + * map frames from scratch. This array associates to each index <tt>i</tt> + * the Item whose index is <tt>i</tt>. All Item objects stored in this + * array are also stored in the {@link #items} hash table. These two arrays + * allow to retrieve an Item from its index or, conversely, to get the index + * of an Item from its value. Each Item stores an internal name in its + * {@link Item#strVal1} field. + */ + Item[] typeTable; + + /** + * Number of elements in the {@link #typeTable} array. + */ + private short typeCount; + + /** + * The access flags of this class. + */ + private int access; + + /** + * The constant pool item that contains the internal name of this class. + */ + private int name; + + /** + * The internal name of this class. + */ + String thisName; + + /** + * The constant pool item that contains the signature of this class. + */ + private int signature; + + /** + * The constant pool item that contains the internal name of the super class + * of this class. + */ + private int superName; + + /** + * Number of interfaces implemented or extended by this class or interface. + */ + private int interfaceCount; + + /** + * The interfaces implemented or extended by this class or interface. More + * precisely, this array contains the indexes of the constant pool items + * that contain the internal names of these interfaces. + */ + private int[] interfaces; + + /** + * The index of the constant pool item that contains the name of the source + * file from which this class was compiled. + */ + private int sourceFile; + + /** + * The SourceDebug attribute of this class. + */ + private ByteVector sourceDebug; + + /** + * The constant pool item that contains the name of the enclosing class of + * this class. + */ + private int enclosingMethodOwner; + + /** + * The constant pool item that contains the name and descriptor of the + * enclosing method of this class. + */ + private int enclosingMethod; + + /** + * The runtime visible annotations of this class. + */ + private AnnotationWriter anns; + + /** + * The runtime invisible annotations of this class. + */ + private AnnotationWriter ianns; + + /** + * The non standard attributes of this class. + */ + private Attribute attrs; + + /** + * The number of entries in the InnerClasses attribute. + */ + private int innerClassesCount; + + /** + * The InnerClasses attribute. + */ + private ByteVector innerClasses; + + /** + * The fields of this class. These fields are stored in a linked list of + * {@link FieldWriter} objects, linked to each other by their + * {@link FieldWriter#next} field. This field stores the first element of + * this list. + */ + FieldWriter firstField; + + /** + * The fields of this class. These fields are stored in a linked list of + * {@link FieldWriter} objects, linked to each other by their + * {@link FieldWriter#next} field. This field stores the last element of + * this list. + */ + FieldWriter lastField; + + /** + * The methods of this class. These methods are stored in a linked list of + * {@link MethodWriter} objects, linked to each other by their + * {@link MethodWriter#next} field. This field stores the first element of + * this list. + */ + MethodWriter firstMethod; + + /** + * The methods of this class. These methods are stored in a linked list of + * {@link MethodWriter} objects, linked to each other by their + * {@link MethodWriter#next} field. This field stores the last element of + * this list. + */ + MethodWriter lastMethod; + + /** + * <tt>true</tt> if the maximum stack size and number of local variables + * must be automatically computed. + */ + private final boolean computeMaxs; + + /** + * <tt>true</tt> if the stack map frames must be recomputed from scratch. + */ + private final boolean computeFrames; + + /** + * <tt>true</tt> if the stack map tables of this class are invalid. The + * {@link MethodWriter#resizeInstructions} method cannot transform existing + * stack map tables, and so produces potentially invalid classes when it is + * executed. In this case the class is reread and rewritten with the + * {@link #COMPUTE_FRAMES} option (the resizeInstructions method can resize + * stack map tables when this option is used). + */ + boolean invalidFrames; + + // ------------------------------------------------------------------------ + // Static initializer + // ------------------------------------------------------------------------ + + /** + * Computes the instruction types of JVM opcodes. + */ + static { + int i; + byte[] b = new byte[220]; + String s = "AAAAAAAAAAAAAAAABCKLLDDDDDEEEEEEEEEEEEEEEEEEEEAAAAAAAADD" + + "DDDEEEEEEEEEEEEEEEEEEEEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + + "AAAAAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAIIIIIIIIIIIIIIIIDNOAA" + + "AAAAGGGGGGGHAFBFAAFFAAQPIIJJIIIIIIIIIIIIIIIIII"; + for (i = 0; i < b.length; ++i) { + b[i] = (byte) (s.charAt(i) - 'A'); + } + TYPE = b; + + // code to generate the above string + // + // // SBYTE_INSN instructions + // b[Constants.NEWARRAY] = SBYTE_INSN; + // b[Constants.BIPUSH] = SBYTE_INSN; + // + // // SHORT_INSN instructions + // b[Constants.SIPUSH] = SHORT_INSN; + // + // // (IMPL)VAR_INSN instructions + // b[Constants.RET] = VAR_INSN; + // for (i = Constants.ILOAD; i <= Constants.ALOAD; ++i) { + // b[i] = VAR_INSN; + // } + // for (i = Constants.ISTORE; i <= Constants.ASTORE; ++i) { + // b[i] = VAR_INSN; + // } + // for (i = 26; i <= 45; ++i) { // ILOAD_0 to ALOAD_3 + // b[i] = IMPLVAR_INSN; + // } + // for (i = 59; i <= 78; ++i) { // ISTORE_0 to ASTORE_3 + // b[i] = IMPLVAR_INSN; + // } + // + // // TYPE_INSN instructions + // b[Constants.NEW] = TYPE_INSN; + // b[Constants.ANEWARRAY] = TYPE_INSN; + // b[Constants.CHECKCAST] = TYPE_INSN; + // b[Constants.INSTANCEOF] = TYPE_INSN; + // + // // (Set)FIELDORMETH_INSN instructions + // for (i = Constants.GETSTATIC; i <= Constants.INVOKESTATIC; ++i) { + // b[i] = FIELDORMETH_INSN; + // } + // b[Constants.INVOKEINTERFACE] = ITFMETH_INSN; + // + // // LABEL(W)_INSN instructions + // for (i = Constants.IFEQ; i <= Constants.JSR; ++i) { + // b[i] = LABEL_INSN; + // } + // b[Constants.IFNULL] = LABEL_INSN; + // b[Constants.IFNONNULL] = LABEL_INSN; + // b[200] = LABELW_INSN; // GOTO_W + // b[201] = LABELW_INSN; // JSR_W + // // temporary opcodes used internally by ASM - see Label and + // MethodWriter + // for (i = 202; i < 220; ++i) { + // b[i] = LABEL_INSN; + // } + // + // // LDC(_W) instructions + // b[Constants.LDC] = LDC_INSN; + // b[19] = LDCW_INSN; // LDC_W + // b[20] = LDCW_INSN; // LDC2_W + // + // // special instructions + // b[Constants.IINC] = IINC_INSN; + // b[Constants.TABLESWITCH] = TABL_INSN; + // b[Constants.LOOKUPSWITCH] = LOOK_INSN; + // b[Constants.MULTIANEWARRAY] = MANA_INSN; + // b[196] = WIDE_INSN; // WIDE + // + // for (i = 0; i < b.length; ++i) { + // System.err.print((char)('A' + b[i])); + // } + // System.err.println(); + } + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + + /** + * Constructs a new {@link ClassWriter} object. + * + * @param flags option flags that can be used to modify the default behavior + * of this class. See {@link #COMPUTE_MAXS}, {@link #COMPUTE_FRAMES}. + */ + public ClassWriter(final int flags) { + index = 1; + pool = new ByteVector(); + items = new Item[256]; + threshold = (int) (0.75d * items.length); + key = new Item(); + key2 = new Item(); + key3 = new Item(); + this.computeMaxs = (flags & COMPUTE_MAXS) != 0; + this.computeFrames = (flags & COMPUTE_FRAMES) != 0; + } + + /** + * Constructs a new {@link ClassWriter} object and enables optimizations for + * "mostly add" bytecode transformations. These optimizations are the + * following: + * + * <ul> <li>The constant pool from the original class is copied as is in + * the new class, which saves time. New constant pool entries will be added + * at the end if necessary, but unused constant pool entries <i>won't be + * removed</i>.</li> <li>Methods that are not transformed are copied as + * is in the new class, directly from the original class bytecode (i.e. + * without emitting visit events for all the method instructions), which + * saves a <i>lot</i> of time. Untransformed methods are detected by the + * fact that the {@link ClassReader} receives {@link MethodVisitor} objects + * that come from a {@link ClassWriter} (and not from a custom + * {@link ClassAdapter} or any other {@link ClassVisitor} instance).</li> + * </ul> + * + * @param classReader the {@link ClassReader} used to read the original + * class. It will be used to copy the entire constant pool from the + * original class and also to copy other fragments of original + * bytecode where applicable. + * @param flags option flags that can be used to modify the default behavior + * of this class. See {@link #COMPUTE_MAXS}, {@link #COMPUTE_FRAMES}. + */ + public ClassWriter(final ClassReader classReader, final int flags) { + this(flags); + classReader.copyPool(this); + this.cr = classReader; + } + + // ------------------------------------------------------------------------ + // Implementation of the ClassVisitor interface + // ------------------------------------------------------------------------ + + public void visit( + final int version, + final int access, + final String name, + final String signature, + final String superName, + final String[] interfaces) + { + this.version = version; + this.access = access; + this.name = newClass(name); + thisName = name; + if (ClassReader.SIGNATURES && signature != null) { + this.signature = newUTF8(signature); + } + this.superName = superName == null ? 0 : newClass(superName); + if (interfaces != null && interfaces.length > 0) { + interfaceCount = interfaces.length; + this.interfaces = new int[interfaceCount]; + for (int i = 0; i < interfaceCount; ++i) { + this.interfaces[i] = newClass(interfaces[i]); + } + } + } + + public void visitSource(final String file, final String debug) { + if (file != null) { + sourceFile = newUTF8(file); + } + if (debug != null) { + sourceDebug = new ByteVector().putUTF8(debug); + } + } + + public void visitOuterClass( + final String owner, + final String name, + final String desc) + { + enclosingMethodOwner = newClass(owner); + if (name != null && desc != null) { + enclosingMethod = newNameType(name, desc); + } + } + + public AnnotationVisitor visitAnnotation( + final String desc, + final boolean visible) + { + if (!ClassReader.ANNOTATIONS) { + return null; + } + ByteVector bv = new ByteVector(); + // write type, and reserve space for values count + bv.putShort(newUTF8(desc)).putShort(0); + AnnotationWriter aw = new AnnotationWriter(this, true, bv, bv, 2); + if (visible) { + aw.next = anns; + anns = aw; + } else { + aw.next = ianns; + ianns = aw; + } + return aw; + } + + public void visitAttribute(final Attribute attr) { + attr.next = attrs; + attrs = attr; + } + + public void visitInnerClass( + final String name, + final String outerName, + final String innerName, + final int access) + { + if (innerClasses == null) { + innerClasses = new ByteVector(); + } + ++innerClassesCount; + innerClasses.putShort(name == null ? 0 : newClass(name)); + innerClasses.putShort(outerName == null ? 0 : newClass(outerName)); + innerClasses.putShort(innerName == null ? 0 : newUTF8(innerName)); + innerClasses.putShort(access); + } + + public FieldVisitor visitField( + final int access, + final String name, + final String desc, + final String signature, + final Object value) + { + return new FieldWriter(this, access, name, desc, signature, value); + } + + public MethodVisitor visitMethod( + final int access, + final String name, + final String desc, + final String signature, + final String[] exceptions) + { + return new MethodWriter(this, + access, + name, + desc, + signature, + exceptions, + computeMaxs, + computeFrames); + } + + public void visitEnd() { + } + + // ------------------------------------------------------------------------ + // Other public methods + // ------------------------------------------------------------------------ + + /** + * Returns the bytecode of the class that was build with this class writer. + * + * @return the bytecode of the class that was build with this class writer. + */ + public byte[] toByteArray() { + // computes the real size of the bytecode of this class + int size = 24 + 2 * interfaceCount; + int nbFields = 0; + FieldWriter fb = firstField; + while (fb != null) { + ++nbFields; + size += fb.getSize(); + fb = fb.next; + } + int nbMethods = 0; + MethodWriter mb = firstMethod; + while (mb != null) { + ++nbMethods; + size += mb.getSize(); + mb = mb.next; + } + int attributeCount = 0; + if (ClassReader.SIGNATURES && signature != 0) { + ++attributeCount; + size += 8; + newUTF8("Signature"); + } + if (sourceFile != 0) { + ++attributeCount; + size += 8; + newUTF8("SourceFile"); + } + if (sourceDebug != null) { + ++attributeCount; + size += sourceDebug.length + 4; + newUTF8("SourceDebugExtension"); + } + if (enclosingMethodOwner != 0) { + ++attributeCount; + size += 10; + newUTF8("EnclosingMethod"); + } + if ((access & Opcodes.ACC_DEPRECATED) != 0) { + ++attributeCount; + size += 6; + newUTF8("Deprecated"); + } + if ((access & Opcodes.ACC_SYNTHETIC) != 0 + && (version & 0xffff) < Opcodes.V1_5) + { + ++attributeCount; + size += 6; + newUTF8("Synthetic"); + } + if (innerClasses != null) { + ++attributeCount; + size += 8 + innerClasses.length; + newUTF8("InnerClasses"); + } + if (ClassReader.ANNOTATIONS && anns != null) { + ++attributeCount; + size += 8 + anns.getSize(); + newUTF8("RuntimeVisibleAnnotations"); + } + if (ClassReader.ANNOTATIONS && ianns != null) { + ++attributeCount; + size += 8 + ianns.getSize(); + newUTF8("RuntimeInvisibleAnnotations"); + } + if (attrs != null) { + attributeCount += attrs.getCount(); + size += attrs.getSize(this, null, 0, -1, -1); + } + size += pool.length; + // allocates a byte vector of this size, in order to avoid unnecessary + // arraycopy operations in the ByteVector.enlarge() method + ByteVector out = new ByteVector(size); + out.putInt(0xCAFEBABE).putInt(version); + out.putShort(index).putByteArray(pool.data, 0, pool.length); + out.putShort(access).putShort(name).putShort(superName); + out.putShort(interfaceCount); + for (int i = 0; i < interfaceCount; ++i) { + out.putShort(interfaces[i]); + } + out.putShort(nbFields); + fb = firstField; + while (fb != null) { + fb.put(out); + fb = fb.next; + } + out.putShort(nbMethods); + mb = firstMethod; + while (mb != null) { + mb.put(out); + mb = mb.next; + } + out.putShort(attributeCount); + if (ClassReader.SIGNATURES && signature != 0) { + out.putShort(newUTF8("Signature")).putInt(2).putShort(signature); + } + if (sourceFile != 0) { + out.putShort(newUTF8("SourceFile")).putInt(2).putShort(sourceFile); + } + if (sourceDebug != null) { + int len = sourceDebug.length - 2; + out.putShort(newUTF8("SourceDebugExtension")).putInt(len); + out.putByteArray(sourceDebug.data, 2, len); + } + if (enclosingMethodOwner != 0) { + out.putShort(newUTF8("EnclosingMethod")).putInt(4); + out.putShort(enclosingMethodOwner).putShort(enclosingMethod); + } + if ((access & Opcodes.ACC_DEPRECATED) != 0) { + out.putShort(newUTF8("Deprecated")).putInt(0); + } + if ((access & Opcodes.ACC_SYNTHETIC) != 0 + && (version & 0xffff) < Opcodes.V1_5) + { + out.putShort(newUTF8("Synthetic")).putInt(0); + } + if (innerClasses != null) { + out.putShort(newUTF8("InnerClasses")); + out.putInt(innerClasses.length + 2).putShort(innerClassesCount); + out.putByteArray(innerClasses.data, 0, innerClasses.length); + } + if (ClassReader.ANNOTATIONS && anns != null) { + out.putShort(newUTF8("RuntimeVisibleAnnotations")); + anns.put(out); + } + if (ClassReader.ANNOTATIONS && ianns != null) { + out.putShort(newUTF8("RuntimeInvisibleAnnotations")); + ianns.put(out); + } + if (attrs != null) { + attrs.put(this, null, 0, -1, -1, out); + } + if (invalidFrames) { + ClassWriter cw = new ClassWriter(COMPUTE_FRAMES); + new ClassReader(out.data).accept(cw, ClassReader.SKIP_FRAMES); + return cw.toByteArray(); + } + return out.data; + } + + // ------------------------------------------------------------------------ + // Utility methods: constant pool management + // ------------------------------------------------------------------------ + + /** + * Adds a number or string constant to the constant pool of the class being + * build. Does nothing if the constant pool already contains a similar item. + * + * @param cst the value of the constant to be added to the constant pool. + * This parameter must be an {@link Integer}, a {@link Float}, a + * {@link Long}, a {@link Double}, a {@link String} or a + * {@link Type}. + * @return a new or already existing constant item with the given value. + */ + Item newConstItem(final Object cst) { + if (cst instanceof Integer) { + int val = ((Integer) cst).intValue(); + return newInteger(val); + } else if (cst instanceof Byte) { + int val = ((Byte) cst).intValue(); + return newInteger(val); + } else if (cst instanceof Character) { + int val = ((Character) cst).charValue(); + return newInteger(val); + } else if (cst instanceof Short) { + int val = ((Short) cst).intValue(); + return newInteger(val); + } else if (cst instanceof Boolean) { + int val = ((Boolean) cst).booleanValue() ? 1 : 0; + return newInteger(val); + } else if (cst instanceof Float) { + float val = ((Float) cst).floatValue(); + return newFloat(val); + } else if (cst instanceof Long) { + long val = ((Long) cst).longValue(); + return newLong(val); + } else if (cst instanceof Double) { + double val = ((Double) cst).doubleValue(); + return newDouble(val); + } else if (cst instanceof String) { + return newString((String) cst); + } else if (cst instanceof Type) { + Type t = (Type) cst; + return newClassItem(t.getSort() == Type.OBJECT + ? t.getInternalName() + : t.getDescriptor()); + } else { + throw new IllegalArgumentException("value " + cst); + } + } + + /** + * Adds a number or string constant to the constant pool of the class being + * build. Does nothing if the constant pool already contains a similar item. + * <i>This method is intended for {@link Attribute} sub classes, and is + * normally not needed by class generators or adapters.</i> + * + * @param cst the value of the constant to be added to the constant pool. + * This parameter must be an {@link Integer}, a {@link Float}, a + * {@link Long}, a {@link Double} or a {@link String}. + * @return the index of a new or already existing constant item with the + * given value. + */ + public int newConst(final Object cst) { + return newConstItem(cst).index; + } + + /** + * Adds an UTF8 string to the constant pool of the class being build. Does + * nothing if the constant pool already contains a similar item. <i>This + * method is intended for {@link Attribute} sub classes, and is normally not + * needed by class generators or adapters.</i> + * + * @param value the String value. + * @return the index of a new or already existing UTF8 item. + */ + public int newUTF8(final String value) { + key.set(UTF8, value, null, null); + Item result = get(key); + if (result == null) { + pool.putByte(UTF8).putUTF8(value); + result = new Item(index++, key); + put(result); + } + return result.index; + } + + /** + * Adds a class reference to the constant pool of the class being build. + * Does nothing if the constant pool already contains a similar item. + * <i>This method is intended for {@link Attribute} sub classes, and is + * normally not needed by class generators or adapters.</i> + * + * @param value the internal name of the class. + * @return a new or already existing class reference item. + */ + Item newClassItem(final String value) { + key2.set(CLASS, value, null, null); + Item result = get(key2); + if (result == null) { + pool.put12(CLASS, newUTF8(value)); + result = new Item(index++, key2); + put(result); + } + return result; + } + + /** + * Adds a class reference to the constant pool of the class being build. + * Does nothing if the constant pool already contains a similar item. + * <i>This method is intended for {@link Attribute} sub classes, and is + * normally not needed by class generators or adapters.</i> + * + * @param value the internal name of the class. + * @return the index of a new or already existing class reference item. + */ + public int newClass(final String value) { + return newClassItem(value).index; + } + + /** + * Adds a field reference to the constant pool of the class being build. + * Does nothing if the constant pool already contains a similar item. + * + * @param owner the internal name of the field's owner class. + * @param name the field's name. + * @param desc the field's descriptor. + * @return a new or already existing field reference item. + */ + Item newFieldItem(final String owner, final String name, final String desc) + { + key3.set(FIELD, owner, name, desc); + Item result = get(key3); + if (result == null) { + put122(FIELD, newClass(owner), newNameType(name, desc)); + result = new Item(index++, key3); + put(result); + } + return result; + } + + /** + * Adds a field reference to the constant pool of the class being build. + * Does nothing if the constant pool already contains a similar item. + * <i>This method is intended for {@link Attribute} sub classes, and is + * normally not needed by class generators or adapters.</i> + * + * @param owner the internal name of the field's owner class. + * @param name the field's name. + * @param desc the field's descriptor. + * @return the index of a new or already existing field reference item. + */ + public int newField(final String owner, final String name, final String desc) + { + return newFieldItem(owner, name, desc).index; + } + + /** + * Adds a method reference to the constant pool of the class being build. + * Does nothing if the constant pool already contains a similar item. + * + * @param owner the internal name of the method's owner class. + * @param name the method's name. + * @param desc the method's descriptor. + * @param itf <tt>true</tt> if <tt>owner</tt> is an interface. + * @return a new or already existing method reference item. + */ + Item newMethodItem( + final String owner, + final String name, + final String desc, + final boolean itf) + { + int type = itf ? IMETH : METH; + key3.set(type, owner, name, desc); + Item result = get(key3); + if (result == null) { + put122(type, newClass(owner), newNameType(name, desc)); + result = new Item(index++, key3); + put(result); + } + return result; + } + + /** + * Adds a method reference to the constant pool of the class being build. + * Does nothing if the constant pool already contains a similar item. + * <i>This method is intended for {@link Attribute} sub classes, and is + * normally not needed by class generators or adapters.</i> + * + * @param owner the internal name of the method's owner class. + * @param name the method's name. + * @param desc the method's descriptor. + * @param itf <tt>true</tt> if <tt>owner</tt> is an interface. + * @return the index of a new or already existing method reference item. + */ + public int newMethod( + final String owner, + final String name, + final String desc, + final boolean itf) + { + return newMethodItem(owner, name, desc, itf).index; + } + + /** + * Adds an integer to the constant pool of the class being build. Does + * nothing if the constant pool already contains a similar item. + * + * @param value the int value. + * @return a new or already existing int item. + */ + Item newInteger(final int value) { + key.set(value); + Item result = get(key); + if (result == null) { + pool.putByte(INT).putInt(value); + result = new Item(index++, key); + put(result); + } + return result; + } + + /** + * Adds a float to the constant pool of the class being build. Does nothing + * if the constant pool already contains a similar item. + * + * @param value the float value. + * @return a new or already existing float item. + */ + Item newFloat(final float value) { + key.set(value); + Item result = get(key); + if (result == null) { + pool.putByte(FLOAT).putInt(key.intVal); + result = new Item(index++, key); + put(result); + } + return result; + } + + /** + * Adds a long to the constant pool of the class being build. Does nothing + * if the constant pool already contains a similar item. + * + * @param value the long value. + * @return a new or already existing long item. + */ + Item newLong(final long value) { + key.set(value); + Item result = get(key); + if (result == null) { + pool.putByte(LONG).putLong(value); + result = new Item(index, key); + put(result); + index += 2; + } + return result; + } + + /** + * Adds a double to the constant pool of the class being build. Does nothing + * if the constant pool already contains a similar item. + * + * @param value the double value. + * @return a new or already existing double item. + */ + Item newDouble(final double value) { + key.set(value); + Item result = get(key); + if (result == null) { + pool.putByte(DOUBLE).putLong(key.longVal); + result = new Item(index, key); + put(result); + index += 2; + } + return result; + } + + /** + * Adds a string to the constant pool of the class being build. Does nothing + * if the constant pool already contains a similar item. + * + * @param value the String value. + * @return a new or already existing string item. + */ + private Item newString(final String value) { + key2.set(STR, value, null, null); + Item result = get(key2); + if (result == null) { + pool.put12(STR, newUTF8(value)); + result = new Item(index++, key2); + put(result); + } + return result; + } + + /** + * Adds a name and type to the constant pool of the class being build. Does + * nothing if the constant pool already contains a similar item. <i>This + * method is intended for {@link Attribute} sub classes, and is normally not + * needed by class generators or adapters.</i> + * + * @param name a name. + * @param desc a type descriptor. + * @return the index of a new or already existing name and type item. + */ + public int newNameType(final String name, final String desc) { + key2.set(NAME_TYPE, name, desc, null); + Item result = get(key2); + if (result == null) { + put122(NAME_TYPE, newUTF8(name), newUTF8(desc)); + result = new Item(index++, key2); + put(result); + } + return result.index; + } + + /** + * Adds the given internal name to {@link #typeTable} and returns its index. + * Does nothing if the type table already contains this internal name. + * + * @param type the internal name to be added to the type table. + * @return the index of this internal name in the type table. + */ + int addType(final String type) { + key.set(TYPE_NORMAL, type, null, null); + Item result = get(key); + if (result == null) { + result = addType(key); + } + return result.index; + } + + /** + * Adds the given "uninitialized" type to {@link #typeTable} and returns its + * index. This method is used for UNINITIALIZED types, made of an internal + * name and a bytecode offset. + * + * @param type the internal name to be added to the type table. + * @param offset the bytecode offset of the NEW instruction that created + * this UNINITIALIZED type value. + * @return the index of this internal name in the type table. + */ + int addUninitializedType(final String type, final int offset) { + key.type = TYPE_UNINIT; + key.intVal = offset; + key.strVal1 = type; + key.hashCode = 0x7FFFFFFF & (TYPE_UNINIT + type.hashCode() + offset); + Item result = get(key); + if (result == null) { + result = addType(key); + } + return result.index; + } + + /** + * Adds the given Item to {@link #typeTable}. + * + * @param item the value to be added to the type table. + * @return the added Item, which a new Item instance with the same value as + * the given Item. + */ + private Item addType(final Item item) { + ++typeCount; + Item result = new Item(typeCount, key); + put(result); + if (typeTable == null) { + typeTable = new Item[16]; + } + if (typeCount == typeTable.length) { + Item[] newTable = new Item[2 * typeTable.length]; + System.arraycopy(typeTable, 0, newTable, 0, typeTable.length); + typeTable = newTable; + } + typeTable[typeCount] = result; + return result; + } + + /** + * Returns the index of the common super type of the two given types. This + * method calls {@link #getCommonSuperClass} and caches the result in the + * {@link #items} hash table to speedup future calls with the same + * parameters. + * + * @param type1 index of an internal name in {@link #typeTable}. + * @param type2 index of an internal name in {@link #typeTable}. + * @return the index of the common super type of the two given types. + */ + int getMergedType(final int type1, final int type2) { + key2.type = TYPE_MERGED; + key2.longVal = type1 | (((long) type2) << 32); + key2.hashCode = 0x7FFFFFFF & (TYPE_MERGED + type1 + type2); + Item result = get(key2); + if (result == null) { + String t = typeTable[type1].strVal1; + String u = typeTable[type2].strVal1; + key2.intVal = addType(getCommonSuperClass(t, u)); + result = new Item((short) 0, key2); + put(result); + } + return result.intVal; + } + + /** + * Returns the common super type of the two given types. The default + * implementation of this method <i>loads<i> the two given classes and uses + * the java.lang.Class methods to find the common super class. It can be + * overridden to compute this common super type in other ways, in particular + * without actually loading any class, or to take into account the class + * that is currently being generated by this ClassWriter, which can of + * course not be loaded since it is under construction. + * + * @param type1 the internal name of a class. + * @param type2 the internal name of another class. + * @return the internal name of the common super class of the two given + * classes. + */ + protected String getCommonSuperClass(final String type1, final String type2) + { + Class c, d; + try { + c = Class.forName(type1.replace('/', '.')); + d = Class.forName(type2.replace('/', '.')); + } catch (Exception e) { + throw new RuntimeException(e.toString()); + } + if (c.isAssignableFrom(d)) { + return type1; + } + if (d.isAssignableFrom(c)) { + return type2; + } + if (c.isInterface() || d.isInterface()) { + return "java/lang/Object"; + } else { + do { + c = c.getSuperclass(); + } while (!c.isAssignableFrom(d)); + return c.getName().replace('.', '/'); + } + } + + /** + * Returns the constant pool's hash table item which is equal to the given + * item. + * + * @param key a constant pool item. + * @return the constant pool's hash table item which is equal to the given + * item, or <tt>null</tt> if there is no such item. + */ + private Item get(final Item key) { + Item i = items[key.hashCode % items.length]; + while (i != null && !key.isEqualTo(i)) { + i = i.next; + } + return i; + } + + /** + * Puts the given item in the constant pool's hash table. The hash table + * <i>must</i> not already contains this item. + * + * @param i the item to be added to the constant pool's hash table. + */ + private void put(final Item i) { + if (index > threshold) { + int ll = items.length; + int nl = ll * 2 + 1; + Item[] newItems = new Item[nl]; + for (int l = ll - 1; l >= 0; --l) { + Item j = items[l]; + while (j != null) { + int index = j.hashCode % newItems.length; + Item k = j.next; + j.next = newItems[index]; + newItems[index] = j; + j = k; + } + } + items = newItems; + threshold = (int) (nl * 0.75); + } + int index = i.hashCode % items.length; + i.next = items[index]; + items[index] = i; + } + + /** + * Puts one byte and two shorts into the constant pool. + * + * @param b a byte. + * @param s1 a short. + * @param s2 another short. + */ + private void put122(final int b, final int s1, final int s2) { + pool.put12(b, s1).putShort(s2); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/ws/org/objectweb/asm/Edge.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,105 @@ +/* + * Copyright 2005-2009 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2007 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.sun.xml.internal.ws.org.objectweb.asm; + +/** + * An edge in the control flow graph of a method body. See {@link Label Label}. + * + * @author Eric Bruneton + */ +class Edge { + + /** + * Denotes a normal control flow graph edge. + */ + static final int NORMAL = 0; + + /** + * Denotes a control flow graph edge corresponding to an exception handler. + * More precisely any {@link Edge} whose {@link #info} is strictly positive + * corresponds to an exception handler. The actual value of {@link #info} is + * the index, in the {@link ClassWriter} type table, of the exception that + * is catched. + */ + static final int EXCEPTION = 0x7FFFFFFF; + + /** + * Information about this control flow graph edge. If + * {@link ClassWriter#COMPUTE_MAXS} is used this field is the (relative) + * stack size in the basic block from which this edge originates. This size + * is equal to the stack size at the "jump" instruction to which this edge + * corresponds, relatively to the stack size at the beginning of the + * originating basic block. If {@link ClassWriter#COMPUTE_FRAMES} is used, + * this field is the kind of this control flow graph edge (i.e. NORMAL or + * EXCEPTION). + */ + int info; + + /** + * The successor block of the basic block from which this edge originates. + */ + Label successor; + + /** + * The next edge in the list of successors of the originating basic block. + * See {@link Label#successors successors}. + */ + Edge next; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/ws/org/objectweb/asm/FieldVisitor.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,94 @@ +/* + * Copyright 2005-2009 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2007 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.sun.xml.internal.ws.org.objectweb.asm; + +/** + * A visitor to visit a Java field. The methods of this interface must be called + * in the following order: ( <tt>visitAnnotation</tt> | + * <tt>visitAttribute</tt> )* <tt>visitEnd</tt>. + * + * @author Eric Bruneton + */ +public interface FieldVisitor { + + /** + * Visits an annotation of the field. + * + * @param desc the class descriptor of the annotation class. + * @param visible <tt>true</tt> if the annotation is visible at runtime. + * @return a visitor to visit the annotation values, or <tt>null</tt> if + * this visitor is not interested in visiting this annotation. + */ + AnnotationVisitor visitAnnotation(String desc, boolean visible); + + /** + * Visits a non standard attribute of the field. + * + * @param attr an attribute. + */ + void visitAttribute(Attribute attr); + + /** + * Visits the end of the field. This method, which is the last one to be + * called, is used to inform the visitor that all the annotations and + * attributes of the field have been visited. + */ + void visitEnd(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/ws/org/objectweb/asm/FieldWriter.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,299 @@ +/* + * Copyright 2005-2009 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2007 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.sun.xml.internal.ws.org.objectweb.asm; + +/** + * An {@link FieldVisitor} that generates Java fields in bytecode form. + * + * @author Eric Bruneton + */ +final class FieldWriter implements FieldVisitor { + + /** + * Next field writer (see {@link ClassWriter#firstField firstField}). + */ + FieldWriter next; + + /** + * The class writer to which this field must be added. + */ + private final ClassWriter cw; + + /** + * Access flags of this field. + */ + private final int access; + + /** + * The index of the constant pool item that contains the name of this + * method. + */ + private final int name; + + /** + * The index of the constant pool item that contains the descriptor of this + * field. + */ + private final int desc; + + /** + * The index of the constant pool item that contains the signature of this + * field. + */ + private int signature; + + /** + * The index of the constant pool item that contains the constant value of + * this field. + */ + private int value; + + /** + * The runtime visible annotations of this field. May be <tt>null</tt>. + */ + private AnnotationWriter anns; + + /** + * The runtime invisible annotations of this field. May be <tt>null</tt>. + */ + private AnnotationWriter ianns; + + /** + * The non standard attributes of this field. May be <tt>null</tt>. + */ + private Attribute attrs; + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + + /** + * Constructs a new {@link FieldWriter}. + * + * @param cw the class writer to which this field must be added. + * @param access the field's access flags (see {@link Opcodes}). + * @param name the field's name. + * @param desc the field's descriptor (see {@link Type}). + * @param signature the field's signature. May be <tt>null</tt>. + * @param value the field's constant value. May be <tt>null</tt>. + */ + FieldWriter( + final ClassWriter cw, + final int access, + final String name, + final String desc, + final String signature, + final Object value) + { + if (cw.firstField == null) { + cw.firstField = this; + } else { + cw.lastField.next = this; + } + cw.lastField = this; + this.cw = cw; + this.access = access; + this.name = cw.newUTF8(name); + this.desc = cw.newUTF8(desc); + if (ClassReader.SIGNATURES && signature != null) { + this.signature = cw.newUTF8(signature); + } + if (value != null) { + this.value = cw.newConstItem(value).index; + } + } + + // ------------------------------------------------------------------------ + // Implementation of the FieldVisitor interface + // ------------------------------------------------------------------------ + + public AnnotationVisitor visitAnnotation( + final String desc, + final boolean visible) + { + if (!ClassReader.ANNOTATIONS) { + return null; + } + ByteVector bv = new ByteVector(); + // write type, and reserve space for values count + bv.putShort(cw.newUTF8(desc)).putShort(0); + AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv, 2); + if (visible) { + aw.next = anns; + anns = aw; + } else { + aw.next = ianns; + ianns = aw; + } + return aw; + } + + public void visitAttribute(final Attribute attr) { + attr.next = attrs; + attrs = attr; + } + + public void visitEnd() { + } + + // ------------------------------------------------------------------------ + // Utility methods + // ------------------------------------------------------------------------ + + /** + * Returns the size of this field. + * + * @return the size of this field. + */ + int getSize() { + int size = 8; + if (value != 0) { + cw.newUTF8("ConstantValue"); + size += 8; + } + if ((access & Opcodes.ACC_SYNTHETIC) != 0 + && (cw.version & 0xffff) < Opcodes.V1_5) + { + cw.newUTF8("Synthetic"); + size += 6; + } + if ((access & Opcodes.ACC_DEPRECATED) != 0) { + cw.newUTF8("Deprecated"); + size += 6; + } + if (ClassReader.SIGNATURES && signature != 0) { + cw.newUTF8("Signature"); + size += 8; + } + if (ClassReader.ANNOTATIONS && anns != null) { + cw.newUTF8("RuntimeVisibleAnnotations"); + size += 8 + anns.getSize(); + } + if (ClassReader.ANNOTATIONS && ianns != null) { + cw.newUTF8("RuntimeInvisibleAnnotations"); + size += 8 + ianns.getSize(); + } + if (attrs != null) { + size += attrs.getSize(cw, null, 0, -1, -1); + } + return size; + } + + /** + * Puts the content of this field into the given byte vector. + * + * @param out where the content of this field must be put. + */ + void put(final ByteVector out) { + out.putShort(access).putShort(name).putShort(desc); + int attributeCount = 0; + if (value != 0) { + ++attributeCount; + } + if ((access & Opcodes.ACC_SYNTHETIC) != 0 + && (cw.version & 0xffff) < Opcodes.V1_5) + { + ++attributeCount; + } + if ((access & Opcodes.ACC_DEPRECATED) != 0) { + ++attributeCount; + } + if (ClassReader.SIGNATURES && signature != 0) { + ++attributeCount; + } + if (ClassReader.ANNOTATIONS && anns != null) { + ++attributeCount; + } + if (ClassReader.ANNOTATIONS && ianns != null) { + ++attributeCount; + } + if (attrs != null) { + attributeCount += attrs.getCount(); + } + out.putShort(attributeCount); + if (value != 0) { + out.putShort(cw.newUTF8("ConstantValue")); + out.putInt(2).putShort(value); + } + if ((access & Opcodes.ACC_SYNTHETIC) != 0 + && (cw.version & 0xffff) < Opcodes.V1_5) + { + out.putShort(cw.newUTF8("Synthetic")).putInt(0); + } + if ((access & Opcodes.ACC_DEPRECATED) != 0) { + out.putShort(cw.newUTF8("Deprecated")).putInt(0); + } + if (ClassReader.SIGNATURES && signature != 0) { + out.putShort(cw.newUTF8("Signature")); + out.putInt(2).putShort(signature); + } + if (ClassReader.ANNOTATIONS && anns != null) { + out.putShort(cw.newUTF8("RuntimeVisibleAnnotations")); + anns.put(out); + } + if (ClassReader.ANNOTATIONS && ianns != null) { + out.putShort(cw.newUTF8("RuntimeInvisibleAnnotations")); + ianns.put(out); + } + if (attrs != null) { + attrs.put(cw, null, 0, -1, -1, out); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/ws/org/objectweb/asm/Frame.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,1432 @@ +/* + * Copyright 2005-2009 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2007 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.sun.xml.internal.ws.org.objectweb.asm; + +/** + * Information about the input and output stack map frames of a basic block. + * + * @author Eric Bruneton + */ +final class Frame { + + /* + * Frames are computed in a two steps process: during the visit of each + * instruction, the state of the frame at the end of current basic block is + * updated by simulating the action of the instruction on the previous state + * of this so called "output frame". In visitMaxs, a fix point algorithm is + * used to compute the "input frame" of each basic block, i.e. the stack map + * frame at the begining of the basic block, starting from the input frame + * of the first basic block (which is computed from the method descriptor), + * and by using the previously computed output frames to compute the input + * state of the other blocks. + * + * All output and input frames are stored as arrays of integers. Reference + * and array types are represented by an index into a type table (which is + * not the same as the constant pool of the class, in order to avoid adding + * unnecessary constants in the pool - not all computed frames will end up + * being stored in the stack map table). This allows very fast type + * comparisons. + * + * Output stack map frames are computed relatively to the input frame of the + * basic block, which is not yet known when output frames are computed. It + * is therefore necessary to be able to represent abstract types such as + * "the type at position x in the input frame locals" or "the type at + * position x from the top of the input frame stack" or even "the type at + * position x in the input frame, with y more (or less) array dimensions". + * This explains the rather complicated type format used in output frames. + * + * This format is the following: DIM KIND VALUE (4, 4 and 24 bits). DIM is a + * signed number of array dimensions (from -8 to 7). KIND is either BASE, + * LOCAL or STACK. BASE is used for types that are not relative to the input + * frame. LOCAL is used for types that are relative to the input local + * variable types. STACK is used for types that are relative to the input + * stack types. VALUE depends on KIND. For LOCAL types, it is an index in + * the input local variable types. For STACK types, it is a position + * relatively to the top of input frame stack. For BASE types, it is either + * one of the constants defined in FrameVisitor, or for OBJECT and + * UNINITIALIZED types, a tag and an index in the type table. + * + * Output frames can contain types of any kind and with a positive or + * negative dimension (and even unassigned types, represented by 0 - which + * does not correspond to any valid type value). Input frames can only + * contain BASE types of positive or null dimension. In all cases the type + * table contains only internal type names (array type descriptors are + * forbidden - dimensions must be represented through the DIM field). + * + * The LONG and DOUBLE types are always represented by using two slots (LONG + + * TOP or DOUBLE + TOP), for local variable types as well as in the operand + * stack. This is necessary to be able to simulate DUPx_y instructions, + * whose effect would be dependent on the actual type values if types were + * always represented by a single slot in the stack (and this is not + * possible, since actual type values are not always known - cf LOCAL and + * STACK type kinds). + */ + + /** + * Mask to get the dimension of a frame type. This dimension is a signed + * integer between -8 and 7. + */ + static final int DIM = 0xF0000000; + + /** + * Constant to be added to a type to get a type with one more dimension. + */ + static final int ARRAY_OF = 0x10000000; + + /** + * Constant to be added to a type to get a type with one less dimension. + */ + static final int ELEMENT_OF = 0xF0000000; + + /** + * Mask to get the kind of a frame type. + * + * @see #BASE + * @see #LOCAL + * @see #STACK + */ + static final int KIND = 0xF000000; + + /** + * Mask to get the value of a frame type. + */ + static final int VALUE = 0xFFFFFF; + + /** + * Mask to get the kind of base types. + */ + static final int BASE_KIND = 0xFF00000; + + /** + * Mask to get the value of base types. + */ + static final int BASE_VALUE = 0xFFFFF; + + /** + * Kind of the types that are not relative to an input stack map frame. + */ + static final int BASE = 0x1000000; + + /** + * Base kind of the base reference types. The BASE_VALUE of such types is an + * index into the type table. + */ + static final int OBJECT = BASE | 0x700000; + + /** + * Base kind of the uninitialized base types. The BASE_VALUE of such types + * in an index into the type table (the Item at that index contains both an + * instruction offset and an internal class name). + */ + static final int UNINITIALIZED = BASE | 0x800000; + + /** + * Kind of the types that are relative to the local variable types of an + * input stack map frame. The value of such types is a local variable index. + */ + private static final int LOCAL = 0x2000000; + + /** + * Kind of the the types that are relative to the stack of an input stack + * map frame. The value of such types is a position relatively to the top of + * this stack. + */ + private static final int STACK = 0x3000000; + + /** + * The TOP type. This is a BASE type. + */ + static final int TOP = BASE | 0; + + /** + * The BOOLEAN type. This is a BASE type mainly used for array types. + */ + static final int BOOLEAN = BASE | 9; + + /** + * The BYTE type. This is a BASE type mainly used for array types. + */ + static final int BYTE = BASE | 10; + + /** + * The CHAR type. This is a BASE type mainly used for array types. + */ + static final int CHAR = BASE | 11; + + /** + * The SHORT type. This is a BASE type mainly used for array types. + */ + static final int SHORT = BASE | 12; + + /** + * The INTEGER type. This is a BASE type. + */ + static final int INTEGER = BASE | 1; + + /** + * The FLOAT type. This is a BASE type. + */ + static final int FLOAT = BASE | 2; + + /** + * The DOUBLE type. This is a BASE type. + */ + static final int DOUBLE = BASE | 3; + + /** + * The LONG type. This is a BASE type. + */ + static final int LONG = BASE | 4; + + /** + * The NULL type. This is a BASE type. + */ + static final int NULL = BASE | 5; + + /** + * The UNINITIALIZED_THIS type. This is a BASE type. + */ + static final int UNINITIALIZED_THIS = BASE | 6; + + /** + * The stack size variation corresponding to each JVM instruction. This + * stack variation is equal to the size of the values produced by an + * instruction, minus the size of the values consumed by this instruction. + */ + static final int[] SIZE; + + /** + * Computes the stack size variation corresponding to each JVM instruction. + */ + static { + int i; + int[] b = new int[202]; + String s = "EFFFFFFFFGGFFFGGFFFEEFGFGFEEEEEEEEEEEEEEEEEEEEDEDEDDDDD" + + "CDCDEEEEEEEEEEEEEEEEEEEEBABABBBBDCFFFGGGEDCDCDCDCDCDCDCDCD" + + "CDCEEEEDDDDDDDCDCDCEFEFDDEEFFDEDEEEBDDBBDDDDDDCCCCCCCCEFED" + + "DDCDCDEEEEEEEEEEFEEEEEEDDEEDDEE"; + for (i = 0; i < b.length; ++i) { + b[i] = s.charAt(i) - 'E'; + } + SIZE = b; + + // code to generate the above string + // + // int NA = 0; // not applicable (unused opcode or variable size opcode) + // + // b = new int[] { + // 0, //NOP, // visitInsn + // 1, //ACONST_NULL, // - + // 1, //ICONST_M1, // - + // 1, //ICONST_0, // - + // 1, //ICONST_1, // - + // 1, //ICONST_2, // - + // 1, //ICONST_3, // - + // 1, //ICONST_4, // - + // 1, //ICONST_5, // - + // 2, //LCONST_0, // - + // 2, //LCONST_1, // - + // 1, //FCONST_0, // - + // 1, //FCONST_1, // - + // 1, //FCONST_2, // - + // 2, //DCONST_0, // - + // 2, //DCONST_1, // - + // 1, //BIPUSH, // visitIntInsn + // 1, //SIPUSH, // - + // 1, //LDC, // visitLdcInsn + // NA, //LDC_W, // - + // NA, //LDC2_W, // - + // 1, //ILOAD, // visitVarInsn + // 2, //LLOAD, // - + // 1, //FLOAD, // - + // 2, //DLOAD, // - + // 1, //ALOAD, // - + // NA, //ILOAD_0, // - + // NA, //ILOAD_1, // - + // NA, //ILOAD_2, // - + // NA, //ILOAD_3, // - + // NA, //LLOAD_0, // - + // NA, //LLOAD_1, // - + // NA, //LLOAD_2, // - + // NA, //LLOAD_3, // - + // NA, //FLOAD_0, // - + // NA, //FLOAD_1, // - + // NA, //FLOAD_2, // - + // NA, //FLOAD_3, // - + // NA, //DLOAD_0, // - + // NA, //DLOAD_1, // - + // NA, //DLOAD_2, // - + // NA, //DLOAD_3, // - + // NA, //ALOAD_0, // - + // NA, //ALOAD_1, // - + // NA, //ALOAD_2, // - + // NA, //ALOAD_3, // - + // -1, //IALOAD, // visitInsn + // 0, //LALOAD, // - + // -1, //FALOAD, // - + // 0, //DALOAD, // - + // -1, //AALOAD, // - + // -1, //BALOAD, // - + // -1, //CALOAD, // - + // -1, //SALOAD, // - + // -1, //ISTORE, // visitVarInsn + // -2, //LSTORE, // - + // -1, //FSTORE, // - + // -2, //DSTORE, // - + // -1, //ASTORE, // - + // NA, //ISTORE_0, // - + // NA, //ISTORE_1, // - + // NA, //ISTORE_2, // - + // NA, //ISTORE_3, // - + // NA, //LSTORE_0, // - + // NA, //LSTORE_1, // - + // NA, //LSTORE_2, // - + // NA, //LSTORE_3, // - + // NA, //FSTORE_0, // - + // NA, //FSTORE_1, // - + // NA, //FSTORE_2, // - + // NA, //FSTORE_3, // - + // NA, //DSTORE_0, // - + // NA, //DSTORE_1, // - + // NA, //DSTORE_2, // - + // NA, //DSTORE_3, // - + // NA, //ASTORE_0, // - + // NA, //ASTORE_1, // - + // NA, //ASTORE_2, // - + // NA, //ASTORE_3, // - + // -3, //IASTORE, // visitInsn + // -4, //LASTORE, // - + // -3, //FASTORE, // - + // -4, //DASTORE, // - + // -3, //AASTORE, // - + // -3, //BASTORE, // - + // -3, //CASTORE, // - + // -3, //SASTORE, // - + // -1, //POP, // - + // -2, //POP2, // - + // 1, //DUP, // - + // 1, //DUP_X1, // - + // 1, //DUP_X2, // - + // 2, //DUP2, // - + // 2, //DUP2_X1, // - + // 2, //DUP2_X2, // - + // 0, //SWAP, // - + // -1, //IADD, // - + // -2, //LADD, // - + // -1, //FADD, // - + // -2, //DADD, // - + // -1, //ISUB, // - + // -2, //LSUB, // - + // -1, //FSUB, // - + // -2, //DSUB, // - + // -1, //IMUL, // - + // -2, //LMUL, // - + // -1, //FMUL, // - + // -2, //DMUL, // - + // -1, //IDIV, // - + // -2, //LDIV, // - + // -1, //FDIV, // - + // -2, //DDIV, // - + // -1, //IREM, // - + // -2, //LREM, // - + // -1, //FREM, // - + // -2, //DREM, // - + // 0, //INEG, // - + // 0, //LNEG, // - + // 0, //FNEG, // - + // 0, //DNEG, // - + // -1, //ISHL, // - + // -1, //LSHL, // - + // -1, //ISHR, // - + // -1, //LSHR, // - + // -1, //IUSHR, // - + // -1, //LUSHR, // - + // -1, //IAND, // - + // -2, //LAND, // - + // -1, //IOR, // - + // -2, //LOR, // - + // -1, //IXOR, // - + // -2, //LXOR, // - + // 0, //IINC, // visitIincInsn + // 1, //I2L, // visitInsn + // 0, //I2F, // - + // 1, //I2D, // - + // -1, //L2I, // - + // -1, //L2F, // - + // 0, //L2D, // - + // 0, //F2I, // - + // 1, //F2L, // - + // 1, //F2D, // - + // -1, //D2I, // - + // 0, //D2L, // - + // -1, //D2F, // - + // 0, //I2B, // - + // 0, //I2C, // - + // 0, //I2S, // - + // -3, //LCMP, // - + // -1, //FCMPL, // - + // -1, //FCMPG, // - + // -3, //DCMPL, // - + // -3, //DCMPG, // - + // -1, //IFEQ, // visitJumpInsn + // -1, //IFNE, // - + // -1, //IFLT, // - + // -1, //IFGE, // - + // -1, //IFGT, // - + // -1, //IFLE, // - + // -2, //IF_ICMPEQ, // - + // -2, //IF_ICMPNE, // - + // -2, //IF_ICMPLT, // - + // -2, //IF_ICMPGE, // - + // -2, //IF_ICMPGT, // - + // -2, //IF_ICMPLE, // - + // -2, //IF_ACMPEQ, // - + // -2, //IF_ACMPNE, // - + // 0, //GOTO, // - + // 1, //JSR, // - + // 0, //RET, // visitVarInsn + // -1, //TABLESWITCH, // visiTableSwitchInsn + // -1, //LOOKUPSWITCH, // visitLookupSwitch + // -1, //IRETURN, // visitInsn + // -2, //LRETURN, // - + // -1, //FRETURN, // - + // -2, //DRETURN, // - + // -1, //ARETURN, // - + // 0, //RETURN, // - + // NA, //GETSTATIC, // visitFieldInsn + // NA, //PUTSTATIC, // - + // NA, //GETFIELD, // - + // NA, //PUTFIELD, // - + // NA, //INVOKEVIRTUAL, // visitMethodInsn + // NA, //INVOKESPECIAL, // - + // NA, //INVOKESTATIC, // - + // NA, //INVOKEINTERFACE, // - + // NA, //UNUSED, // NOT VISITED + // 1, //NEW, // visitTypeInsn + // 0, //NEWARRAY, // visitIntInsn + // 0, //ANEWARRAY, // visitTypeInsn + // 0, //ARRAYLENGTH, // visitInsn + // NA, //ATHROW, // - + // 0, //CHECKCAST, // visitTypeInsn + // 0, //INSTANCEOF, // - + // -1, //MONITORENTER, // visitInsn + // -1, //MONITOREXIT, // - + // NA, //WIDE, // NOT VISITED + // NA, //MULTIANEWARRAY, // visitMultiANewArrayInsn + // -1, //IFNULL, // visitJumpInsn + // -1, //IFNONNULL, // - + // NA, //GOTO_W, // - + // NA, //JSR_W, // - + // }; + // for (i = 0; i < b.length; ++i) { + // System.err.print((char)('E' + b[i])); + // } + // System.err.println(); + } + + /** + * The label (i.e. basic block) to which these input and output stack map + * frames correspond. + */ + Label owner; + + /** + * The input stack map frame locals. + */ + int[] inputLocals; + + /** + * The input stack map frame stack. + */ + int[] inputStack; + + /** + * The output stack map frame locals. + */ + private int[] outputLocals; + + /** + * The output stack map frame stack. + */ + private int[] outputStack; + + /** + * Relative size of the output stack. The exact semantics of this field + * depends on the algorithm that is used. + * + * When only the maximum stack size is computed, this field is the size of + * the output stack relatively to the top of the input stack. + * + * When the stack map frames are completely computed, this field is the + * actual number of types in {@link #outputStack}. + */ + private int outputStackTop; + + /** + * Number of types that are initialized in the basic block. + * + * @see #initializations + */ + private int initializationCount; + + /** + * The types that are initialized in the basic block. A constructor + * invocation on an UNINITIALIZED or UNINITIALIZED_THIS type must replace + * <i>every occurence</i> of this type in the local variables and in the + * operand stack. This cannot be done during the first phase of the + * algorithm since, during this phase, the local variables and the operand + * stack are not completely computed. It is therefore necessary to store the + * types on which constructors are invoked in the basic block, in order to + * do this replacement during the second phase of the algorithm, where the + * frames are fully computed. Note that this array can contain types that + * are relative to input locals or to the input stack (see below for the + * description of the algorithm). + */ + private int[] initializations; + + /** + * Returns the output frame local variable type at the given index. + * + * @param local the index of the local that must be returned. + * @return the output frame local variable type at the given index. + */ + private int get(final int local) { + if (outputLocals == null || local >= outputLocals.length) { + // this local has never been assigned in this basic block, + // so it is still equal to its value in the input frame + return LOCAL | local; + } else { + int type = outputLocals[local]; + if (type == 0) { + // this local has never been assigned in this basic block, + // so it is still equal to its value in the input frame + type = outputLocals[local] = LOCAL | local; + } + return type; + } + } + + /** + * Sets the output frame local variable type at the given index. + * + * @param local the index of the local that must be set. + * @param type the value of the local that must be set. + */ + private void set(final int local, final int type) { + // creates and/or resizes the output local variables array if necessary + if (outputLocals == null) { + outputLocals = new int[10]; + } + int n = outputLocals.length; + if (local >= n) { + int[] t = new int[Math.max(local + 1, 2 * n)]; + System.arraycopy(outputLocals, 0, t, 0, n); + outputLocals = t; + } + // sets the local variable + outputLocals[local] = type; + } + + /** + * Pushes a new type onto the output frame stack. + * + * @param type the type that must be pushed. + */ + private void push(final int type) { + // creates and/or resizes the output stack array if necessary + if (outputStack == null) { + outputStack = new int[10]; + } + int n = outputStack.length; + if (outputStackTop >= n) { + int[] t = new int[Math.max(outputStackTop + 1, 2 * n)]; + System.arraycopy(outputStack, 0, t, 0, n); + outputStack = t; + } + // pushes the type on the output stack + outputStack[outputStackTop++] = type; + // updates the maximun height reached by the output stack, if needed + int top = owner.inputStackTop + outputStackTop; + if (top > owner.outputStackMax) { + owner.outputStackMax = top; + } + } + + /** + * Pushes a new type onto the output frame stack. + * + * @param cw the ClassWriter to which this label belongs. + * @param desc the descriptor of the type to be pushed. Can also be a method + * descriptor (in this case this method pushes its return type onto + * the output frame stack). + */ + private void push(final ClassWriter cw, final String desc) { + int type = type(cw, desc); + if (type != 0) { + push(type); + if (type == LONG || type == DOUBLE) { + push(TOP); + } + } + } + + /** + * Returns the int encoding of the given type. + * + * @param cw the ClassWriter to which this label belongs. + * @param desc a type descriptor. + * @return the int encoding of the given type. + */ + private static int type(final ClassWriter cw, final String desc) { + String t; + int index = desc.charAt(0) == '(' ? desc.indexOf(')') + 1 : 0; + switch (desc.charAt(index)) { + case 'V': + return 0; + case 'Z': + case 'C': + case 'B': + case 'S': + case 'I': + return INTEGER; + case 'F': + return FLOAT; + case 'J': + return LONG; + case 'D': + return DOUBLE; + case 'L': + // stores the internal name, not the descriptor! + t = desc.substring(index + 1, desc.length() - 1); + return OBJECT | cw.addType(t); + // case '[': + default: + // extracts the dimensions and the element type + int data; + int dims = index + 1; + while (desc.charAt(dims) == '[') { + ++dims; + } + switch (desc.charAt(dims)) { + case 'Z': + data = BOOLEAN; + break; + case 'C': + data = CHAR; + break; + case 'B': + data = BYTE; + break; + case 'S': + data = SHORT; + break; + case 'I': + data = INTEGER; + break; + case 'F': + data = FLOAT; + break; + case 'J': + data = LONG; + break; + case 'D': + data = DOUBLE; + break; + // case 'L': + default: + // stores the internal name, not the descriptor + t = desc.substring(dims + 1, desc.length() - 1); + data = OBJECT | cw.addType(t); + } + return (dims - index) << 28 | data; + } + } + + /** + * Pops a type from the output frame stack and returns its value. + * + * @return the type that has been popped from the output frame stack. + */ + private int pop() { + if (outputStackTop > 0) { + return outputStack[--outputStackTop]; + } else { + // if the output frame stack is empty, pops from the input stack + return STACK | -(--owner.inputStackTop); + } + } + + /** + * Pops the given number of types from the output frame stack. + * + * @param elements the number of types that must be popped. + */ + private void pop(final int elements) { + if (outputStackTop >= elements) { + outputStackTop -= elements; + } else { + // if the number of elements to be popped is greater than the number + // of elements in the output stack, clear it, and pops the remaining + // elements from the input stack. + owner.inputStackTop -= elements - outputStackTop; + outputStackTop = 0; + } + } + + /** + * Pops a type from the output frame stack. + * + * @param desc the descriptor of the type to be popped. Can also be a method + * descriptor (in this case this method pops the types corresponding + * to the method arguments). + */ + private void pop(final String desc) { + char c = desc.charAt(0); + if (c == '(') { + pop((MethodWriter.getArgumentsAndReturnSizes(desc) >> 2) - 1); + } else if (c == 'J' || c == 'D') { + pop(2); + } else { + pop(1); + } + } + + /** + * Adds a new type to the list of types on which a constructor is invoked in + * the basic block. + * + * @param var a type on a which a constructor is invoked. + */ + private void init(final int var) { + // creates and/or resizes the initializations array if necessary + if (initializations == null) { + initializations = new int[2]; + } + int n = initializations.length; + if (initializationCount >= n) { + int[] t = new int[Math.max(initializationCount + 1, 2 * n)]; + System.arraycopy(initializations, 0, t, 0, n); + initializations = t; + } + // stores the type to be initialized + initializations[initializationCount++] = var; + } + + /** + * Replaces the given type with the appropriate type if it is one of the + * types on which a constructor is invoked in the basic block. + * + * @param cw the ClassWriter to which this label belongs. + * @param t a type + * @return t or, if t is one of the types on which a constructor is invoked + * in the basic block, the type corresponding to this constructor. + */ + private int init(final ClassWriter cw, final int t) { + int s; + if (t == UNINITIALIZED_THIS) { + s = OBJECT | cw.addType(cw.thisName); + } else if ((t & (DIM | BASE_KIND)) == UNINITIALIZED) { + String type = cw.typeTable[t & BASE_VALUE].strVal1; + s = OBJECT | cw.addType(type); + } else { + return t; + } + for (int j = 0; j < initializationCount; ++j) { + int u = initializations[j]; + int dim = u & DIM; + int kind = u & KIND; + if (kind == LOCAL) { + u = dim + inputLocals[u & VALUE]; + } else if (kind == STACK) { + u = dim + inputStack[inputStack.length - (u & VALUE)]; + } + if (t == u) { + return s; + } + } + return t; + } + + /** + * Initializes the input frame of the first basic block from the method + * descriptor. + * + * @param cw the ClassWriter to which this label belongs. + * @param access the access flags of the method to which this label belongs. + * @param args the formal parameter types of this method. + * @param maxLocals the maximum number of local variables of this method. + */ + void initInputFrame( + final ClassWriter cw, + final int access, + final Type[] args, + final int maxLocals) + { + inputLocals = new int[maxLocals]; + inputStack = new int[0]; + int i = 0; + if ((access & Opcodes.ACC_STATIC) == 0) { + if ((access & MethodWriter.ACC_CONSTRUCTOR) == 0) { + inputLocals[i++] = OBJECT | cw.addType(cw.thisName); + } else { + inputLocals[i++] = UNINITIALIZED_THIS; + } + } + for (int j = 0; j < args.length; ++j) { + int t = type(cw, args[j].getDescriptor()); + inputLocals[i++] = t; + if (t == LONG || t == DOUBLE) { + inputLocals[i++] = TOP; + } + } + while (i < maxLocals) { + inputLocals[i++] = TOP; + } + } + + /** + * Simulates the action of the given instruction on the output stack frame. + * + * @param opcode the opcode of the instruction. + * @param arg the operand of the instruction, if any. + * @param cw the class writer to which this label belongs. + * @param item the operand of the instructions, if any. + */ + void execute( + final int opcode, + final int arg, + final ClassWriter cw, + final Item item) + { + int t1, t2, t3, t4; + switch (opcode) { + case Opcodes.NOP: + case Opcodes.INEG: + case Opcodes.LNEG: + case Opcodes.FNEG: + case Opcodes.DNEG: + case Opcodes.I2B: + case Opcodes.I2C: + case Opcodes.I2S: + case Opcodes.GOTO: + case Opcodes.RETURN: + break; + case Opcodes.ACONST_NULL: + push(NULL); + break; + case Opcodes.ICONST_M1: + case Opcodes.ICONST_0: + case Opcodes.ICONST_1: + case Opcodes.ICONST_2: + case Opcodes.ICONST_3: + case Opcodes.ICONST_4: + case Opcodes.ICONST_5: + case Opcodes.BIPUSH: + case Opcodes.SIPUSH: + case Opcodes.ILOAD: + push(INTEGER); + break; + case Opcodes.LCONST_0: + case Opcodes.LCONST_1: + case Opcodes.LLOAD: + push(LONG); + push(TOP); + break; + case Opcodes.FCONST_0: + case Opcodes.FCONST_1: + case Opcodes.FCONST_2: + case Opcodes.FLOAD: + push(FLOAT); + break; + case Opcodes.DCONST_0: + case Opcodes.DCONST_1: + case Opcodes.DLOAD: + push(DOUBLE); + push(TOP); + break; + case Opcodes.LDC: + switch (item.type) { + case ClassWriter.INT: + push(INTEGER); + break; + case ClassWriter.LONG: + push(LONG); + push(TOP); + break; + case ClassWriter.FLOAT: + push(FLOAT); + break; + case ClassWriter.DOUBLE: + push(DOUBLE); + push(TOP); + break; + case ClassWriter.CLASS: + push(OBJECT | cw.addType("java/lang/Class")); + break; + // case ClassWriter.STR: + default: + push(OBJECT | cw.addType("java/lang/String")); + } + break; + case Opcodes.ALOAD: + push(get(arg)); + break; + case Opcodes.IALOAD: + case Opcodes.BALOAD: + case Opcodes.CALOAD: + case Opcodes.SALOAD: + pop(2); + push(INTEGER); + break; + case Opcodes.LALOAD: + case Opcodes.D2L: + pop(2); + push(LONG); + push(TOP); + break; + case Opcodes.FALOAD: + pop(2); + push(FLOAT); + break; + case Opcodes.DALOAD: + case Opcodes.L2D: + pop(2); + push(DOUBLE); + push(TOP); + break; + case Opcodes.AALOAD: + pop(1); + t1 = pop(); + push(ELEMENT_OF + t1); + break; + case Opcodes.ISTORE: + case Opcodes.FSTORE: + case Opcodes.ASTORE: + t1 = pop(); + set(arg, t1); + if (arg > 0) { + t2 = get(arg - 1); + // if t2 is of kind STACK or LOCAL we cannot know its size! + if (t2 == LONG || t2 == DOUBLE) { + set(arg - 1, TOP); + } + } + break; + case Opcodes.LSTORE: + case Opcodes.DSTORE: + pop(1); + t1 = pop(); + set(arg, t1); + set(arg + 1, TOP); + if (arg > 0) { + t2 = get(arg - 1); + // if t2 is of kind STACK or LOCAL we cannot know its size! + if (t2 == LONG || t2 == DOUBLE) { + set(arg - 1, TOP); + } + } + break; + case Opcodes.IASTORE: + case Opcodes.BASTORE: + case Opcodes.CASTORE: + case Opcodes.SASTORE: + case Opcodes.FASTORE: + case Opcodes.AASTORE: + pop(3); + break; + case Opcodes.LASTORE: + case Opcodes.DASTORE: + pop(4); + break; + case Opcodes.POP: + case Opcodes.IFEQ: + case Opcodes.IFNE: + case Opcodes.IFLT: + case Opcodes.IFGE: + case Opcodes.IFGT: + case Opcodes.IFLE: + case Opcodes.IRETURN: + case Opcodes.FRETURN: + case Opcodes.ARETURN: + case Opcodes.TABLESWITCH: + case Opcodes.LOOKUPSWITCH: + case Opcodes.ATHROW: + case Opcodes.MONITORENTER: + case Opcodes.MONITOREXIT: + case Opcodes.IFNULL: + case Opcodes.IFNONNULL: + pop(1); + break; + case Opcodes.POP2: + case Opcodes.IF_ICMPEQ: + case Opcodes.IF_ICMPNE: + case Opcodes.IF_ICMPLT: + case Opcodes.IF_ICMPGE: + case Opcodes.IF_ICMPGT: + case Opcodes.IF_ICMPLE: + case Opcodes.IF_ACMPEQ: + case Opcodes.IF_ACMPNE: + case Opcodes.LRETURN: + case Opcodes.DRETURN: + pop(2); + break; + case Opcodes.DUP: + t1 = pop(); + push(t1); + push(t1); + break; + case Opcodes.DUP_X1: + t1 = pop(); + t2 = pop(); + push(t1); + push(t2); + push(t1); + break; + case Opcodes.DUP_X2: + t1 = pop(); + t2 = pop(); + t3 = pop(); + push(t1); + push(t3); + push(t2); + push(t1); + break; + case Opcodes.DUP2: + t1 = pop(); + t2 = pop(); + push(t2); + push(t1); + push(t2); + push(t1); + break; + case Opcodes.DUP2_X1: + t1 = pop(); + t2 = pop(); + t3 = pop(); + push(t2); + push(t1); + push(t3); + push(t2); + push(t1); + break; + case Opcodes.DUP2_X2: + t1 = pop(); + t2 = pop(); + t3 = pop(); + t4 = pop(); + push(t2); + push(t1); + push(t4); + push(t3); + push(t2); + push(t1); + break; + case Opcodes.SWAP: + t1 = pop(); + t2 = pop(); + push(t1); + push(t2); + break; + case Opcodes.IADD: + case Opcodes.ISUB: + case Opcodes.IMUL: + case Opcodes.IDIV: + case Opcodes.IREM: + case Opcodes.IAND: + case Opcodes.IOR: + case Opcodes.IXOR: + case Opcodes.ISHL: + case Opcodes.ISHR: + case Opcodes.IUSHR: + case Opcodes.L2I: + case Opcodes.D2I: + case Opcodes.FCMPL: + case Opcodes.FCMPG: + pop(2); + push(INTEGER); + break; + case Opcodes.LADD: + case Opcodes.LSUB: + case Opcodes.LMUL: + case Opcodes.LDIV: + case Opcodes.LREM: + case Opcodes.LAND: + case Opcodes.LOR: + case Opcodes.LXOR: + pop(4); + push(LONG); + push(TOP); + break; + case Opcodes.FADD: + case Opcodes.FSUB: + case Opcodes.FMUL: + case Opcodes.FDIV: + case Opcodes.FREM: + case Opcodes.L2F: + case Opcodes.D2F: + pop(2); + push(FLOAT); + break; + case Opcodes.DADD: + case Opcodes.DSUB: + case Opcodes.DMUL: + case Opcodes.DDIV: + case Opcodes.DREM: + pop(4); + push(DOUBLE); + push(TOP); + break; + case Opcodes.LSHL: + case Opcodes.LSHR: + case Opcodes.LUSHR: + pop(3); + push(LONG); + push(TOP); + break; + case Opcodes.IINC: + set(arg, INTEGER); + break; + case Opcodes.I2L: + case Opcodes.F2L: + pop(1); + push(LONG); + push(TOP); + break; + case Opcodes.I2F: + pop(1); + push(FLOAT); + break; + case Opcodes.I2D: + case Opcodes.F2D: + pop(1); + push(DOUBLE); + push(TOP); + break; + case Opcodes.F2I: + case Opcodes.ARRAYLENGTH: + case Opcodes.INSTANCEOF: + pop(1); + push(INTEGER); + break; + case Opcodes.LCMP: + case Opcodes.DCMPL: + case Opcodes.DCMPG: + pop(4); + push(INTEGER); + break; + case Opcodes.JSR: + case Opcodes.RET: + throw new RuntimeException("JSR/RET are not supported with computeFrames option"); + case Opcodes.GETSTATIC: + push(cw, item.strVal3); + break; + case Opcodes.PUTSTATIC: + pop(item.strVal3); + break; + case Opcodes.GETFIELD: + pop(1); + push(cw, item.strVal3); + break; + case Opcodes.PUTFIELD: + pop(item.strVal3); + pop(); + break; + case Opcodes.INVOKEVIRTUAL: + case Opcodes.INVOKESPECIAL: + case Opcodes.INVOKESTATIC: + case Opcodes.INVOKEINTERFACE: + pop(item.strVal3); + if (opcode != Opcodes.INVOKESTATIC) { + t1 = pop(); + if (opcode == Opcodes.INVOKESPECIAL + && item.strVal2.charAt(0) == '<') + { + init(t1); + } + } + push(cw, item.strVal3); + break; + case Opcodes.NEW: + push(UNINITIALIZED | cw.addUninitializedType(item.strVal1, arg)); + break; + case Opcodes.NEWARRAY: + pop(); + switch (arg) { + case Opcodes.T_BOOLEAN: + push(ARRAY_OF | BOOLEAN); + break; + case Opcodes.T_CHAR: + push(ARRAY_OF | CHAR); + break; + case Opcodes.T_BYTE: + push(ARRAY_OF | BYTE); + break; + case Opcodes.T_SHORT: + push(ARRAY_OF | SHORT); + break; + case Opcodes.T_INT: + push(ARRAY_OF | INTEGER); + break; + case Opcodes.T_FLOAT: + push(ARRAY_OF | FLOAT); + break; + case Opcodes.T_DOUBLE: + push(ARRAY_OF | DOUBLE); + break; + // case Opcodes.T_LONG: + default: + push(ARRAY_OF | LONG); + break; + } + break; + case Opcodes.ANEWARRAY: + String s = item.strVal1; + pop(); + if (s.charAt(0) == '[') { + push(cw, '[' + s); + } else { + push(ARRAY_OF | OBJECT | cw.addType(s)); + } + break; + case Opcodes.CHECKCAST: + s = item.strVal1; + pop(); + if (s.charAt(0) == '[') { + push(cw, s); + } else { + push(OBJECT | cw.addType(s)); + } + break; + // case Opcodes.MULTIANEWARRAY: + default: + pop(arg); + push(cw, item.strVal1); + break; + } + } + + /** + * Merges the input frame of the given basic block with the input and output + * frames of this basic block. Returns <tt>true</tt> if the input frame of + * the given label has been changed by this operation. + * + * @param cw the ClassWriter to which this label belongs. + * @param frame the basic block whose input frame must be updated. + * @param edge the kind of the {@link Edge} between this label and 'label'. + * See {@link Edge#info}. + * @return <tt>true</tt> if the input frame of the given label has been + * changed by this operation. + */ + boolean merge(final ClassWriter cw, final Frame frame, final int edge) { + boolean changed = false; + int i, s, dim, kind, t; + + int nLocal = inputLocals.length; + int nStack = inputStack.length; + if (frame.inputLocals == null) { + frame.inputLocals = new int[nLocal]; + changed = true; + } + + for (i = 0; i < nLocal; ++i) { + if (outputLocals != null && i < outputLocals.length) { + s = outputLocals[i]; + if (s == 0) { + t = inputLocals[i]; + } else { + dim = s & DIM; + kind = s & KIND; + if (kind == LOCAL) { + t = dim + inputLocals[s & VALUE]; + } else if (kind == STACK) { + t = dim + inputStack[nStack - (s & VALUE)]; + } else { + t = s; + } + } + } else { + t = inputLocals[i]; + } + if (initializations != null) { + t = init(cw, t); + } + changed |= merge(cw, t, frame.inputLocals, i); + } + + if (edge > 0) { + for (i = 0; i < nLocal; ++i) { + t = inputLocals[i]; + changed |= merge(cw, t, frame.inputLocals, i); + } + if (frame.inputStack == null) { + frame.inputStack = new int[1]; + changed = true; + } + changed |= merge(cw, edge, frame.inputStack, 0); + return changed; + } + + int nInputStack = inputStack.length + owner.inputStackTop; + if (frame.inputStack == null) { + frame.inputStack = new int[nInputStack + outputStackTop]; + changed = true; + } + + for (i = 0; i < nInputStack; ++i) { + t = inputStack[i]; + if (initializations != null) { + t = init(cw, t); + } + changed |= merge(cw, t, frame.inputStack, i); + } + for (i = 0; i < outputStackTop; ++i) { + s = outputStack[i]; + dim = s & DIM; + kind = s & KIND; + if (kind == LOCAL) { + t = dim + inputLocals[s & VALUE]; + } else if (kind == STACK) { + t = dim + inputStack[nStack - (s & VALUE)]; + } else { + t = s; + } + if (initializations != null) { + t = init(cw, t); + } + changed |= merge(cw, t, frame.inputStack, nInputStack + i); + } + return changed; + } + + /** + * Merges the type at the given index in the given type array with the given + * type. Returns <tt>true</tt> if the type array has been modified by this + * operation. + * + * @param cw the ClassWriter to which this label belongs. + * @param t the type with which the type array element must be merged. + * @param types an array of types. + * @param index the index of the type that must be merged in 'types'. + * @return <tt>true</tt> if the type array has been modified by this + * operation. + */ + private static boolean merge( + final ClassWriter cw, + int t, + final int[] types, + final int index) + { + int u = types[index]; + if (u == t) { + // if the types are equal, merge(u,t)=u, so there is no change + return false; + } + if ((t & ~DIM) == NULL) { + if (u == NULL) { + return false; + } + t = NULL; + } + if (u == 0) { + // if types[index] has never been assigned, merge(u,t)=t + types[index] = t; + return true; + } + int v; + if ((u & BASE_KIND) == OBJECT || (u & DIM) != 0) { + // if u is a reference type of any dimension + if (t == NULL) { + // if t is the NULL type, merge(u,t)=u, so there is no change + return false; + } else if ((t & (DIM | BASE_KIND)) == (u & (DIM | BASE_KIND))) { + if ((u & BASE_KIND) == OBJECT) { + // if t is also a reference type, and if u and t have the + // same dimension merge(u,t) = dim(t) | common parent of the + // element types of u and t + v = (t & DIM) | OBJECT + | cw.getMergedType(t & BASE_VALUE, u & BASE_VALUE); + } else { + // if u and t are array types, but not with the same element + // type, merge(u,t)=java/lang/Object + v = OBJECT | cw.addType("java/lang/Object"); + } + } else if ((t & BASE_KIND) == OBJECT || (t & DIM) != 0) { + // if t is any other reference or array type, + // merge(u,t)=java/lang/Object + v = OBJECT | cw.addType("java/lang/Object"); + } else { + // if t is any other type, merge(u,t)=TOP + v = TOP; + } + } else if (u == NULL) { + // if u is the NULL type, merge(u,t)=t, + // or TOP if t is not a reference type + v = (t & BASE_KIND) == OBJECT || (t & DIM) != 0 ? t : TOP; + } else { + // if u is any other type, merge(u,t)=TOP whatever t + v = TOP; + } + if (u != v) { + types[index] = v; + return true; + } + return false; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/ws/org/objectweb/asm/Handler.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,100 @@ +/* + * Copyright 2005-2009 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2007 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.sun.xml.internal.ws.org.objectweb.asm; + +/** + * Information about an exception handler block. + * + * @author Eric Bruneton + */ +class Handler { + + /** + * Beginning of the exception handler's scope (inclusive). + */ + Label start; + + /** + * End of the exception handler's scope (exclusive). + */ + Label end; + + /** + * Beginning of the exception handler's code. + */ + Label handler; + + /** + * Internal name of the type of exceptions handled by this handler, or + * <tt>null</tt> to catch any exceptions. + */ + String desc; + + /** + * Constant pool index of the internal name of the type of exceptions + * handled by this handler, or 0 to catch any exceptions. + */ + int type; + + /** + * Next exception handler block info. + */ + Handler next; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/ws/org/objectweb/asm/Item.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,286 @@ +/* + * Copyright 2005-2009 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2007 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.sun.xml.internal.ws.org.objectweb.asm; + +/** + * A constant pool item. Constant pool items can be created with the 'newXXX' + * methods in the {@link ClassWriter} class. + * + * @author Eric Bruneton + */ +final class Item { + + /** + * Index of this item in the constant pool. + */ + int index; + + /** + * Type of this constant pool item. A single class is used to represent all + * constant pool item types, in order to minimize the bytecode size of this + * package. The value of this field is one of {@link ClassWriter#INT}, + * {@link ClassWriter#LONG}, {@link ClassWriter#FLOAT}, + * {@link ClassWriter#DOUBLE}, {@link ClassWriter#UTF8}, + * {@link ClassWriter#STR}, {@link ClassWriter#CLASS}, + * {@link ClassWriter#NAME_TYPE}, {@link ClassWriter#FIELD}, + * {@link ClassWriter#METH}, {@link ClassWriter#IMETH}. + * + * Special Item types are used for Items that are stored in the ClassWriter + * {@link ClassWriter#typeTable}, instead of the constant pool, in order to + * avoid clashes with normal constant pool items in the ClassWriter constant + * pool's hash table. These special item types are + * {@link ClassWriter#TYPE_NORMAL}, {@link ClassWriter#TYPE_UNINIT} and + * {@link ClassWriter#TYPE_MERGED}. + */ + int type; + + /** + * Value of this item, for an integer item. + */ + int intVal; + + /** + * Value of this item, for a long item. + */ + long longVal; + + /** + * First part of the value of this item, for items that do not hold a + * primitive value. + */ + String strVal1; + + /** + * Second part of the value of this item, for items that do not hold a + * primitive value. + */ + String strVal2; + + /** + * Third part of the value of this item, for items that do not hold a + * primitive value. + */ + String strVal3; + + /** + * The hash code value of this constant pool item. + */ + int hashCode; + + /** + * Link to another constant pool item, used for collision lists in the + * constant pool's hash table. + */ + Item next; + + /** + * Constructs an uninitialized {@link Item}. + */ + Item() { + } + + /** + * Constructs an uninitialized {@link Item} for constant pool element at + * given position. + * + * @param index index of the item to be constructed. + */ + Item(final int index) { + this.index = index; + } + + /** + * Constructs a copy of the given item. + * + * @param index index of the item to be constructed. + * @param i the item that must be copied into the item to be constructed. + */ + Item(final int index, final Item i) { + this.index = index; + type = i.type; + intVal = i.intVal; + longVal = i.longVal; + strVal1 = i.strVal1; + strVal2 = i.strVal2; + strVal3 = i.strVal3; + hashCode = i.hashCode; + } + + /** + * Sets this item to an integer item. + * + * @param intVal the value of this item. + */ + void set(final int intVal) { + this.type = ClassWriter.INT; + this.intVal = intVal; + this.hashCode = 0x7FFFFFFF & (type + intVal); + } + + /** + * Sets this item to a long item. + * + * @param longVal the value of this item. + */ + void set(final long longVal) { + this.type = ClassWriter.LONG; + this.longVal = longVal; + this.hashCode = 0x7FFFFFFF & (type + (int) longVal); + } + + /** + * Sets this item to a float item. + * + * @param floatVal the value of this item. + */ + void set(final float floatVal) { + this.type = ClassWriter.FLOAT; + this.intVal = Float.floatToRawIntBits(floatVal); + this.hashCode = 0x7FFFFFFF & (type + (int) floatVal); + } + + /** + * Sets this item to a double item. + * + * @param doubleVal the value of this item. + */ + void set(final double doubleVal) { + this.type = ClassWriter.DOUBLE; + this.longVal = Double.doubleToRawLongBits(doubleVal); + this.hashCode = 0x7FFFFFFF & (type + (int) doubleVal); + } + + /** + * Sets this item to an item that do not hold a primitive value. + * + * @param type the type of this item. + * @param strVal1 first part of the value of this item. + * @param strVal2 second part of the value of this item. + * @param strVal3 third part of the value of this item. + */ + void set( + final int type, + final String strVal1, + final String strVal2, + final String strVal3) + { + this.type = type; + this.strVal1 = strVal1; + this.strVal2 = strVal2; + this.strVal3 = strVal3; + switch (type) { + case ClassWriter.UTF8: + case ClassWriter.STR: + case ClassWriter.CLASS: + case ClassWriter.TYPE_NORMAL: + hashCode = 0x7FFFFFFF & (type + strVal1.hashCode()); + return; + case ClassWriter.NAME_TYPE: + hashCode = 0x7FFFFFFF & (type + strVal1.hashCode() + * strVal2.hashCode()); + return; + // ClassWriter.FIELD: + // ClassWriter.METH: + // ClassWriter.IMETH: + default: + hashCode = 0x7FFFFFFF & (type + strVal1.hashCode() + * strVal2.hashCode() * strVal3.hashCode()); + } + } + + /** + * Indicates if the given item is equal to this one. + * + * @param i the item to be compared to this one. + * @return <tt>true</tt> if the given item if equal to this one, + * <tt>false</tt> otherwise. + */ + boolean isEqualTo(final Item i) { + if (i.type == type) { + switch (type) { + case ClassWriter.INT: + case ClassWriter.FLOAT: + return i.intVal == intVal; + case ClassWriter.TYPE_MERGED: + case ClassWriter.LONG: + case ClassWriter.DOUBLE: + return i.longVal == longVal; + case ClassWriter.UTF8: + case ClassWriter.STR: + case ClassWriter.CLASS: + case ClassWriter.TYPE_NORMAL: + return i.strVal1.equals(strVal1); + case ClassWriter.TYPE_UNINIT: + return i.intVal == intVal && i.strVal1.equals(strVal1); + case ClassWriter.NAME_TYPE: + return i.strVal1.equals(strVal1) + && i.strVal2.equals(strVal2); + // ClassWriter.FIELD: + // ClassWriter.METH: + // ClassWriter.IMETH: + default: + return i.strVal1.equals(strVal1) + && i.strVal2.equals(strVal2) + && i.strVal3.equals(strVal3); + } + } + return false; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/ws/org/objectweb/asm/Label.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,556 @@ +/* + * Copyright 2005-2009 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2007 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.sun.xml.internal.ws.org.objectweb.asm; + +/** + * A label represents a position in the bytecode of a method. Labels are used + * for jump, goto, and switch instructions, and for try catch blocks. + * + * @author Eric Bruneton + */ +public class Label { + + /** + * Indicates if this label is only used for debug attributes. Such a label + * is not the start of a basic block, the target of a jump instruction, or + * an exception handler. It can be safely ignored in control flow graph + * analysis algorithms (for optimization purposes). + */ + static final int DEBUG = 1; + + /** + * Indicates if the position of this label is known. + */ + static final int RESOLVED = 2; + + /** + * Indicates if this label has been updated, after instruction resizing. + */ + static final int RESIZED = 4; + + /** + * Indicates if this basic block has been pushed in the basic block stack. + * See {@link MethodWriter#visitMaxs visitMaxs}. + */ + static final int PUSHED = 8; + + /** + * Indicates if this label is the target of a jump instruction, or the start + * of an exception handler. + */ + static final int TARGET = 16; + + /** + * Indicates if a stack map frame must be stored for this label. + */ + static final int STORE = 32; + + /** + * Indicates if this label corresponds to a reachable basic block. + */ + static final int REACHABLE = 64; + + /** + * Indicates if this basic block ends with a JSR instruction. + */ + static final int JSR = 128; + + /** + * Indicates if this basic block ends with a RET instruction. + */ + static final int RET = 256; + + /** + * Indicates if this basic block is the start of a subroutine. + */ + static final int SUBROUTINE = 512; + + /** + * Indicates if this subroutine basic block has been visited. + */ + static final int VISITED = 1024; + + /** + * Field used to associate user information to a label. Warning: this field + * is used by the ASM tree package. In order to use it with the ASM tree + * package you must override the {@link + * com.sun.xml.internal.ws.org.objectweb.asm.tree.MethodNode#getLabelNode} method. + */ + public Object info; + + /** + * Flags that indicate the status of this label. + * + * @see #DEBUG + * @see #RESOLVED + * @see #RESIZED + * @see #PUSHED + * @see #TARGET + * @see #STORE + * @see #REACHABLE + * @see #JSR + * @see #RET + */ + int status; + + /** + * The line number corresponding to this label, if known. + */ + int line; + + /** + * The position of this label in the code, if known. + */ + int position; + + /** + * Number of forward references to this label, times two. + */ + private int referenceCount; + + /** + * Informations about forward references. Each forward reference is + * described by two consecutive integers in this array: the first one is the + * position of the first byte of the bytecode instruction that contains the + * forward reference, while the second is the position of the first byte of + * the forward reference itself. In fact the sign of the first integer + * indicates if this reference uses 2 or 4 bytes, and its absolute value + * gives the position of the bytecode instruction. This array is also used + * as a bitset to store the subroutines to which a basic block belongs. This + * information is needed in {@linked MethodWriter#visitMaxs}, after all + * forward references have been resolved. Hence the same array can be used + * for both purposes without problems. + */ + private int[] srcAndRefPositions; + + // ------------------------------------------------------------------------ + + /* + * Fields for the control flow and data flow graph analysis algorithms (used + * to compute the maximum stack size or the stack map frames). A control + * flow graph contains one node per "basic block", and one edge per "jump" + * from one basic block to another. Each node (i.e., each basic block) is + * represented by the Label object that corresponds to the first instruction + * of this basic block. Each node also stores the list of its successors in + * the graph, as a linked list of Edge objects. + * + * The control flow analysis algorithms used to compute the maximum stack + * size or the stack map frames are similar and use two steps. The first + * step, during the visit of each instruction, builds information about the + * state of the local variables and the operand stack at the end of each + * basic block, called the "output frame", <i>relatively</i> to the frame + * state at the beginning of the basic block, which is called the "input + * frame", and which is <i>unknown</i> during this step. The second step, + * in {@link MethodWriter#visitMaxs}, is a fix point algorithm that + * computes information about the input frame of each basic block, from the + * input state of the first basic block (known from the method signature), + * and by the using the previously computed relative output frames. + * + * The algorithm used to compute the maximum stack size only computes the + * relative output and absolute input stack heights, while the algorithm + * used to compute stack map frames computes relative output frames and + * absolute input frames. + */ + + /** + * Start of the output stack relatively to the input stack. The exact + * semantics of this field depends on the algorithm that is used. + * + * When only the maximum stack size is computed, this field is the number of + * elements in the input stack. + * + * When the stack map frames are completely computed, this field is the + * offset of the first output stack element relatively to the top of the + * input stack. This offset is always negative or null. A null offset means + * that the output stack must be appended to the input stack. A -n offset + * means that the first n output stack elements must replace the top n input + * stack elements, and that the other elements must be appended to the input + * stack. + */ + int inputStackTop; + + /** + * Maximum height reached by the output stack, relatively to the top of the + * input stack. This maximum is always positive or null. + */ + int outputStackMax; + + /** + * Information about the input and output stack map frames of this basic + * block. This field is only used when {@link ClassWriter#COMPUTE_FRAMES} + * option is used. + */ + Frame frame; + + /** + * The successor of this label, in the order they are visited. This linked + * list does not include labels used for debug info only. If + * {@link ClassWriter#COMPUTE_FRAMES} option is used then, in addition, it + * does not contain successive labels that denote the same bytecode position + * (in this case only the first label appears in this list). + */ + Label successor; + + /** + * The successors of this node in the control flow graph. These successors + * are stored in a linked list of {@link Edge Edge} objects, linked to each + * other by their {@link Edge#next} field. + */ + Edge successors; + + /** + * The next basic block in the basic block stack. This stack is used in the + * main loop of the fix point algorithm used in the second step of the + * control flow analysis algorithms. + * + * @see MethodWriter#visitMaxs + */ + Label next; + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + + /** + * Constructs a new label. + */ + public Label() { + } + + // ------------------------------------------------------------------------ + // Methods to compute offsets and to manage forward references + // ------------------------------------------------------------------------ + + /** + * Returns the offset corresponding to this label. This offset is computed + * from the start of the method's bytecode. <i>This method is intended for + * {@link Attribute} sub classes, and is normally not needed by class + * generators or adapters.</i> + * + * @return the offset corresponding to this label. + * @throws IllegalStateException if this label is not resolved yet. + */ + public int getOffset() { + if ((status & RESOLVED) == 0) { + throw new IllegalStateException("Label offset position has not been resolved yet"); + } + return position; + } + + /** + * Puts a reference to this label in the bytecode of a method. If the + * position of the label is known, the offset is computed and written + * directly. Otherwise, a null offset is written and a new forward reference + * is declared for this label. + * + * @param owner the code writer that calls this method. + * @param out the bytecode of the method. + * @param source the position of first byte of the bytecode instruction that + * contains this label. + * @param wideOffset <tt>true</tt> if the reference must be stored in 4 + * bytes, or <tt>false</tt> if it must be stored with 2 bytes. + * @throws IllegalArgumentException if this label has not been created by + * the given code writer. + */ + void put( + final MethodWriter owner, + final ByteVector out, + final int source, + final boolean wideOffset) + { + if ((status & RESOLVED) == 0) { + if (wideOffset) { + addReference(-1 - source, out.length); + out.putInt(-1); + } else { + addReference(source, out.length); + out.putShort(-1); + } + } else { + if (wideOffset) { + out.putInt(position - source); + } else { + out.putShort(position - source); + } + } + } + + /** + * Adds a forward reference to this label. This method must be called only + * for a true forward reference, i.e. only if this label is not resolved + * yet. For backward references, the offset of the reference can be, and + * must be, computed and stored directly. + * + * @param sourcePosition the position of the referencing instruction. This + * position will be used to compute the offset of this forward + * reference. + * @param referencePosition the position where the offset for this forward + * reference must be stored. + */ + private void addReference( + final int sourcePosition, + final int referencePosition) + { + if (srcAndRefPositions == null) { + srcAndRefPositions = new int[6]; + } + if (referenceCount >= srcAndRefPositions.length) { + int[] a = new int[srcAndRefPositions.length + 6]; + System.arraycopy(srcAndRefPositions, + 0, + a, + 0, + srcAndRefPositions.length); + srcAndRefPositions = a; + } + srcAndRefPositions[referenceCount++] = sourcePosition; + srcAndRefPositions[referenceCount++] = referencePosition; + } + + /** + * Resolves all forward references to this label. This method must be called + * when this label is added to the bytecode of the method, i.e. when its + * position becomes known. This method fills in the blanks that where left + * in the bytecode by each forward reference previously added to this label. + * + * @param owner the code writer that calls this method. + * @param position the position of this label in the bytecode. + * @param data the bytecode of the method. + * @return <tt>true</tt> if a blank that was left for this label was to + * small to store the offset. In such a case the corresponding jump + * instruction is replaced with a pseudo instruction (using unused + * opcodes) using an unsigned two bytes offset. These pseudo + * instructions will need to be replaced with true instructions with + * wider offsets (4 bytes instead of 2). This is done in + * {@link MethodWriter#resizeInstructions}. + * @throws IllegalArgumentException if this label has already been resolved, + * or if it has not been created by the given code writer. + */ + boolean resolve( + final MethodWriter owner, + final int position, + final byte[] data) + { + boolean needUpdate = false; + this.status |= RESOLVED; + this.position = position; + int i = 0; + while (i < referenceCount) { + int source = srcAndRefPositions[i++]; + int reference = srcAndRefPositions[i++]; + int offset; + if (source >= 0) { + offset = position - source; + if (offset < Short.MIN_VALUE || offset > Short.MAX_VALUE) { + /* + * changes the opcode of the jump instruction, in order to + * be able to find it later (see resizeInstructions in + * MethodWriter). These temporary opcodes are similar to + * jump instruction opcodes, except that the 2 bytes offset + * is unsigned (and can therefore represent values from 0 to + * 65535, which is sufficient since the size of a method is + * limited to 65535 bytes). + */ + int opcode = data[reference - 1] & 0xFF; + if (opcode <= Opcodes.JSR) { + // changes IFEQ ... JSR to opcodes 202 to 217 + data[reference - 1] = (byte) (opcode + 49); + } else { + // changes IFNULL and IFNONNULL to opcodes 218 and 219 + data[reference - 1] = (byte) (opcode + 20); + } + needUpdate = true; + } + data[reference++] = (byte) (offset >>> 8); + data[reference] = (byte) offset; + } else { + offset = position + source + 1; + data[reference++] = (byte) (offset >>> 24); + data[reference++] = (byte) (offset >>> 16); + data[reference++] = (byte) (offset >>> 8); + data[reference] = (byte) offset; + } + } + return needUpdate; + } + + /** + * Returns the first label of the series to which this label belongs. For an + * isolated label or for the first label in a series of successive labels, + * this method returns the label itself. For other labels it returns the + * first label of the series. + * + * @return the first label of the series to which this label belongs. + */ + Label getFirst() { + return !ClassReader.FRAMES || frame == null ? this : frame.owner; + } + + // ------------------------------------------------------------------------ + // Methods related to subroutines + // ------------------------------------------------------------------------ + + /** + * Returns true is this basic block belongs to the given subroutine. + * + * @param id a subroutine id. + * @return true is this basic block belongs to the given subroutine. + */ + boolean inSubroutine(final long id) { + if ((status & Label.VISITED) != 0) { + return (srcAndRefPositions[(int) (id >>> 32)] & (int) id) != 0; + } + return false; + } + + /** + * Returns true if this basic block and the given one belong to a common + * subroutine. + * + * @param block another basic block. + * @return true if this basic block and the given one belong to a common + * subroutine. + */ + boolean inSameSubroutine(final Label block) { + for (int i = 0; i < srcAndRefPositions.length; ++i) { + if ((srcAndRefPositions[i] & block.srcAndRefPositions[i]) != 0) { + return true; + } + } + return false; + } + + /** + * Marks this basic block as belonging to the given subroutine. + * + * @param id a subroutine id. + * @param nbSubroutines the total number of subroutines in the method. + */ + void addToSubroutine(final long id, final int nbSubroutines) { + if ((status & VISITED) == 0) { + status |= VISITED; + srcAndRefPositions = new int[(nbSubroutines - 1) / 32 + 1]; + } + srcAndRefPositions[(int) (id >>> 32)] |= (int) id; + } + + /** + * Finds the basic blocks that belong to a given subroutine, and marks these + * blocks as belonging to this subroutine. This recursive method follows the + * control flow graph to find all the blocks that are reachable from the + * current block WITHOUT following any JSR target. + * + * @param JSR a JSR block that jumps to this subroutine. If this JSR is not + * null it is added to the successor of the RET blocks found in the + * subroutine. + * @param id the id of this subroutine. + * @param nbSubroutines the total number of subroutines in the method. + */ + void visitSubroutine(final Label JSR, final long id, final int nbSubroutines) + { + if (JSR != null) { + if ((status & VISITED) != 0) { + return; + } + status |= VISITED; + // adds JSR to the successors of this block, if it is a RET block + if ((status & RET) != 0) { + if (!inSameSubroutine(JSR)) { + Edge e = new Edge(); + e.info = inputStackTop; + e.successor = JSR.successors.successor; + e.next = successors; + successors = e; + } + } + } else { + // if this block already belongs to subroutine 'id', returns + if (inSubroutine(id)) { + return; + } + // marks this block as belonging to subroutine 'id' + addToSubroutine(id, nbSubroutines); + } + // calls this method recursively on each successor, except JSR targets + Edge e = successors; + while (e != null) { + // if this block is a JSR block, then 'successors.next' leads + // to the JSR target (see {@link #visitJumpInsn}) and must therefore + // not be followed + if ((status & Label.JSR) == 0 || e != successors.next) { + e.successor.visitSubroutine(JSR, id, nbSubroutines); + } + e = e.next; + } + } + + // ------------------------------------------------------------------------ + // Overriden Object methods + // ------------------------------------------------------------------------ + + /** + * Returns a string representation of this label. + * + * @return a string representation of this label. + */ + public String toString() { + return "L" + System.identityHashCode(this); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/ws/org/objectweb/asm/MethodVisitor.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,425 @@ +/* + * Copyright 2005-2009 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2007 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.sun.xml.internal.ws.org.objectweb.asm; + +/** + * A visitor to visit a Java method. The methods of this interface must be + * called in the following order: [ <tt>visitAnnotationDefault</tt> ] ( + * <tt>visitAnnotation</tt> | <tt>visitParameterAnnotation</tt> | + * <tt>visitAttribute</tt> )* [ <tt>visitCode</tt> ( <tt>visitFrame</tt> | + * <tt>visit</tt><i>X</i>Insn</tt> | <tt>visitLabel</tt> | <tt>visitTryCatchBlock</tt> | + * <tt>visitLocalVariable</tt> | <tt>visitLineNumber</tt>)* <tt>visitMaxs</tt> ] + * <tt>visitEnd</tt>. In addition, the <tt>visit</tt><i>X</i>Insn</tt> + * and <tt>visitLabel</tt> methods must be called in the sequential order of + * the bytecode instructions of the visited code, <tt>visitTryCatchBlock</tt> + * must be called <i>before</i> the labels passed as arguments have been + * visited, and the <tt>visitLocalVariable</tt> and <tt>visitLineNumber</tt> + * methods must be called <i>after</i> the labels passed as arguments have been + * visited. + * + * @author Eric Bruneton + */ +public interface MethodVisitor { + + // ------------------------------------------------------------------------- + // Annotations and non standard attributes + // ------------------------------------------------------------------------- + + /** + * Visits the default value of this annotation interface method. + * + * @return a visitor to the visit the actual default value of this + * annotation interface method, or <tt>null</tt> if this visitor + * is not interested in visiting this default value. The 'name' + * parameters passed to the methods of this annotation visitor are + * ignored. Moreover, exacly one visit method must be called on this + * annotation visitor, followed by visitEnd. + */ + AnnotationVisitor visitAnnotationDefault(); + + /** + * Visits an annotation of this method. + * + * @param desc the class descriptor of the annotation class. + * @param visible <tt>true</tt> if the annotation is visible at runtime. + * @return a visitor to visit the annotation values, or <tt>null</tt> if + * this visitor is not interested in visiting this annotation. + */ + AnnotationVisitor visitAnnotation(String desc, boolean visible); + + /** + * Visits an annotation of a parameter this method. + * + * @param parameter the parameter index. + * @param desc the class descriptor of the annotation class. + * @param visible <tt>true</tt> if the annotation is visible at runtime. + * @return a visitor to visit the annotation values, or <tt>null</tt> if + * this visitor is not interested in visiting this annotation. + */ + AnnotationVisitor visitParameterAnnotation( + int parameter, + String desc, + boolean visible); + + /** + * Visits a non standard attribute of this method. + * + * @param attr an attribute. + */ + void visitAttribute(Attribute attr); + + /** + * Starts the visit of the method's code, if any (i.e. non abstract method). + */ + void visitCode(); + + /** + * Visits the current state of the local variables and operand stack + * elements. This method must(*) be called <i>just before</i> any + * instruction <b>i</b> that follows an unconditionnal branch instruction + * such as GOTO or THROW, that is the target of a jump instruction, or that + * starts an exception handler block. The visited types must describe the + * values of the local variables and of the operand stack elements <i>just + * before</i> <b>i</b> is executed. <br> <br> (*) this is mandatory only + * for classes whose version is greater than or equal to + * {@link Opcodes#V1_6 V1_6}. <br> <br> Packed frames are basically + * "deltas" from the state of the previous frame (very first frame is + * implicitly defined by the method's parameters and access flags): <ul> + * <li>{@link Opcodes#F_SAME} representing frame with exactly the same + * locals as the previous frame and with the empty stack.</li> <li>{@link Opcodes#F_SAME1} + * representing frame with exactly the same locals as the previous frame and + * with single value on the stack (<code>nStack</code> is 1 and + * <code>stack[0]</code> contains value for the type of the stack item).</li> + * <li>{@link Opcodes#F_APPEND} representing frame with current locals are + * the same as the locals in the previous frame, except that additional + * locals are defined (<code>nLocal</code> is 1, 2 or 3 and + * <code>local</code> elements contains values representing added types).</li> + * <li>{@link Opcodes#F_CHOP} representing frame with current locals are + * the same as the locals in the previous frame, except that the last 1-3 + * locals are absent and with the empty stack (<code>nLocals</code> is 1, + * 2 or 3). </li> <li>{@link Opcodes#F_FULL} representing complete frame + * data.</li> </li> </ul> + * + * @param type the type of this stack map frame. Must be + * {@link Opcodes#F_NEW} for expanded frames, or + * {@link Opcodes#F_FULL}, {@link Opcodes#F_APPEND}, + * {@link Opcodes#F_CHOP}, {@link Opcodes#F_SAME} or + * {@link Opcodes#F_APPEND}, {@link Opcodes#F_SAME1} for compressed + * frames. + * @param nLocal the number of local variables in the visited frame. + * @param local the local variable types in this frame. This array must not + * be modified. Primitive types are represented by + * {@link Opcodes#TOP}, {@link Opcodes#INTEGER}, + * {@link Opcodes#FLOAT}, {@link Opcodes#LONG}, + * {@link Opcodes#DOUBLE},{@link Opcodes#NULL} or + * {@link Opcodes#UNINITIALIZED_THIS} (long and double are + * represented by a single element). Reference types are represented + * by String objects (representing internal names), and uninitialized + * types by Label objects (this label designates the NEW instruction + * that created this uninitialized value). + * @param nStack the number of operand stack elements in the visited frame. + * @param stack the operand stack types in this frame. This array must not + * be modified. Its content has the same format as the "local" array. + */ + void visitFrame( + int type, + int nLocal, + Object[] local, + int nStack, + Object[] stack); + + // ------------------------------------------------------------------------- + // Normal instructions + // ------------------------------------------------------------------------- + + /** + * Visits a zero operand instruction. + * + * @param opcode the opcode of the instruction to be visited. This opcode is + * either NOP, ACONST_NULL, ICONST_M1, ICONST_0, ICONST_1, ICONST_2, + * ICONST_3, ICONST_4, ICONST_5, LCONST_0, LCONST_1, FCONST_0, + * FCONST_1, FCONST_2, DCONST_0, DCONST_1, IALOAD, LALOAD, FALOAD, + * DALOAD, AALOAD, BALOAD, CALOAD, SALOAD, IASTORE, LASTORE, FASTORE, + * DASTORE, AASTORE, BASTORE, CASTORE, SASTORE, POP, POP2, DUP, + * DUP_X1, DUP_X2, DUP2, DUP2_X1, DUP2_X2, SWAP, IADD, LADD, FADD, + * DADD, ISUB, LSUB, FSUB, DSUB, IMUL, LMUL, FMUL, DMUL, IDIV, LDIV, + * FDIV, DDIV, IREM, LREM, FREM, DREM, INEG, LNEG, FNEG, DNEG, ISHL, + * LSHL, ISHR, LSHR, IUSHR, LUSHR, IAND, LAND, IOR, LOR, IXOR, LXOR, + * I2L, I2F, I2D, L2I, L2F, L2D, F2I, F2L, F2D, D2I, D2L, D2F, I2B, + * I2C, I2S, LCMP, FCMPL, FCMPG, DCMPL, DCMPG, IRETURN, LRETURN, + * FRETURN, DRETURN, ARETURN, RETURN, ARRAYLENGTH, ATHROW, + * MONITORENTER, or MONITOREXIT. + */ + void visitInsn(int opcode); + + /** + * Visits an instruction with a single int operand. + * + * @param opcode the opcode of the instruction to be visited. This opcode is + * either BIPUSH, SIPUSH or NEWARRAY. + * @param operand the operand of the instruction to be visited.<br> When + * opcode is BIPUSH, operand value should be between Byte.MIN_VALUE + * and Byte.MAX_VALUE.<br> When opcode is SIPUSH, operand value + * should be between Short.MIN_VALUE and Short.MAX_VALUE.<br> When + * opcode is NEWARRAY, operand value should be one of + * {@link Opcodes#T_BOOLEAN}, {@link Opcodes#T_CHAR}, + * {@link Opcodes#T_FLOAT}, {@link Opcodes#T_DOUBLE}, + * {@link Opcodes#T_BYTE}, {@link Opcodes#T_SHORT}, + * {@link Opcodes#T_INT} or {@link Opcodes#T_LONG}. + */ + void visitIntInsn(int opcode, int operand); + + /** + * Visits a local variable instruction. A local variable instruction is an + * instruction that loads or stores the value of a local variable. + * + * @param opcode the opcode of the local variable instruction to be visited. + * This opcode is either ILOAD, LLOAD, FLOAD, DLOAD, ALOAD, ISTORE, + * LSTORE, FSTORE, DSTORE, ASTORE or RET. + * @param var the operand of the instruction to be visited. This operand is + * the index of a local variable. + */ + void visitVarInsn(int opcode, int var); + + /** + * Visits a type instruction. A type instruction is an instruction that + * takes the internal name of a class as parameter. + * + * @param opcode the opcode of the type instruction to be visited. This + * opcode is either NEW, ANEWARRAY, CHECKCAST or INSTANCEOF. + * @param type the operand of the instruction to be visited. This operand + * must be the internal name of an object or array class (see {@link + * Type#getInternalName() getInternalName}). + */ + void visitTypeInsn(int opcode, String type); + + /** + * Visits a field instruction. A field instruction is an instruction that + * loads or stores the value of a field of an object. + * + * @param opcode the opcode of the type instruction to be visited. This + * opcode is either GETSTATIC, PUTSTATIC, GETFIELD or PUTFIELD. + * @param owner the internal name of the field's owner class (see {@link + * Type#getInternalName() getInternalName}). + * @param name the field's name. + * @param desc the field's descriptor (see {@link Type Type}). + */ + void visitFieldInsn(int opcode, String owner, String name, String desc); + + /** + * Visits a method instruction. A method instruction is an instruction that + * invokes a method. + * + * @param opcode the opcode of the type instruction to be visited. This + * opcode is either INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or + * INVOKEINTERFACE. + * @param owner the internal name of the method's owner class (see {@link + * Type#getInternalName() getInternalName}). + * @param name the method's name. + * @param desc the method's descriptor (see {@link Type Type}). + */ + void visitMethodInsn(int opcode, String owner, String name, String desc); + + /** + * Visits a jump instruction. A jump instruction is an instruction that may + * jump to another instruction. + * + * @param opcode the opcode of the type instruction to be visited. This + * opcode is either IFEQ, IFNE, IFLT, IFGE, IFGT, IFLE, IF_ICMPEQ, + * IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, IF_ACMPEQ, + * IF_ACMPNE, GOTO, JSR, IFNULL or IFNONNULL. + * @param label the operand of the instruction to be visited. This operand + * is a label that designates the instruction to which the jump + * instruction may jump. + */ + void visitJumpInsn(int opcode, Label label); + + /** + * Visits a label. A label designates the instruction that will be visited + * just after it. + * + * @param label a {@link Label Label} object. + */ + void visitLabel(Label label); + + // ------------------------------------------------------------------------- + // Special instructions + // ------------------------------------------------------------------------- + + /** + * Visits a LDC instruction. + * + * @param cst the constant to be loaded on the stack. This parameter must be + * a non null {@link Integer}, a {@link Float}, a {@link Long}, a + * {@link Double} a {@link String} (or a {@link Type} for + * <tt>.class</tt> constants, for classes whose version is 49.0 or + * more). + */ + void visitLdcInsn(Object cst); + + /** + * Visits an IINC instruction. + * + * @param var index of the local variable to be incremented. + * @param increment amount to increment the local variable by. + */ + void visitIincInsn(int var, int increment); + + /** + * Visits a TABLESWITCH instruction. + * + * @param min the minimum key value. + * @param max the maximum key value. + * @param dflt beginning of the default handler block. + * @param labels beginnings of the handler blocks. <tt>labels[i]</tt> is + * the beginning of the handler block for the <tt>min + i</tt> key. + */ + void visitTableSwitchInsn(int min, int max, Label dflt, Label[] labels); + + /** + * Visits a LOOKUPSWITCH instruction. + * + * @param dflt beginning of the default handler block. + * @param keys the values of the keys. + * @param labels beginnings of the handler blocks. <tt>labels[i]</tt> is + * the beginning of the handler block for the <tt>keys[i]</tt> key. + */ + void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels); + + /** + * Visits a MULTIANEWARRAY instruction. + * + * @param desc an array type descriptor (see {@link Type Type}). + * @param dims number of dimensions of the array to allocate. + */ + void visitMultiANewArrayInsn(String desc, int dims); + + // ------------------------------------------------------------------------- + // Exceptions table entries, debug information, max stack and max locals + // ------------------------------------------------------------------------- + + /** + * Visits a try catch block. + * + * @param start beginning of the exception handler's scope (inclusive). + * @param end end of the exception handler's scope (exclusive). + * @param handler beginning of the exception handler's code. + * @param type internal name of the type of exceptions handled by the + * handler, or <tt>null</tt> to catch any exceptions (for "finally" + * blocks). + * @throws IllegalArgumentException if one of the labels has already been + * visited by this visitor (by the {@link #visitLabel visitLabel} + * method). + */ + void visitTryCatchBlock(Label start, Label end, Label handler, String type); + + /** + * Visits a local variable declaration. + * + * @param name the name of a local variable. + * @param desc the type descriptor of this local variable. + * @param signature the type signature of this local variable. May be + * <tt>null</tt> if the local variable type does not use generic + * types. + * @param start the first instruction corresponding to the scope of this + * local variable (inclusive). + * @param end the last instruction corresponding to the scope of this local + * variable (exclusive). + * @param index the local variable's index. + * @throws IllegalArgumentException if one of the labels has not already + * been visited by this visitor (by the + * {@link #visitLabel visitLabel} method). + */ + void visitLocalVariable( + String name, + String desc, + String signature, + Label start, + Label end, + int index); + + /** + * Visits a line number declaration. + * + * @param line a line number. This number refers to the source file from + * which the class was compiled. + * @param start the first instruction corresponding to this line number. + * @throws IllegalArgumentException if <tt>start</tt> has not already been + * visited by this visitor (by the {@link #visitLabel visitLabel} + * method). + */ + void visitLineNumber(int line, Label start); + + /** + * Visits the maximum stack size and the maximum number of local variables + * of the method. + * + * @param maxStack maximum stack size of the method. + * @param maxLocals maximum number of local variables for the method. + */ + void visitMaxs(int maxStack, int maxLocals); + + /** + * Visits the end of the method. This method, which is the last one to be + * called, is used to inform the visitor that all the annotations and + * attributes of the method have been visited. + */ + void visitEnd(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/ws/org/objectweb/asm/MethodWriter.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,2631 @@ +/* + * Copyright 2005-2009 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2007 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.sun.xml.internal.ws.org.objectweb.asm; + +/** + * A {@link MethodVisitor} that generates methods in bytecode form. Each visit + * method of this class appends the bytecode corresponding to the visited + * instruction to a byte vector, in the order these methods are called. + * + * @author Eric Bruneton + * @author Eugene Kuleshov + */ +class MethodWriter implements MethodVisitor { + + /** + * Pseudo access flag used to denote constructors. + */ + static final int ACC_CONSTRUCTOR = 262144; + + /** + * Frame has exactly the same locals as the previous stack map frame and + * number of stack items is zero. + */ + static final int SAME_FRAME = 0; // to 63 (0-3f) + + /** + * Frame has exactly the same locals as the previous stack map frame and + * number of stack items is 1 + */ + static final int SAME_LOCALS_1_STACK_ITEM_FRAME = 64; // to 127 (40-7f) + + /** + * Reserved for future use + */ + static final int RESERVED = 128; + + /** + * Frame has exactly the same locals as the previous stack map frame and + * number of stack items is 1. Offset is bigger then 63; + */ + static final int SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED = 247; // f7 + + /** + * Frame where current locals are the same as the locals in the previous + * frame, except that the k last locals are absent. The value of k is given + * by the formula 251-frame_type. + */ + static final int CHOP_FRAME = 248; // to 250 (f8-fA) + + /** + * Frame has exactly the same locals as the previous stack map frame and + * number of stack items is zero. Offset is bigger then 63; + */ + static final int SAME_FRAME_EXTENDED = 251; // fb + + /** + * Frame where current locals are the same as the locals in the previous + * frame, except that k additional locals are defined. The value of k is + * given by the formula frame_type-251. + */ + static final int APPEND_FRAME = 252; // to 254 // fc-fe + + /** + * Full frame + */ + static final int FULL_FRAME = 255; // ff + + /** + * Indicates that the stack map frames must be recomputed from scratch. In + * this case the maximum stack size and number of local variables is also + * recomputed from scratch. + * + * @see #compute + */ + private static final int FRAMES = 0; + + /** + * Indicates that the maximum stack size and number of local variables must + * be automatically computed. + * + * @see #compute + */ + private static final int MAXS = 1; + + /** + * Indicates that nothing must be automatically computed. + * + * @see #compute + */ + private static final int NOTHING = 2; + + /** + * Next method writer (see {@link ClassWriter#firstMethod firstMethod}). + */ + MethodWriter next; + + /** + * The class writer to which this method must be added. + */ + final ClassWriter cw; + + /** + * Access flags of this method. + */ + private int access; + + /** + * The index of the constant pool item that contains the name of this + * method. + */ + private final int name; + + /** + * The index of the constant pool item that contains the descriptor of this + * method. + */ + private final int desc; + + /** + * The descriptor of this method. + */ + private final String descriptor; + + /** + * The signature of this method. + */ + String signature; + + /** + * If not zero, indicates that the code of this method must be copied from + * the ClassReader associated to this writer in <code>cw.cr</code>. More + * precisely, this field gives the index of the first byte to copied from + * <code>cw.cr.b</code>. + */ + int classReaderOffset; + + /** + * If not zero, indicates that the code of this method must be copied from + * the ClassReader associated to this writer in <code>cw.cr</code>. More + * precisely, this field gives the number of bytes to copied from + * <code>cw.cr.b</code>. + */ + int classReaderLength; + + /** + * Number of exceptions that can be thrown by this method. + */ + int exceptionCount; + + /** + * The exceptions that can be thrown by this method. More precisely, this + * array contains the indexes of the constant pool items that contain the + * internal names of these exception classes. + */ + int[] exceptions; + + /** + * The annotation default attribute of this method. May be <tt>null</tt>. + */ + private ByteVector annd; + + /** + * The runtime visible annotations of this method. May be <tt>null</tt>. + */ + private AnnotationWriter anns; + + /** + * The runtime invisible annotations of this method. May be <tt>null</tt>. + */ + private AnnotationWriter ianns; + + /** + * The runtime visible parameter annotations of this method. May be + * <tt>null</tt>. + */ + private AnnotationWriter[] panns; + + /** + * The runtime invisible parameter annotations of this method. May be + * <tt>null</tt>. + */ + private AnnotationWriter[] ipanns; + + /** + * The number of synthetic parameters of this method. + */ + private int synthetics; + + /** + * The non standard attributes of the method. + */ + private Attribute attrs; + + /** + * The bytecode of this method. + */ + private ByteVector code = new ByteVector(); + + /** + * Maximum stack size of this method. + */ + private int maxStack; + + /** + * Maximum number of local variables for this method. + */ + private int maxLocals; + + /** + * Number of stack map frames in the StackMapTable attribute. + */ + private int frameCount; + + /** + * The StackMapTable attribute. + */ + private ByteVector stackMap; + + /** + * The offset of the last frame that was written in the StackMapTable + * attribute. + */ + private int previousFrameOffset; + + /** + * The last frame that was written in the StackMapTable attribute. + * + * @see #frame + */ + private int[] previousFrame; + + /** + * Index of the next element to be added in {@link #frame}. + */ + private int frameIndex; + + /** + * The current stack map frame. The first element contains the offset of the + * instruction to which the frame corresponds, the second element is the + * number of locals and the third one is the number of stack elements. The + * local variables start at index 3 and are followed by the operand stack + * values. In summary frame[0] = offset, frame[1] = nLocal, frame[2] = + * nStack, frame[3] = nLocal. All types are encoded as integers, with the + * same format as the one used in {@link Label}, but limited to BASE types. + */ + private int[] frame; + + /** + * Number of elements in the exception handler list. + */ + private int handlerCount; + + /** + * The first element in the exception handler list. + */ + private Handler firstHandler; + + /** + * The last element in the exception handler list. + */ + private Handler lastHandler; + + /** + * Number of entries in the LocalVariableTable attribute. + */ + private int localVarCount; + + /** + * The LocalVariableTable attribute. + */ + private ByteVector localVar; + + /** + * Number of entries in the LocalVariableTypeTable attribute. + */ + private int localVarTypeCount; + + /** + * The LocalVariableTypeTable attribute. + */ + private ByteVector localVarType; + + /** + * Number of entries in the LineNumberTable attribute. + */ + private int lineNumberCount; + + /** + * The LineNumberTable attribute. + */ + private ByteVector lineNumber; + + /** + * The non standard attributes of the method's code. + */ + private Attribute cattrs; + + /** + * Indicates if some jump instructions are too small and need to be resized. + */ + private boolean resize; + + /** + * The number of subroutines in this method. + */ + private int subroutines; + + // ------------------------------------------------------------------------ + + /* + * Fields for the control flow graph analysis algorithm (used to compute the + * maximum stack size). A control flow graph contains one node per "basic + * block", and one edge per "jump" from one basic block to another. Each + * node (i.e., each basic block) is represented by the Label object that + * corresponds to the first instruction of this basic block. Each node also + * stores the list of its successors in the graph, as a linked list of Edge + * objects. + */ + + /** + * Indicates what must be automatically computed. + * + * @see #FRAMES + * @see #MAXS + * @see #NOTHING + */ + private final int compute; + + /** + * A list of labels. This list is the list of basic blocks in the method, + * i.e. a list of Label objects linked to each other by their + * {@link Label#successor} field, in the order they are visited by + * {@link MethodVisitor#visitLabel}, and starting with the first basic block. + */ + private Label labels; + + /** + * The previous basic block. + */ + private Label previousBlock; + + /** + * The current basic block. + */ + private Label currentBlock; + + /** + * The (relative) stack size after the last visited instruction. This size + * is relative to the beginning of the current basic block, i.e., the true + * stack size after the last visited instruction is equal to the + * {@link Label#inputStackTop beginStackSize} of the current basic block + * plus <tt>stackSize</tt>. + */ + private int stackSize; + + /** + * The (relative) maximum stack size after the last visited instruction. + * This size is relative to the beginning of the current basic block, i.e., + * the true maximum stack size after the last visited instruction is equal + * to the {@link Label#inputStackTop beginStackSize} of the current basic + * block plus <tt>stackSize</tt>. + */ + private int maxStackSize; + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + + /** + * Constructs a new {@link MethodWriter}. + * + * @param cw the class writer in which the method must be added. + * @param access the method's access flags (see {@link Opcodes}). + * @param name the method's name. + * @param desc the method's descriptor (see {@link Type}). + * @param signature the method's signature. May be <tt>null</tt>. + * @param exceptions the internal names of the method's exceptions. May be + * <tt>null</tt>. + * @param computeMaxs <tt>true</tt> if the maximum stack size and number + * of local variables must be automatically computed. + * @param computeFrames <tt>true</tt> if the stack map tables must be + * recomputed from scratch. + */ + MethodWriter( + final ClassWriter cw, + final int access, + final String name, + final String desc, + final String signature, + final String[] exceptions, + final boolean computeMaxs, + final boolean computeFrames) + { + if (cw.firstMethod == null) { + cw.firstMethod = this; + } else { + cw.lastMethod.next = this; + } + cw.lastMethod = this; + this.cw = cw; + this.access = access; + this.name = cw.newUTF8(name); + this.desc = cw.newUTF8(desc); + this.descriptor = desc; + if (ClassReader.SIGNATURES) { + this.signature = signature; + } + if (exceptions != null && exceptions.length > 0) { + exceptionCount = exceptions.length; + this.exceptions = new int[exceptionCount]; + for (int i = 0; i < exceptionCount; ++i) { + this.exceptions[i] = cw.newClass(exceptions[i]); + } + } + this.compute = computeFrames ? FRAMES : (computeMaxs ? MAXS : NOTHING); + if (computeMaxs || computeFrames) { + if (computeFrames && "<init>".equals(name)) { + this.access |= ACC_CONSTRUCTOR; + } + // updates maxLocals + int size = getArgumentsAndReturnSizes(descriptor) >> 2; + if ((access & Opcodes.ACC_STATIC) != 0) { + --size; + } + maxLocals = size; + // creates and visits the label for the first basic block + labels = new Label(); + labels.status |= Label.PUSHED; + visitLabel(labels); + } + } + + // ------------------------------------------------------------------------ + // Implementation of the MethodVisitor interface + // ------------------------------------------------------------------------ + + public AnnotationVisitor visitAnnotationDefault() { + if (!ClassReader.ANNOTATIONS) { + return null; + } + annd = new ByteVector(); + return new AnnotationWriter(cw, false, annd, null, 0); + } + + public AnnotationVisitor visitAnnotation( + final String desc, + final boolean visible) + { + if (!ClassReader.ANNOTATIONS) { + return null; + } + ByteVector bv = new ByteVector(); + // write type, and reserve space for values count + bv.putShort(cw.newUTF8(desc)).putShort(0); + AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv, 2); + if (visible) { + aw.next = anns; + anns = aw; + } else { + aw.next = ianns; + ianns = aw; + } + return aw; + } + + public AnnotationVisitor visitParameterAnnotation( + final int parameter, + final String desc, + final boolean visible) + { + if (!ClassReader.ANNOTATIONS) { + return null; + } + ByteVector bv = new ByteVector(); + if ("Ljava/lang/Synthetic;".equals(desc)) { + // workaround for a bug in javac with synthetic parameters + // see ClassReader.readParameterAnnotations + synthetics = Math.max(synthetics, parameter + 1); + return new AnnotationWriter(cw, false, bv, null, 0); + } + // write type, and reserve space for values count + bv.putShort(cw.newUTF8(desc)).putShort(0); + AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv, 2); + if (visible) { + if (panns == null) { + panns = new AnnotationWriter[Type.getArgumentTypes(descriptor).length]; + } + aw.next = panns[parameter]; + panns[parameter] = aw; + } else { + if (ipanns == null) { + ipanns = new AnnotationWriter[Type.getArgumentTypes(descriptor).length]; + } + aw.next = ipanns[parameter]; + ipanns[parameter] = aw; + } + return aw; + } + + public void visitAttribute(final Attribute attr) { + if (attr.isCodeAttribute()) { + attr.next = cattrs; + cattrs = attr; + } else { + attr.next = attrs; + attrs = attr; + } + } + + public void visitCode() { + } + + public void visitFrame( + final int type, + final int nLocal, + final Object[] local, + final int nStack, + final Object[] stack) + { + if (!ClassReader.FRAMES || compute == FRAMES) { + return; + } + + if (type == Opcodes.F_NEW) { + startFrame(code.length, nLocal, nStack); + for (int i = 0; i < nLocal; ++i) { + if (local[i] instanceof String) { + frame[frameIndex++] = Frame.OBJECT + | cw.addType((String) local[i]); + } else if (local[i] instanceof Integer) { + frame[frameIndex++] = ((Integer) local[i]).intValue(); + } else { + frame[frameIndex++] = Frame.UNINITIALIZED + | cw.addUninitializedType("", + ((Label) local[i]).position); + } + } + for (int i = 0; i < nStack; ++i) { + if (stack[i] instanceof String) { + frame[frameIndex++] = Frame.OBJECT + | cw.addType((String) stack[i]); + } else if (stack[i] instanceof Integer) { + frame[frameIndex++] = ((Integer) stack[i]).intValue(); + } else { + frame[frameIndex++] = Frame.UNINITIALIZED + | cw.addUninitializedType("", + ((Label) stack[i]).position); + } + } + endFrame(); + } else { + int delta; + if (stackMap == null) { + stackMap = new ByteVector(); + delta = code.length; + } else { + delta = code.length - previousFrameOffset - 1; + } + + switch (type) { + case Opcodes.F_FULL: + stackMap.putByte(FULL_FRAME) + .putShort(delta) + .putShort(nLocal); + for (int i = 0; i < nLocal; ++i) { + writeFrameType(local[i]); + } + stackMap.putShort(nStack); + for (int i = 0; i < nStack; ++i) { + writeFrameType(stack[i]); + } + break; + case Opcodes.F_APPEND: + stackMap.putByte(SAME_FRAME_EXTENDED + nLocal) + .putShort(delta); + for (int i = 0; i < nLocal; ++i) { + writeFrameType(local[i]); + } + break; + case Opcodes.F_CHOP: + stackMap.putByte(SAME_FRAME_EXTENDED - nLocal) + .putShort(delta); + break; + case Opcodes.F_SAME: + if (delta < 64) { + stackMap.putByte(delta); + } else { + stackMap.putByte(SAME_FRAME_EXTENDED).putShort(delta); + } + break; + case Opcodes.F_SAME1: + if (delta < 64) { + stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME + delta); + } else { + stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED) + .putShort(delta); + } + writeFrameType(stack[0]); + break; + } + + previousFrameOffset = code.length; + ++frameCount; + } + } + + public void visitInsn(final int opcode) { + // adds the instruction to the bytecode of the method + code.putByte(opcode); + // update currentBlock + // Label currentBlock = this.currentBlock; + if (currentBlock != null) { + if (compute == FRAMES) { + currentBlock.frame.execute(opcode, 0, null, null); + } else { + // updates current and max stack sizes + int size = stackSize + Frame.SIZE[opcode]; + if (size > maxStackSize) { + maxStackSize = size; + } + stackSize = size; + } + // if opcode == ATHROW or xRETURN, ends current block (no successor) + if ((opcode >= Opcodes.IRETURN && opcode <= Opcodes.RETURN) + || opcode == Opcodes.ATHROW) + { + noSuccessor(); + } + } + } + + public void visitIntInsn(final int opcode, final int operand) { + // Label currentBlock = this.currentBlock; + if (currentBlock != null) { + if (compute == FRAMES) { + currentBlock.frame.execute(opcode, operand, null, null); + } else if (opcode != Opcodes.NEWARRAY) { + // updates current and max stack sizes only for NEWARRAY + // (stack size variation = 0 for BIPUSH or SIPUSH) + int size = stackSize + 1; + if (size > maxStackSize) { + maxStackSize = size; + } + stackSize = size; + } + } + // adds the instruction to the bytecode of the method + if (opcode == Opcodes.SIPUSH) { + code.put12(opcode, operand); + } else { // BIPUSH or NEWARRAY + code.put11(opcode, operand); + } + } + + public void visitVarInsn(final int opcode, final int var) { + // Label currentBlock = this.currentBlock; + if (currentBlock != null) { + if (compute == FRAMES) { + currentBlock.frame.execute(opcode, var, null, null); + } else { + // updates current and max stack sizes + if (opcode == Opcodes.RET) { + // no stack change, but end of current block (no successor) + currentBlock.status |= Label.RET; + // save 'stackSize' here for future use + // (see {@link #findSubroutineSuccessors}) + currentBlock.inputStackTop = stackSize; + noSuccessor(); + } else { // xLOAD or xSTORE + int size = stackSize + Frame.SIZE[opcode]; + if (size > maxStackSize) { + maxStackSize = size; + } + stackSize = size; + } + } + } + if (compute != NOTHING) { + // updates max locals + int n; + if (opcode == Opcodes.LLOAD || opcode == Opcodes.DLOAD + || opcode == Opcodes.LSTORE || opcode == Opcodes.DSTORE) + { + n = var + 2; + } else { + n = var + 1; + } + if (n > maxLocals) { + maxLocals = n; + } + } + // adds the instruction to the bytecode of the method + if (var < 4 && opcode != Opcodes.RET) { + int opt; + if (opcode < Opcodes.ISTORE) { + /* ILOAD_0 */ + opt = 26 + ((opcode - Opcodes.ILOAD) << 2) + var; + } else { + /* ISTORE_0 */ + opt = 59 + ((opcode - Opcodes.ISTORE) << 2) + var; + } + code.putByte(opt); + } else if (var >= 256) { + code.putByte(196 /* WIDE */).put12(opcode, var); + } else { + code.put11(opcode, var); + } + if (opcode >= Opcodes.ISTORE && compute == FRAMES && handlerCount > 0) { + visitLabel(new Label()); + } + } + + public void visitTypeInsn(final int opcode, final String type) { + Item i = cw.newClassItem(type); + // Label currentBlock = this.currentBlock; + if (currentBlock != null) { + if (compute == FRAMES) { + currentBlock.frame.execute(opcode, code.length, cw, i); + } else if (opcode == Opcodes.NEW) { + // updates current and max stack sizes only if opcode == NEW + // (no stack change for ANEWARRAY, CHECKCAST, INSTANCEOF) + int size = stackSize + 1; + if (size > maxStackSize) { + maxStackSize = size; + } + stackSize = size; + } + } + // adds the instruction to the bytecode of the method + code.put12(opcode, i.index); + } + + public void visitFieldInsn( + final int opcode, + final String owner, + final String name, + final String desc) + { + Item i = cw.newFieldItem(owner, name, desc); + // Label currentBlock = this.currentBlock; + if (currentBlock != null) { + if (compute == FRAMES) { + currentBlock.frame.execute(opcode, 0, cw, i); + } else { + int size; + // computes the stack size variation + char c = desc.charAt(0); + switch (opcode) { + case Opcodes.GETSTATIC: + size = stackSize + (c == 'D' || c == 'J' ? 2 : 1); + break; + case Opcodes.PUTSTATIC: + size = stackSize + (c == 'D' || c == 'J' ? -2 : -1); + break; + case Opcodes.GETFIELD: + size = stackSize + (c == 'D' || c == 'J' ? 1 : 0); + break; + // case Constants.PUTFIELD: + default: + size = stackSize + (c == 'D' || c == 'J' ? -3 : -2); + break; + } + // updates current and max stack sizes + if (size > maxStackSize) { + maxStackSize = size; + } + stackSize = size; + } + } + // adds the instruction to the bytecode of the method + code.put12(opcode, i.index); + } + + public void visitMethodInsn( + final int opcode, + final String owner, + final String name, + final String desc) + { + boolean itf = opcode == Opcodes.INVOKEINTERFACE; + Item i = cw.newMethodItem(owner, name, desc, itf); + int argSize = i.intVal; + // Label currentBlock = this.currentBlock; + if (currentBlock != null) { + if (compute == FRAMES) { + currentBlock.frame.execute(opcode, 0, cw, i); + } else { + /* + * computes the stack size variation. In order not to recompute + * several times this variation for the same Item, we use the + * intVal field of this item to store this variation, once it + * has been computed. More precisely this intVal field stores + * the sizes of the arguments and of the return value + * corresponding to desc. + */ + if (argSize == 0) { + // the above sizes have not been computed yet, + // so we compute them... + argSize = getArgumentsAndReturnSizes(desc); + // ... and we save them in order + // not to recompute them in the future + i.intVal = argSize; + } + int size; + if (opcode == Opcodes.INVOKESTATIC) { + size = stackSize - (argSize >> 2) + (argSize & 0x03) + 1; + } else { + size = stackSize - (argSize >> 2) + (argSize & 0x03); + } + // updates current and max stack sizes + if (size > maxStackSize) { + maxStackSize = size; + } + stackSize = size; + } + } + // adds the instruction to the bytecode of the method + if (itf) { + if (argSize == 0) { + argSize = getArgumentsAndReturnSizes(desc); + i.intVal = argSize; + } + code.put12(Opcodes.INVOKEINTERFACE, i.index).put11(argSize >> 2, 0); + } else { + code.put12(opcode, i.index); + } + } + + public void visitJumpInsn(final int opcode, final Label label) { + Label nextInsn = null; + // Label currentBlock = this.currentBlock; + if (currentBlock != null) { + if (compute == FRAMES) { + currentBlock.frame.execute(opcode, 0, null, null); + // 'label' is the target of a jump instruction + label.getFirst().status |= Label.TARGET; + // adds 'label' as a successor of this basic block + addSuccessor(Edge.NORMAL, label); + if (opcode != Opcodes.GOTO) { + // creates a Label for the next basic block + nextInsn = new Label(); + } + } else { + if (opcode == Opcodes.JSR) { + if ((label.status & Label.SUBROUTINE) == 0) { + label.status |= Label.SUBROUTINE; + ++subroutines; + } + currentBlock.status |= Label.JSR; + addSuccessor(stackSize + 1, label); + // creates a Label for the next basic block + nextInsn = new Label(); + /* + * note that, by construction in this method, a JSR block + * has at least two successors in the control flow graph: + * the first one leads the next instruction after the JSR, + * while the second one leads to the JSR target. + */ + } else { + // updates current stack size (max stack size unchanged + // because stack size variation always negative in this + // case) + stackSize += Frame.SIZE[opcode]; + addSuccessor(stackSize, label); + } + } + } + // adds the instruction to the bytecode of the method + if ((label.status & Label.RESOLVED) != 0 + && label.position - code.length < Short.MIN_VALUE) + { + /* + * case of a backward jump with an offset < -32768. In this case we + * automatically replace GOTO with GOTO_W, JSR with JSR_W and IFxxx + * <l> with IFNOTxxx <l'> GOTO_W <l>, where IFNOTxxx is the + * "opposite" opcode of IFxxx (i.e., IFNE for IFEQ) and where <l'> + * designates the instruction just after the GOTO_W. + */ + if (opcode == Opcodes.GOTO) { + code.putByte(200); // GOTO_W + } else if (opcode == Opcodes.JSR) { + code.putByte(201); // JSR_W + } else { + // if the IF instruction is transformed into IFNOT GOTO_W the + // next instruction becomes the target of the IFNOT instruction + if (nextInsn != null) { + nextInsn.status |= Label.TARGET; + } + code.putByte(opcode <= 166 + ? ((opcode + 1) ^ 1) - 1 + : opcode ^ 1); + code.putShort(8); // jump offset + code.putByte(200); // GOTO_W + } + label.put(this, code, code.length - 1, true); + } else { + /* + * case of a backward jump with an offset >= -32768, or of a forward + * jump with, of course, an unknown offset. In these cases we store + * the offset in 2 bytes (which will be increased in + * resizeInstructions, if needed). + */ + code.putByte(opcode); + label.put(this, code, code.length - 1, false); + } + if (currentBlock != null) { + if (nextInsn != null) { + // if the jump instruction is not a GOTO, the next instruction + // is also a successor of this instruction. Calling visitLabel + // adds the label of this next instruction as a successor of the + // current block, and starts a new basic block + visitLabel(nextInsn); + } + if (opcode == Opcodes.GOTO) { + noSuccessor(); + } + } + } + + public void visitLabel(final Label label) { + // resolves previous forward references to label, if any + resize |= label.resolve(this, code.length, code.data); + // updates currentBlock + if ((label.status & Label.DEBUG) != 0) { + return; + } + if (compute == FRAMES) { + if (currentBlock != null) { + if (label.position == currentBlock.position) { + // successive labels, do not start a new basic block + currentBlock.status |= (label.status & Label.TARGET); + label.frame = currentBlock.frame; + return; + } + // ends current block (with one new successor) + addSuccessor(Edge.NORMAL, label); + } + // begins a new current block + currentBlock = label; + if (label.frame == null) { + label.frame = new Frame(); + label.frame.owner = label; + } + // updates the basic block list + if (previousBlock != null) { + if (label.position == previousBlock.position) { + previousBlock.status |= (label.status & Label.TARGET); + label.frame = previousBlock.frame; + currentBlock = previousBlock; + return; + } + previousBlock.successor = label; + } + previousBlock = label; + } else if (compute == MAXS) { + if (currentBlock != null) { + // ends current block (with one new successor) + currentBlock.outputStackMax = maxStackSize; + addSuccessor(stackSize, label); + } + // begins a new current block + currentBlock = label; + // resets the relative current and max stack sizes + stackSize = 0; + maxStackSize = 0; + // updates the basic block list + if (previousBlock != null) { + previousBlock.successor = label; + } + previousBlock = label; + } + } + + public void visitLdcInsn(final Object cst) { + Item i = cw.newConstItem(cst); + // Label currentBlock = this.currentBlock; + if (currentBlock != null) { + if (compute == FRAMES) { + currentBlock.frame.execute(Opcodes.LDC, 0, cw, i); + } else { + int size; + // computes the stack size variation + if (i.type == ClassWriter.LONG || i.type == ClassWriter.DOUBLE) + { + size = stackSize + 2; + } else { + size = stackSize + 1; + } + // updates current and max stack sizes + if (size > maxStackSize) { + maxStackSize = size; + } + stackSize = size; + } + } + // adds the instruction to the bytecode of the method + int index = i.index; + if (i.type == ClassWriter.LONG || i.type == ClassWriter.DOUBLE) { + code.put12(20 /* LDC2_W */, index); + } else if (index >= 256) { + code.put12(19 /* LDC_W */, index); + } else { + code.put11(Opcodes.LDC, index); + } + } + + public void visitIincInsn(final int var, final int increment) { + if (currentBlock != null) { + if (compute == FRAMES) { + currentBlock.frame.execute(Opcodes.IINC, var, null, null); + } + } + if (compute != NOTHING) { + // updates max locals + int n = var + 1; + if (n > maxLocals) { + maxLocals = n; + } + } + // adds the instruction to the bytecode of the method + if ((var > 255) || (increment > 127) || (increment < -128)) { + code.putByte(196 /* WIDE */) + .put12(Opcodes.IINC, var) + .putShort(increment); + } else { + code.putByte(Opcodes.IINC).put11(var, increment); + } + } + + public void visitTableSwitchInsn( + final int min, + final int max, + final Label dflt, + final Label[] labels) + { + // adds the instruction to the bytecode of the method + int source = code.length; + code.putByte(Opcodes.TABLESWITCH); + code.length += (4 - code.length % 4) % 4; + dflt.put(this, code, source, true); + code.putInt(min).putInt(max); + for (int i = 0; i < labels.length; ++i) { + labels[i].put(this, code, source, true); + } + // updates currentBlock + visitSwitchInsn(dflt, labels); + } + + public void visitLookupSwitchInsn( + final Label dflt, + final int[] keys, + final Label[] labels) + { + // adds the instruction to the bytecode of the method + int source = code.length; + code.putByte(Opcodes.LOOKUPSWITCH); + code.length += (4 - code.length % 4) % 4; + dflt.put(this, code, source, true); + code.putInt(labels.length); + for (int i = 0; i < labels.length; ++i) { + code.putInt(keys[i]); + labels[i].put(this, code, source, true); + } + // updates currentBlock + visitSwitchInsn(dflt, labels); + } + + private void visitSwitchInsn(final Label dflt, final Label[] labels) { + // Label currentBlock = this.currentBlock; + if (currentBlock != null) { + if (compute == FRAMES) { + currentBlock.frame.execute(Opcodes.LOOKUPSWITCH, 0, null, null); + // adds current block successors + addSuccessor(Edge.NORMAL, dflt); + dflt.getFirst().status |= Label.TARGET; + for (int i = 0; i < labels.length; ++i) { + addSuccessor(Edge.NORMAL, labels[i]); + labels[i].getFirst().status |= Label.TARGET; + } + } else { + // updates current stack size (max stack size unchanged) + --stackSize; + // adds current block successors + addSuccessor(stackSize, dflt); + for (int i = 0; i < labels.length; ++i) { + addSuccessor(stackSize, labels[i]); + } + } + // ends current block + noSuccessor(); + } + } + + public void visitMultiANewArrayInsn(final String desc, final int dims) { + Item i = cw.newClassItem(desc); + // Label currentBlock = this.currentBlock; + if (currentBlock != null) { + if (compute == FRAMES) { + currentBlock.frame.execute(Opcodes.MULTIANEWARRAY, dims, cw, i); + } else { + // updates current stack size (max stack size unchanged because + // stack size variation always negative or null) + stackSize += 1 - dims; + } + } + // adds the instruction to the bytecode of the method + code.put12(Opcodes.MULTIANEWARRAY, i.index).putByte(dims); + } + + public void visitTryCatchBlock( + final Label start, + final Label end, + final Label handler, + final String type) + { + ++handlerCount; + Handler h = new Handler(); + h.start = start; + h.end = end; + h.handler = handler; + h.desc = type; + h.type = type != null ? cw.newClass(type) : 0; + if (lastHandler == null) { + firstHandler = h; + } else { + lastHandler.next = h; + } + lastHandler = h; + } + + public void visitLocalVariable( + final String name, + final String desc, + final String signature, + final Label start, + final Label end, + final int index) + { + if (signature != null) { + if (localVarType == null) { + localVarType = new ByteVector(); + } + ++localVarTypeCount; + localVarType.putShort(start.position) + .putShort(end.position - start.position) + .putShort(cw.newUTF8(name)) + .putShort(cw.newUTF8(signature)) + .putShort(index); + } + if (localVar == null) { + localVar = new ByteVector(); + } + ++localVarCount; + localVar.putShort(start.position) + .putShort(end.position - start.position) + .putShort(cw.newUTF8(name)) + .putShort(cw.newUTF8(desc)) + .putShort(index); + if (compute != NOTHING) { + // updates max locals + char c = desc.charAt(0); + int n = index + (c == 'J' || c == 'D' ? 2 : 1); + if (n > maxLocals) { + maxLocals = n; + } + } + } + + public void visitLineNumber(final int line, final Label start) { + if (lineNumber == null) { + lineNumber = new ByteVector(); + } + ++lineNumberCount; + lineNumber.putShort(start.position); + lineNumber.putShort(line); + } + + public void visitMaxs(final int maxStack, final int maxLocals) { + if (ClassReader.FRAMES && compute == FRAMES) { + // completes the control flow graph with exception handler blocks + Handler handler = firstHandler; + while (handler != null) { + Label l = handler.start.getFirst(); + Label h = handler.handler.getFirst(); + Label e = handler.end.getFirst(); + // computes the kind of the edges to 'h' + String t = handler.desc == null + ? "java/lang/Throwable" + : handler.desc; + int kind = Frame.OBJECT | cw.addType(t); + // h is an exception handler + h.status |= Label.TARGET; + // adds 'h' as a successor of labels between 'start' and 'end' + while (l != e) { + // creates an edge to 'h' + Edge b = new Edge(); + b.info = kind; + b.successor = h; + // adds it to the successors of 'l' + b.next = l.successors; + l.successors = b; + // goes to the next label + l = l.successor; + } + handler = handler.next; + } + + // creates and visits the first (implicit) frame + Frame f = labels.frame; + Type[] args = Type.getArgumentTypes(descriptor); + f.initInputFrame(cw, access, args, this.maxLocals); + visitFrame(f); + + /* + * fix point algorithm: mark the first basic block as 'changed' + * (i.e. put it in the 'changed' list) and, while there are changed + * basic blocks, choose one, mark it as unchanged, and update its + * successors (which can be changed in the process). + */ + int max = 0; + Label changed = labels; + while (changed != null) { + // removes a basic block from the list of changed basic blocks + Label l = changed; + changed = changed.next; + l.next = null; + f = l.frame; + // a reacheable jump target must be stored in the stack map + if ((l.status & Label.TARGET) != 0) { + l.status |= Label.STORE; + } + // all visited labels are reacheable, by definition + l.status |= Label.REACHABLE; + // updates the (absolute) maximum stack size + int blockMax = f.inputStack.length + l.outputStackMax; + if (blockMax > max) { + max = blockMax; + } + // updates the successors of the current basic block + Edge e = l.successors; + while (e != null) { + Label n = e.successor.getFirst(); + boolean change = f.merge(cw, n.frame, e.info); + if (change && n.next == null) { + // if n has changed and is not already in the 'changed' + // list, adds it to this list + n.next = changed; + changed = n; + } + e = e.next; + } + } + this.maxStack = max; + + // visits all the frames that must be stored in the stack map + Label l = labels; + while (l != null) { + f = l.frame; + if ((l.status & Label.STORE) != 0) { + visitFrame(f); + } + if ((l.status & Label.REACHABLE) == 0) { + // finds start and end of dead basic block + Label k = l.successor; + int start = l.position; + int end = (k == null ? code.length : k.position) - 1; + // if non empty basic block + if (end >= start) { + // replaces instructions with NOP ... NOP ATHROW + for (int i = start; i < end; ++i) { + code.data[i] = Opcodes.NOP; + } + code.data[end] = (byte) Opcodes.ATHROW; + // emits a frame for this unreachable block + startFrame(start, 0, 1); + frame[frameIndex++] = Frame.OBJECT + | cw.addType("java/lang/Throwable"); + endFrame(); + } + } + l = l.successor; + } + } else if (compute == MAXS) { + // completes the control flow graph with exception handler blocks + Handler handler = firstHandler; + while (handler != null) { + Label l = handler.start; + Label h = handler.handler; + Label e = handler.end; + // adds 'h' as a successor of labels between 'start' and 'end' + while (l != e) { + // creates an edge to 'h' + Edge b = new Edge(); + b.info = Edge.EXCEPTION; + b.successor = h; + // adds it to the successors of 'l' + if ((l.status & Label.JSR) == 0) { + b.next = l.successors; + l.successors = b; + } else { + // if l is a JSR block, adds b after the first two edges + // to preserve the hypothesis about JSR block successors + // order (see {@link #visitJumpInsn}) + b.next = l.successors.next.next; + l.successors.next.next = b; + } + // goes to the next label + l = l.successor; + } + handler = handler.next; + } + + if (subroutines > 0) { + // completes the control flow graph with the RET successors + /* + * first step: finds the subroutines. This step determines, for + * each basic block, to which subroutine(s) it belongs. + */ + // finds the basic blocks that belong to the "main" subroutine + int id = 0; + labels.visitSubroutine(null, 1, subroutines); + // finds the basic blocks that belong to the real subroutines + Label l = labels; + while (l != null) { + if ((l.status & Label.JSR) != 0) { + // the subroutine is defined by l's TARGET, not by l + Label subroutine = l.successors.next.successor; + // if this subroutine has not been visited yet... + if ((subroutine.status & Label.VISITED) == 0) { + // ...assigns it a new id and finds its basic blocks + id += 1; + subroutine.visitSubroutine(null, (id / 32L) << 32 + | (1L << (id % 32)), subroutines); + } + } + l = l.successor; + } + // second step: finds the successors of RET blocks + l = labels; + while (l != null) { + if ((l.status & Label.JSR) != 0) { + Label L = labels; + while (L != null) { + L.status &= ~Label.VISITED; + L = L.successor; + } + // the subroutine is defined by l's TARGET, not by l + Label subroutine = l.successors.next.successor; + subroutine.visitSubroutine(l, 0, subroutines); + } + l = l.successor; + } + } + + /* + * control flow analysis algorithm: while the block stack is not + * empty, pop a block from this stack, update the max stack size, + * compute the true (non relative) begin stack size of the + * successors of this block, and push these successors onto the + * stack (unless they have already been pushed onto the stack). + * Note: by hypothesis, the {@link Label#inputStackTop} of the + * blocks in the block stack are the true (non relative) beginning + * stack sizes of these blocks. + */ + int max = 0; + Label stack = labels; + while (stack != null) { + // pops a block from the stack + Label l = stack; + stack = stack.next; + // computes the true (non relative) max stack size of this block + int start = l.inputStackTop; + int blockMax = start + l.outputStackMax; + // updates the global max stack size + if (blockMax > max) { + max = blockMax; + } + // analyzes the successors of the block + Edge b = l.successors; + if ((l.status & Label.JSR) != 0) { + // ignores the first edge of JSR blocks (virtual successor) + b = b.next; + } + while (b != null) { + l = b.successor; + // if this successor has not already been pushed... + if ((l.status & Label.PUSHED) == 0) { + // computes its true beginning stack size... + l.inputStackTop = b.info == Edge.EXCEPTION ? 1 : start + + b.info; + // ...and pushes it onto the stack + l.status |= Label.PUSHED; + l.next = stack; + stack = l; + } + b = b.next; + } + } + this.maxStack = max; + } else { + this.maxStack = maxStack; + this.maxLocals = maxLocals; + } + } + + public void visitEnd() { + } + + // ------------------------------------------------------------------------ + // Utility methods: control flow analysis algorithm + // ------------------------------------------------------------------------ + + /** + * Computes the size of the arguments and of the return value of a method. + * + * @param desc the descriptor of a method. + * @return the size of the arguments of the method (plus one for the + * implicit this argument), argSize, and the size of its return + * value, retSize, packed into a single int i = + * <tt>(argSize << 2) | retSize</tt> (argSize is therefore equal + * to <tt>i >> 2</tt>, and retSize to <tt>i & 0x03</tt>). + */ + static int getArgumentsAndReturnSizes(final String desc) { + int n = 1; + int c = 1; + while (true) { + char car = desc.charAt(c++); + if (car == ')') { + car = desc.charAt(c); + return n << 2 + | (car == 'V' ? 0 : (car == 'D' || car == 'J' ? 2 : 1)); + } else if (car == 'L') { + while (desc.charAt(c++) != ';') { + } + n += 1; + } else if (car == '[') { + while ((car = desc.charAt(c)) == '[') { + ++c; + } + if (car == 'D' || car == 'J') { + n -= 1; + } + } else if (car == 'D' || car == 'J') { + n += 2; + } else { + n += 1; + } + } + } + + /** + * Adds a successor to the {@link #currentBlock currentBlock} block. + * + * @param info information about the control flow edge to be added. + * @param successor the successor block to be added to the current block. + */ + private void addSuccessor(final int info, final Label successor) { + // creates and initializes an Edge object... + Edge b = new Edge(); + b.info = info; + b.successor = successor; + // ...and adds it to the successor list of the currentBlock block + b.next = currentBlock.successors; + currentBlock.successors = b; + } + + /** + * Ends the current basic block. This method must be used in the case where + * the current basic block does not have any successor. + */ + private void noSuccessor() { + if (compute == FRAMES) { + Label l = new Label(); + l.frame = new Frame(); + l.frame.owner = l; + l.resolve(this, code.length, code.data); + previousBlock.successor = l; + previousBlock = l; + } else { + currentBlock.outputStackMax = maxStackSize; + } + currentBlock = null; + } + + // ------------------------------------------------------------------------ + // Utility methods: stack map frames + // ------------------------------------------------------------------------ + + /** + * Visits a frame that has been computed from scratch. + * + * @param f the frame that must be visited. + */ + private void visitFrame(final Frame f) { + int i, t; + int nTop = 0; + int nLocal = 0; + int nStack = 0; + int[] locals = f.inputLocals; + int[] stacks = f.inputStack; + // computes the number of locals (ignores TOP types that are just after + // a LONG or a DOUBLE, and all trailing TOP types) + for (i = 0; i < locals.length; ++i) { + t = locals[i]; + if (t == Frame.TOP) { + ++nTop; + } else { + nLocal += nTop + 1; + nTop = 0; + } + if (t == Frame.LONG || t == Frame.DOUBLE) { + ++i; + } + } + // computes the stack size (ignores TOP types that are just after + // a LONG or a DOUBLE) + for (i = 0; i < stacks.length; ++i) { + t = stacks[i]; + ++nStack; + if (t == Frame.LONG || t == Frame.DOUBLE) { + ++i; + } + } + // visits the frame and its content + startFrame(f.owner.position, nLocal, nStack); + for (i = 0; nLocal > 0; ++i, --nLocal) { + t = locals[i]; + frame[frameIndex++] = t; + if (t == Frame.LONG || t == Frame.DOUBLE) { + ++i; + } + } + for (i = 0; i < stacks.length; ++i) { + t = stacks[i]; + frame[frameIndex++] = t; + if (t == Frame.LONG || t == Frame.DOUBLE) { + ++i; + } + } + endFrame(); + } + + /** + * Starts the visit of a stack map frame. + * + * @param offset the offset of the instruction to which the frame + * corresponds. + * @param nLocal the number of local variables in the frame. + * @param nStack the number of stack elements in the frame. + */ + private void startFrame(final int offset, final int nLocal, final int nStack) + { + int n = 3 + nLocal + nStack; + if (frame == null || frame.length < n) { + frame = new int[n]; + } + frame[0] = offset; + frame[1] = nLocal; + frame[2] = nStack; + frameIndex = 3; + } + + /** + * Checks if the visit of the current frame {@link #frame} is finished, and + * if yes, write it in the StackMapTable attribute. + */ + private void endFrame() { + if (previousFrame != null) { // do not write the first frame + if (stackMap == null) { + stackMap = new ByteVector(); + } + writeFrame(); + ++frameCount; + } + previousFrame = frame; + frame = null; + } + + /** + * Compress and writes the current frame {@link #frame} in the StackMapTable + * attribute. + */ + private void writeFrame() { + int clocalsSize = frame[1]; + int cstackSize = frame[2]; + if ((cw.version & 0xFFFF) < Opcodes.V1_6) { + stackMap.putShort(frame[0]).putShort(clocalsSize); + writeFrameTypes(3, 3 + clocalsSize); + stackMap.putShort(cstackSize); + writeFrameTypes(3 + clocalsSize, 3 + clocalsSize + cstackSize); + return; + } + int localsSize = previousFrame[1]; + int type = FULL_FRAME; + int k = 0; + int delta; + if (frameCount == 0) { + delta = frame[0]; + } else { + delta = frame[0] - previousFrame[0] - 1; + } + if (cstackSize == 0) { + k = clocalsSize - localsSize; + switch (k) { + case -3: + case -2: + case -1: + type = CHOP_FRAME; + localsSize = clocalsSize; + break; + case 0: + type = delta < 64 ? SAME_FRAME : SAME_FRAME_EXTENDED; + break; + case 1: + case 2: + case 3: + type = APPEND_FRAME; + break; + } + } else if (clocalsSize == localsSize && cstackSize == 1) { + type = delta < 63 + ? SAME_LOCALS_1_STACK_ITEM_FRAME + : SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED; + } + if (type != FULL_FRAME) { + // verify if locals are the same + int l = 3; + for (int j = 0; j < localsSize; j++) { + if (frame[l] != previousFrame[l]) { + type = FULL_FRAME; + break; + } + l++; + } + } + switch (type) { + case SAME_FRAME: + stackMap.putByte(delta); + break; + case SAME_LOCALS_1_STACK_ITEM_FRAME: + stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME + delta); + writeFrameTypes(3 + clocalsSize, 4 + clocalsSize); + break; + case SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED: + stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED) + .putShort(delta); + writeFrameTypes(3 + clocalsSize, 4 + clocalsSize); + break; + case SAME_FRAME_EXTENDED: + stackMap.putByte(SAME_FRAME_EXTENDED).putShort(delta); + break; + case CHOP_FRAME: + stackMap.putByte(SAME_FRAME_EXTENDED + k).putShort(delta); + break; + case APPEND_FRAME: + stackMap.putByte(SAME_FRAME_EXTENDED + k).putShort(delta); + writeFrameTypes(3 + localsSize, 3 + clocalsSize); + break; + // case FULL_FRAME: + default: + stackMap.putByte(FULL_FRAME) + .putShort(delta) + .putShort(clocalsSize); + writeFrameTypes(3, 3 + clocalsSize); + stackMap.putShort(cstackSize); + writeFrameTypes(3 + clocalsSize, 3 + clocalsSize + cstackSize); + } + } + + /** + * Writes some types of the current frame {@link #frame} into the + * StackMapTableAttribute. This method converts types from the format used + * in {@link Label} to the format used in StackMapTable attributes. In + * particular, it converts type table indexes to constant pool indexes. + * + * @param start index of the first type in {@link #frame} to write. + * @param end index of last type in {@link #frame} to write (exclusive). + */ + private void writeFrameTypes(final int start, final int end) { + for (int i = start; i < end; ++i) { + int t = frame[i]; + int d = t & Frame.DIM; + if (d == 0) { + int v = t & Frame.BASE_VALUE; + switch (t & Frame.BASE_KIND) { + case Frame.OBJECT: + stackMap.putByte(7) + .putShort(cw.newClass(cw.typeTable[v].strVal1)); + break; + case Frame.UNINITIALIZED: + stackMap.putByte(8).putShort(cw.typeTable[v].intVal); + break; + default: + stackMap.putByte(v); + } + } else { + StringBuffer buf = new StringBuffer(); + d >>= 28; + while (d-- > 0) { + buf.append('['); + } + if ((t & Frame.BASE_KIND) == Frame.OBJECT) { + buf.append('L'); + buf.append(cw.typeTable[t & Frame.BASE_VALUE].strVal1); + buf.append(';'); + } else { + switch (t & 0xF) { + case 1: + buf.append('I'); + break; + case 2: + buf.append('F'); + break; + case 3: + buf.append('D'); + break; + case 9: + buf.append('Z'); + break; + case 10: + buf.append('B'); + break; + case 11: + buf.append('C'); + break; + case 12: + buf.append('S'); + break; + default: + buf.append('J'); + } + } + stackMap.putByte(7).putShort(cw.newClass(buf.toString())); + } + } + } + + private void writeFrameType(final Object type) { + if (type instanceof String) { + stackMap.putByte(7).putShort(cw.newClass((String) type)); + } else if (type instanceof Integer) { + stackMap.putByte(((Integer) type).intValue()); + } else { + stackMap.putByte(8).putShort(((Label) type).position); + } + } + + // ------------------------------------------------------------------------ + // Utility methods: dump bytecode array + // ------------------------------------------------------------------------ + + /** + * Returns the size of the bytecode of this method. + * + * @return the size of the bytecode of this method. + */ + final int getSize() { + if (classReaderOffset != 0) { + return 6 + classReaderLength; + } + if (resize) { + // replaces the temporary jump opcodes introduced by Label.resolve. + if (ClassReader.RESIZE) { + resizeInstructions(); + } else { + throw new RuntimeException("Method code too large!"); + } + } + int size = 8; + if (code.length > 0) { + cw.newUTF8("Code"); + size += 18 + code.length + 8 * handlerCount; + if (localVar != null) { + cw.newUTF8("LocalVariableTable"); + size += 8 + localVar.length; + } + if (localVarType != null) { + cw.newUTF8("LocalVariableTypeTable"); + size += 8 + localVarType.length; + } + if (lineNumber != null) { + cw.newUTF8("LineNumberTable"); + size += 8 + lineNumber.length; + } + if (stackMap != null) { + boolean zip = (cw.version & 0xFFFF) >= Opcodes.V1_6; + cw.newUTF8(zip ? "StackMapTable" : "StackMap"); + size += 8 + stackMap.length; + } + if (cattrs != null) { + size += cattrs.getSize(cw, + code.data, + code.length, + maxStack, + maxLocals); + } + } + if (exceptionCount > 0) { + cw.newUTF8("Exceptions"); + size += 8 + 2 * exceptionCount; + } + if ((access & Opcodes.ACC_SYNTHETIC) != 0 + && (cw.version & 0xffff) < Opcodes.V1_5) + { + cw.newUTF8("Synthetic"); + size += 6; + } + if ((access & Opcodes.ACC_DEPRECATED) != 0) { + cw.newUTF8("Deprecated"); + size += 6; + } + if (ClassReader.SIGNATURES && signature != null) { + cw.newUTF8("Signature"); + cw.newUTF8(signature); + size += 8; + } + if (ClassReader.ANNOTATIONS && annd != null) { + cw.newUTF8("AnnotationDefault"); + size += 6 + annd.length; + } + if (ClassReader.ANNOTATIONS && anns != null) { + cw.newUTF8("RuntimeVisibleAnnotations"); + size += 8 + anns.getSize(); + } + if (ClassReader.ANNOTATIONS && ianns != null) { + cw.newUTF8("RuntimeInvisibleAnnotations"); + size += 8 + ianns.getSize(); + } + if (ClassReader.ANNOTATIONS && panns != null) { + cw.newUTF8("RuntimeVisibleParameterAnnotations"); + size += 7 + 2 * (panns.length - synthetics); + for (int i = panns.length - 1; i >= synthetics; --i) { + size += panns[i] == null ? 0 : panns[i].getSize(); + } + } + if (ClassReader.ANNOTATIONS && ipanns != null) { + cw.newUTF8("RuntimeInvisibleParameterAnnotations"); + size += 7 + 2 * (ipanns.length - synthetics); + for (int i = ipanns.length - 1; i >= synthetics; --i) { + size += ipanns[i] == null ? 0 : ipanns[i].getSize(); + } + } + if (attrs != null) { + size += attrs.getSize(cw, null, 0, -1, -1); + } + return size; + } + + /** + * Puts the bytecode of this method in the given byte vector. + * + * @param out the byte vector into which the bytecode of this method must be + * copied. + */ + final void put(final ByteVector out) { + out.putShort(access).putShort(name).putShort(desc); + if (classReaderOffset != 0) { + out.putByteArray(cw.cr.b, classReaderOffset, classReaderLength); + return; + } + int attributeCount = 0; + if (code.length > 0) { + ++attributeCount; + } + if (exceptionCount > 0) { + ++attributeCount; + } + if ((access & Opcodes.ACC_SYNTHETIC) != 0 + && (cw.version & 0xffff) < Opcodes.V1_5) + { + ++attributeCount; + } + if ((access & Opcodes.ACC_DEPRECATED) != 0) { + ++attributeCount; + } + if (ClassReader.SIGNATURES && signature != null) { + ++attributeCount; + } + if (ClassReader.ANNOTATIONS && annd != null) { + ++attributeCount; + } + if (ClassReader.ANNOTATIONS && anns != null) { + ++attributeCount; + } + if (ClassReader.ANNOTATIONS && ianns != null) { + ++attributeCount; + } + if (ClassReader.ANNOTATIONS && panns != null) { + ++attributeCount; + } + if (ClassReader.ANNOTATIONS && ipanns != null) { + ++attributeCount; + } + if (attrs != null) { + attributeCount += attrs.getCount(); + } + out.putShort(attributeCount); + if (code.length > 0) { + int size = 12 + code.length + 8 * handlerCount; + if (localVar != null) { + size += 8 + localVar.length; + } + if (localVarType != null) { + size += 8 + localVarType.length; + } + if (lineNumber != null) { + size += 8 + lineNumber.length; + } + if (stackMap != null) { + size += 8 + stackMap.length; + } + if (cattrs != null) { + size += cattrs.getSize(cw, + code.data, + code.length, + maxStack, + maxLocals); + } + out.putShort(cw.newUTF8("Code")).putInt(size); + out.putShort(maxStack).putShort(maxLocals); + out.putInt(code.length).putByteArray(code.data, 0, code.length); + out.putShort(handlerCount); + if (handlerCount > 0) { + Handler h = firstHandler; + while (h != null) { + out.putShort(h.start.position) + .putShort(h.end.position) + .putShort(h.handler.position) + .putShort(h.type); + h = h.next; + } + } + attributeCount = 0; + if (localVar != null) { + ++attributeCount; + } + if (localVarType != null) { + ++attributeCount; + } + if (lineNumber != null) { + ++attributeCount; + } + if (stackMap != null) { + ++attributeCount; + } + if (cattrs != null) { + attributeCount += cattrs.getCount(); + } + out.putShort(attributeCount); + if (localVar != null) { + out.putShort(cw.newUTF8("LocalVariableTable")); + out.putInt(localVar.length + 2).putShort(localVarCount); + out.putByteArray(localVar.data, 0, localVar.length); + } + if (localVarType != null) { + out.putShort(cw.newUTF8("LocalVariableTypeTable")); + out.putInt(localVarType.length + 2).putShort(localVarTypeCount); + out.putByteArray(localVarType.data, 0, localVarType.length); + } + if (lineNumber != null) { + out.putShort(cw.newUTF8("LineNumberTable")); + out.putInt(lineNumber.length + 2).putShort(lineNumberCount); + out.putByteArray(lineNumber.data, 0, lineNumber.length); + } + if (stackMap != null) { + boolean zip = (cw.version & 0xFFFF) >= Opcodes.V1_6; + out.putShort(cw.newUTF8(zip ? "StackMapTable" : "StackMap")); + out.putInt(stackMap.length + 2).putShort(frameCount); + out.putByteArray(stackMap.data, 0, stackMap.length); + } + if (cattrs != null) { + cattrs.put(cw, code.data, code.length, maxLocals, maxStack, out); + } + } + if (exceptionCount > 0) { + out.putShort(cw.newUTF8("Exceptions")) + .putInt(2 * exceptionCount + 2); + out.putShort(exceptionCount); + for (int i = 0; i < exceptionCount; ++i) { + out.putShort(exceptions[i]); + } + } + if ((access & Opcodes.ACC_SYNTHETIC) != 0 + && (cw.version & 0xffff) < Opcodes.V1_5) + { + out.putShort(cw.newUTF8("Synthetic")).putInt(0); + } + if ((access & Opcodes.ACC_DEPRECATED) != 0) { + out.putShort(cw.newUTF8("Deprecated")).putInt(0); + } + if (ClassReader.SIGNATURES && signature != null) { + out.putShort(cw.newUTF8("Signature")) + .putInt(2) + .putShort(cw.newUTF8(signature)); + } + if (ClassReader.ANNOTATIONS && annd != null) { + out.putShort(cw.newUTF8("AnnotationDefault")); + out.putInt(annd.length); + out.putByteArray(annd.data, 0, annd.length); + } + if (ClassReader.ANNOTATIONS && anns != null) { + out.putShort(cw.newUTF8("RuntimeVisibleAnnotations")); + anns.put(out); + } + if (ClassReader.ANNOTATIONS && ianns != null) { + out.putShort(cw.newUTF8("RuntimeInvisibleAnnotations")); + ianns.put(out); + } + if (ClassReader.ANNOTATIONS && panns != null) { + out.putShort(cw.newUTF8("RuntimeVisibleParameterAnnotations")); + AnnotationWriter.put(panns, synthetics, out); + } + if (ClassReader.ANNOTATIONS && ipanns != null) { + out.putShort(cw.newUTF8("RuntimeInvisibleParameterAnnotations")); + AnnotationWriter.put(ipanns, synthetics, out); + } + if (attrs != null) { + attrs.put(cw, null, 0, -1, -1, out); + } + } + + // ------------------------------------------------------------------------ + // Utility methods: instruction resizing (used to handle GOTO_W and JSR_W) + // ------------------------------------------------------------------------ + + /** + * Resizes and replaces the temporary instructions inserted by + * {@link Label#resolve} for wide forward jumps, while keeping jump offsets + * and instruction addresses consistent. This may require to resize other + * existing instructions, or even to introduce new instructions: for + * example, increasing the size of an instruction by 2 at the middle of a + * method can increases the offset of an IFEQ instruction from 32766 to + * 32768, in which case IFEQ 32766 must be replaced with IFNEQ 8 GOTO_W + * 32765. This, in turn, may require to increase the size of another jump + * instruction, and so on... All these operations are handled automatically + * by this method. <p> <i>This method must be called after all the method + * that is being built has been visited</i>. In particular, the + * {@link Label Label} objects used to construct the method are no longer + * valid after this method has been called. + */ + private void resizeInstructions() { + byte[] b = code.data; // bytecode of the method + int u, v, label; // indexes in b + int i, j; // loop indexes + /* + * 1st step: As explained above, resizing an instruction may require to + * resize another one, which may require to resize yet another one, and + * so on. The first step of the algorithm consists in finding all the + * instructions that need to be resized, without modifying the code. + * This is done by the following "fix point" algorithm: + * + * Parse the code to find the jump instructions whose offset will need + * more than 2 bytes to be stored (the future offset is computed from + * the current offset and from the number of bytes that will be inserted + * or removed between the source and target instructions). For each such + * instruction, adds an entry in (a copy of) the indexes and sizes + * arrays (if this has not already been done in a previous iteration!). + * + * If at least one entry has been added during the previous step, go + * back to the beginning, otherwise stop. + * + * In fact the real algorithm is complicated by the fact that the size + * of TABLESWITCH and LOOKUPSWITCH instructions depends on their + * position in the bytecode (because of padding). In order to ensure the + * convergence of the algorithm, the number of bytes to be added or + * removed from these instructions is over estimated during the previous + * loop, and computed exactly only after the loop is finished (this + * requires another pass to parse the bytecode of the method). + */ + int[] allIndexes = new int[0]; // copy of indexes + int[] allSizes = new int[0]; // copy of sizes + boolean[] resize; // instructions to be resized + int newOffset; // future offset of a jump instruction + + resize = new boolean[code.length]; + + // 3 = loop again, 2 = loop ended, 1 = last pass, 0 = done + int state = 3; + do { + if (state == 3) { + state = 2; + } + u = 0; + while (u < b.length) { + int opcode = b[u] & 0xFF; // opcode of current instruction + int insert = 0; // bytes to be added after this instruction + + switch (ClassWriter.TYPE[opcode]) { + case ClassWriter.NOARG_INSN: + case ClassWriter.IMPLVAR_INSN: + u += 1; + break; + case ClassWriter.LABEL_INSN: + if (opcode > 201) { + // converts temporary opcodes 202 to 217, 218 and + // 219 to IFEQ ... JSR (inclusive), IFNULL and + // IFNONNULL + opcode = opcode < 218 ? opcode - 49 : opcode - 20; + label = u + readUnsignedShort(b, u + 1); + } else { + label = u + readShort(b, u + 1); + } + newOffset = getNewOffset(allIndexes, allSizes, u, label); + if (newOffset < Short.MIN_VALUE + || newOffset > Short.MAX_VALUE) + { + if (!resize[u]) { + if (opcode == Opcodes.GOTO + || opcode == Opcodes.JSR) + { + // two additional bytes will be required to + // replace this GOTO or JSR instruction with + // a GOTO_W or a JSR_W + insert = 2; + } else { + // five additional bytes will be required to + // replace this IFxxx <l> instruction with + // IFNOTxxx <l'> GOTO_W <l>, where IFNOTxxx + // is the "opposite" opcode of IFxxx (i.e., + // IFNE for IFEQ) and where <l'> designates + // the instruction just after the GOTO_W. + insert = 5; + } + resize[u] = true; + } + } + u += 3; + break; + case ClassWriter.LABELW_INSN: + u += 5; + break; + case ClassWriter.TABL_INSN: + if (state == 1) { + // true number of bytes to be added (or removed) + // from this instruction = (future number of padding + // bytes - current number of padding byte) - + // previously over estimated variation = + // = ((3 - newOffset%4) - (3 - u%4)) - u%4 + // = (-newOffset%4 + u%4) - u%4 + // = -(newOffset & 3) + newOffset = getNewOffset(allIndexes, allSizes, 0, u); + insert = -(newOffset & 3); + } else if (!resize[u]) { + // over estimation of the number of bytes to be + // added to this instruction = 3 - current number + // of padding bytes = 3 - (3 - u%4) = u%4 = u & 3 + insert = u & 3; + resize[u] = true; + } + // skips instruction + u = u + 4 - (u & 3); + u += 4 * (readInt(b, u + 8) - readInt(b, u + 4) + 1) + 12; + break; + case ClassWriter.LOOK_INSN: + if (state == 1) { + // like TABL_INSN + newOffset = getNewOffset(allIndexes, allSizes, 0, u); + insert = -(newOffset & 3); + } else if (!resize[u]) { + // like TABL_INSN + insert = u & 3; + resize[u] = true; + } + // skips instruction + u = u + 4 - (u & 3); + u += 8 * readInt(b, u + 4) + 8; + break; + case ClassWriter.WIDE_INSN: + opcode = b[u + 1] & 0xFF; + if (opcode == Opcodes.IINC) { + u += 6; + } else { + u += 4; + } + break; + case ClassWriter.VAR_INSN: + case ClassWriter.SBYTE_INSN: + case ClassWriter.LDC_INSN: + u += 2; + break; + case ClassWriter.SHORT_INSN: + case ClassWriter.LDCW_INSN: + case ClassWriter.FIELDORMETH_INSN: + case ClassWriter.TYPE_INSN: + case ClassWriter.IINC_INSN: + u += 3; + break; + case ClassWriter.ITFMETH_INSN: + u += 5; + break; + // case ClassWriter.MANA_INSN: + default: + u += 4; + break; + } + if (insert != 0) { + // adds a new (u, insert) entry in the allIndexes and + // allSizes arrays + int[] newIndexes = new int[allIndexes.length + 1]; + int[] newSizes = new int[allSizes.length + 1]; + System.arraycopy(allIndexes, + 0, + newIndexes, + 0, + allIndexes.length); + System.arraycopy(allSizes, 0, newSizes, 0, allSizes.length); + newIndexes[allIndexes.length] = u; + newSizes[allSizes.length] = insert; + allIndexes = newIndexes; + allSizes = newSizes; + if (insert > 0) { + state = 3; + } + } + } + if (state < 3) { + --state; + } + } while (state != 0); + + // 2nd step: + // copies the bytecode of the method into a new bytevector, updates the + // offsets, and inserts (or removes) bytes as requested. + + ByteVector newCode = new ByteVector(code.length); + + u = 0; + while (u < code.length) { + int opcode = b[u] & 0xFF; + switch (ClassWriter.TYPE[opcode]) { + case ClassWriter.NOARG_INSN: + case ClassWriter.IMPLVAR_INSN: + newCode.putByte(opcode); + u += 1; + break; + case ClassWriter.LABEL_INSN: + if (opcode > 201) { + // changes temporary opcodes 202 to 217 (inclusive), 218 + // and 219 to IFEQ ... JSR (inclusive), IFNULL and + // IFNONNULL + opcode = opcode < 218 ? opcode - 49 : opcode - 20; + label = u + readUnsignedShort(b, u + 1); + } else { + label = u + readShort(b, u + 1); + } + newOffset = getNewOffset(allIndexes, allSizes, u, label); + if (resize[u]) { + // replaces GOTO with GOTO_W, JSR with JSR_W and IFxxx + // <l> with IFNOTxxx <l'> GOTO_W <l>, where IFNOTxxx is + // the "opposite" opcode of IFxxx (i.e., IFNE for IFEQ) + // and where <l'> designates the instruction just after + // the GOTO_W. + if (opcode == Opcodes.GOTO) { + newCode.putByte(200); // GOTO_W + } else if (opcode == Opcodes.JSR) { + newCode.putByte(201); // JSR_W + } else { + newCode.putByte(opcode <= 166 + ? ((opcode + 1) ^ 1) - 1 + : opcode ^ 1); + newCode.putShort(8); // jump offset + newCode.putByte(200); // GOTO_W + // newOffset now computed from start of GOTO_W + newOffset -= 3; + } + newCode.putInt(newOffset); + } else { + newCode.putByte(opcode); + newCode.putShort(newOffset); + } + u += 3; + break; + case ClassWriter.LABELW_INSN: + label = u + readInt(b, u + 1); + newOffset = getNewOffset(allIndexes, allSizes, u, label); + newCode.putByte(opcode); + newCode.putInt(newOffset); + u += 5; + break; + case ClassWriter.TABL_INSN: + // skips 0 to 3 padding bytes + v = u; + u = u + 4 - (v & 3); + // reads and copies instruction + newCode.putByte(Opcodes.TABLESWITCH); + newCode.length += (4 - newCode.length % 4) % 4; + label = v + readInt(b, u); + u += 4; + newOffset = getNewOffset(allIndexes, allSizes, v, label); + newCode.putInt(newOffset); + j = readInt(b, u); + u += 4; + newCode.putInt(j); + j = readInt(b, u) - j + 1; + u += 4; + newCode.putInt(readInt(b, u - 4)); + for (; j > 0; --j) { + label = v + readInt(b, u); + u += 4; + newOffset = getNewOffset(allIndexes, allSizes, v, label); + newCode.putInt(newOffset); + } + break; + case ClassWriter.LOOK_INSN: + // skips 0 to 3 padding bytes + v = u; + u = u + 4 - (v & 3); + // reads and copies instruction + newCode.putByte(Opcodes.LOOKUPSWITCH); + newCode.length += (4 - newCode.length % 4) % 4; + label = v + readInt(b, u); + u += 4; + newOffset = getNewOffset(allIndexes, allSizes, v, label); + newCode.putInt(newOffset); + j = readInt(b, u); + u += 4; + newCode.putInt(j); + for (; j > 0; --j) { + newCode.putInt(readInt(b, u)); + u += 4; + label = v + readInt(b, u); + u += 4; + newOffset = getNewOffset(allIndexes, allSizes, v, label); + newCode.putInt(newOffset); + } + break; + case ClassWriter.WIDE_INSN: + opcode = b[u + 1] & 0xFF; + if (opcode == Opcodes.IINC) { + newCode.putByteArray(b, u, 6); + u += 6; + } else { + newCode.putByteArray(b, u, 4); + u += 4; + } + break; + case ClassWriter.VAR_INSN: + case ClassWriter.SBYTE_INSN: + case ClassWriter.LDC_INSN: + newCode.putByteArray(b, u, 2); + u += 2; + break; + case ClassWriter.SHORT_INSN: + case ClassWriter.LDCW_INSN: + case ClassWriter.FIELDORMETH_INSN: + case ClassWriter.TYPE_INSN: + case ClassWriter.IINC_INSN: + newCode.putByteArray(b, u, 3); + u += 3; + break; + case ClassWriter.ITFMETH_INSN: + newCode.putByteArray(b, u, 5); + u += 5; + break; + // case MANA_INSN: + default: + newCode.putByteArray(b, u, 4); + u += 4; + break; + } + } + + // recomputes the stack map frames + if (frameCount > 0) { + if (compute == FRAMES) { + frameCount = 0; + stackMap = null; + previousFrame = null; + frame = null; + Frame f = new Frame(); + f.owner = labels; + Type[] args = Type.getArgumentTypes(descriptor); + f.initInputFrame(cw, access, args, maxLocals); + visitFrame(f); + Label l = labels; + while (l != null) { + /* + * here we need the original label position. getNewOffset + * must therefore never have been called for this label. + */ + u = l.position - 3; + if ((l.status & Label.STORE) != 0 || (u >= 0 && resize[u])) + { + getNewOffset(allIndexes, allSizes, l); + // TODO update offsets in UNINITIALIZED values + visitFrame(l.frame); + } + l = l.successor; + } + } else { + /* + * Resizing an existing stack map frame table is really hard. + * Not only the table must be parsed to update the offets, but + * new frames may be needed for jump instructions that were + * inserted by this method. And updating the offsets or + * inserting frames can change the format of the following + * frames, in case of packed frames. In practice the whole table + * must be recomputed. For this the frames are marked as + * potentially invalid. This will cause the whole class to be + * reread and rewritten with the COMPUTE_FRAMES option (see the + * ClassWriter.toByteArray method). This is not very efficient + * but is much easier and requires much less code than any other + * method I can think of. + */ + cw.invalidFrames = true; + } + } + // updates the exception handler block labels + Handler h = firstHandler; + while (h != null) { + getNewOffset(allIndexes, allSizes, h.start); + getNewOffset(allIndexes, allSizes, h.end); + getNewOffset(allIndexes, allSizes, h.handler); + h = h.next; + } + // updates the instructions addresses in the + // local var and line number tables + for (i = 0; i < 2; ++i) { + ByteVector bv = i == 0 ? localVar : localVarType; + if (bv != null) { + b = bv.data; + u = 0; + while (u < bv.length) { + label = readUnsignedShort(b, u); + newOffset = getNewOffset(allIndexes, allSizes, 0, label); + writeShort(b, u, newOffset); + label += readUnsignedShort(b, u + 2); + newOffset = getNewOffset(allIndexes, allSizes, 0, label) + - newOffset; + writeShort(b, u + 2, newOffset); + u += 10; + } + } + } + if (lineNumber != null) { + b = lineNumber.data; + u = 0; + while (u < lineNumber.length) { + writeShort(b, u, getNewOffset(allIndexes, + allSizes, + 0, + readUnsignedShort(b, u))); + u += 4; + } + } + // updates the labels of the other attributes + Attribute attr = cattrs; + while (attr != null) { + Label[] labels = attr.getLabels(); + if (labels != null) { + for (i = labels.length - 1; i >= 0; --i) { + getNewOffset(allIndexes, allSizes, labels[i]); + } + } + attr = attr.next; + } + + // replaces old bytecodes with new ones + code = newCode; + } + + /** + * Reads an unsigned short value in the given byte array. + * + * @param b a byte array. + * @param index the start index of the value to be read. + * @return the read value. + */ + static int readUnsignedShort(final byte[] b, final int index) { + return ((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF); + } + + /** + * Reads a signed short value in the given byte array. + * + * @param b a byte array. + * @param index the start index of the value to be read. + * @return the read value. + */ + static short readShort(final byte[] b, final int index) { + return (short) (((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF)); + } + + /** + * Reads a signed int value in the given byte array. + * + * @param b a byte array. + * @param index the start index of the value to be read. + * @return the read value. + */ + static int readInt(final byte[] b, final int index) { + return ((b[index] & 0xFF) << 24) | ((b[index + 1] & 0xFF) << 16) + | ((b[index + 2] & 0xFF) << 8) | (b[index + 3] & 0xFF); + } + + /** + * Writes a short value in the given byte array. + * + * @param b a byte array. + * @param index where the first byte of the short value must be written. + * @param s the value to be written in the given byte array. + */ + static void writeShort(final byte[] b, final int index, final int s) { + b[index] = (byte) (s >>> 8); + b[index + 1] = (byte) s; + } + + /** + * Computes the future value of a bytecode offset. <p> Note: it is possible + * to have several entries for the same instruction in the <tt>indexes</tt> + * and <tt>sizes</tt>: two entries (index=a,size=b) and (index=a,size=b') + * are equivalent to a single entry (index=a,size=b+b'). + * + * @param indexes current positions of the instructions to be resized. Each + * instruction must be designated by the index of its <i>last</i> + * byte, plus one (or, in other words, by the index of the <i>first</i> + * byte of the <i>next</i> instruction). + * @param sizes the number of bytes to be <i>added</i> to the above + * instructions. More precisely, for each i < <tt>len</tt>, + * <tt>sizes</tt>[i] bytes will be added at the end of the + * instruction designated by <tt>indexes</tt>[i] or, if + * <tt>sizes</tt>[i] is negative, the <i>last</i> |<tt>sizes[i]</tt>| + * bytes of the instruction will be removed (the instruction size + * <i>must not</i> become negative or null). + * @param begin index of the first byte of the source instruction. + * @param end index of the first byte of the target instruction. + * @return the future value of the given bytecode offset. + */ + static int getNewOffset( + final int[] indexes, + final int[] sizes, + final int begin, + final int end) + { + int offset = end - begin; + for (int i = 0; i < indexes.length; ++i) { + if (begin < indexes[i] && indexes[i] <= end) { + // forward jump + offset += sizes[i]; + } else if (end < indexes[i] && indexes[i] <= begin) { + // backward jump + offset -= sizes[i]; + } + } + return offset; + } + + /** + * Updates the offset of the given label. + * + * @param indexes current positions of the instructions to be resized. Each + * instruction must be designated by the index of its <i>last</i> + * byte, plus one (or, in other words, by the index of the <i>first</i> + * byte of the <i>next</i> instruction). + * @param sizes the number of bytes to be <i>added</i> to the above + * instructions. More precisely, for each i < <tt>len</tt>, + * <tt>sizes</tt>[i] bytes will be added at the end of the + * instruction designated by <tt>indexes</tt>[i] or, if + * <tt>sizes</tt>[i] is negative, the <i>last</i> |<tt>sizes[i]</tt>| + * bytes of the instruction will be removed (the instruction size + * <i>must not</i> become negative or null). + * @param label the label whose offset must be updated. + */ + static void getNewOffset( + final int[] indexes, + final int[] sizes, + final Label label) + { + if ((label.status & Label.RESIZED) == 0) { + label.position = getNewOffset(indexes, sizes, 0, label.position); + label.status |= Label.RESIZED; + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/ws/org/objectweb/asm/Opcodes.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,371 @@ +/* + * Copyright 2005-2009 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2007 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.sun.xml.internal.ws.org.objectweb.asm; + +/** + * Defines the JVM opcodes, access flags and array type codes. This interface + * does not define all the JVM opcodes because some opcodes are automatically + * handled. For example, the xLOAD and xSTORE opcodes are automatically replaced + * by xLOAD_n and xSTORE_n opcodes when possible. The xLOAD_n and xSTORE_n + * opcodes are therefore not defined in this interface. Likewise for LDC, + * automatically replaced by LDC_W or LDC2_W when necessary, WIDE, GOTO_W and + * JSR_W. + * + * @author Eric Bruneton + * @author Eugene Kuleshov + */ +public interface Opcodes { + + // versions + + int V1_1 = 3 << 16 | 45; + int V1_2 = 0 << 16 | 46; + int V1_3 = 0 << 16 | 47; + int V1_4 = 0 << 16 | 48; + int V1_5 = 0 << 16 | 49; + int V1_6 = 0 << 16 | 50; + + // access flags + + int ACC_PUBLIC = 0x0001; // class, field, method + int ACC_PRIVATE = 0x0002; // class, field, method + int ACC_PROTECTED = 0x0004; // class, field, method + int ACC_STATIC = 0x0008; // field, method + int ACC_FINAL = 0x0010; // class, field, method + int ACC_SUPER = 0x0020; // class + int ACC_SYNCHRONIZED = 0x0020; // method + int ACC_VOLATILE = 0x0040; // field + int ACC_BRIDGE = 0x0040; // method + int ACC_VARARGS = 0x0080; // method + int ACC_TRANSIENT = 0x0080; // field + int ACC_NATIVE = 0x0100; // method + int ACC_INTERFACE = 0x0200; // class + int ACC_ABSTRACT = 0x0400; // class, method + int ACC_STRICT = 0x0800; // method + int ACC_SYNTHETIC = 0x1000; // class, field, method + int ACC_ANNOTATION = 0x2000; // class + int ACC_ENUM = 0x4000; // class(?) field inner + + // ASM specific pseudo access flags + + int ACC_DEPRECATED = 131072; // class, field, method + + // types for NEWARRAY + + int T_BOOLEAN = 4; + int T_CHAR = 5; + int T_FLOAT = 6; + int T_DOUBLE = 7; + int T_BYTE = 8; + int T_SHORT = 9; + int T_INT = 10; + int T_LONG = 11; + + // stack map frame types + + /** + * Represents an expanded frame. See {@link ClassReader#EXPAND_FRAMES}. + */ + int F_NEW = -1; + + /** + * Represents a compressed frame with complete frame data. + */ + int F_FULL = 0; + + /** + * Represents a compressed frame where locals are the same as the locals in + * the previous frame, except that additional 1-3 locals are defined, and + * with an empty stack. + */ + int F_APPEND = 1; + + /** + * Represents a compressed frame where locals are the same as the locals in + * the previous frame, except that the last 1-3 locals are absent and with + * an empty stack. + */ + int F_CHOP = 2; + + /** + * Represents a compressed frame with exactly the same locals as the + * previous frame and with an empty stack. + */ + int F_SAME = 3; + + /** + * Represents a compressed frame with exactly the same locals as the + * previous frame and with a single value on the stack. + */ + int F_SAME1 = 4; + + Integer TOP = new Integer(0); + Integer INTEGER = new Integer(1); + Integer FLOAT = new Integer(2); + Integer DOUBLE = new Integer(3); + Integer LONG = new Integer(4); + Integer NULL = new Integer(5); + Integer UNINITIALIZED_THIS = new Integer(6); + + // opcodes // visit method (- = idem) + + int NOP = 0; // visitInsn + int ACONST_NULL = 1; // - + int ICONST_M1 = 2; // - + int ICONST_0 = 3; // - + int ICONST_1 = 4; // - + int ICONST_2 = 5; // - + int ICONST_3 = 6; // - + int ICONST_4 = 7; // - + int ICONST_5 = 8; // - + int LCONST_0 = 9; // - + int LCONST_1 = 10; // - + int FCONST_0 = 11; // - + int FCONST_1 = 12; // - + int FCONST_2 = 13; // - + int DCONST_0 = 14; // - + int DCONST_1 = 15; // - + int BIPUSH = 16; // visitIntInsn + int SIPUSH = 17; // - + int LDC = 18; // visitLdcInsn + // int LDC_W = 19; // - + // int LDC2_W = 20; // - + int ILOAD = 21; // visitVarInsn + int LLOAD = 22; // - + int FLOAD = 23; // - + int DLOAD = 24; // - + int ALOAD = 25; // - + // int ILOAD_0 = 26; // - + // int ILOAD_1 = 27; // - + // int ILOAD_2 = 28; // - + // int ILOAD_3 = 29; // - + // int LLOAD_0 = 30; // - + // int LLOAD_1 = 31; // - + // int LLOAD_2 = 32; // - + // int LLOAD_3 = 33; // - + // int FLOAD_0 = 34; // - + // int FLOAD_1 = 35; // - + // int FLOAD_2 = 36; // - + // int FLOAD_3 = 37; // - + // int DLOAD_0 = 38; // - + // int DLOAD_1 = 39; // - + // int DLOAD_2 = 40; // - + // int DLOAD_3 = 41; // - + // int ALOAD_0 = 42; // - + // int ALOAD_1 = 43; // - + // int ALOAD_2 = 44; // - + // int ALOAD_3 = 45; // - + int IALOAD = 46; // visitInsn + int LALOAD = 47; // - + int FALOAD = 48; // - + int DALOAD = 49; // - + int AALOAD = 50; // - + int BALOAD = 51; // - + int CALOAD = 52; // - + int SALOAD = 53; // - + int ISTORE = 54; // visitVarInsn + int LSTORE = 55; // - + int FSTORE = 56; // - + int DSTORE = 57; // - + int ASTORE = 58; // - + // int ISTORE_0 = 59; // - + // int ISTORE_1 = 60; // - + // int ISTORE_2 = 61; // - + // int ISTORE_3 = 62; // - + // int LSTORE_0 = 63; // - + // int LSTORE_1 = 64; // - + // int LSTORE_2 = 65; // - + // int LSTORE_3 = 66; // - + // int FSTORE_0 = 67; // - + // int FSTORE_1 = 68; // - + // int FSTORE_2 = 69; // - + // int FSTORE_3 = 70; // - + // int DSTORE_0 = 71; // - + // int DSTORE_1 = 72; // - + // int DSTORE_2 = 73; // - + // int DSTORE_3 = 74; // - + // int ASTORE_0 = 75; // - + // int ASTORE_1 = 76; // - + // int ASTORE_2 = 77; // - + // int ASTORE_3 = 78; // - + int IASTORE = 79; // visitInsn + int LASTORE = 80; // - + int FASTORE = 81; // - + int DASTORE = 82; // - + int AASTORE = 83; // - + int BASTORE = 84; // - + int CASTORE = 85; // - + int SASTORE = 86; // - + int POP = 87; // - + int POP2 = 88; // - + int DUP = 89; // - + int DUP_X1 = 90; // - + int DUP_X2 = 91; // - + int DUP2 = 92; // - + int DUP2_X1 = 93; // - + int DUP2_X2 = 94; // - + int SWAP = 95; // - + int IADD = 96; // - + int LADD = 97; // - + int FADD = 98; // - + int DADD = 99; // - + int ISUB = 100; // - + int LSUB = 101; // - + int FSUB = 102; // - + int DSUB = 103; // - + int IMUL = 104; // - + int LMUL = 105; // - + int FMUL = 106; // - + int DMUL = 107; // - + int IDIV = 108; // - + int LDIV = 109; // - + int FDIV = 110; // - + int DDIV = 111; // - + int IREM = 112; // - + int LREM = 113; // - + int FREM = 114; // - + int DREM = 115; // - + int INEG = 116; // - + int LNEG = 117; // - + int FNEG = 118; // - + int DNEG = 119; // - + int ISHL = 120; // - + int LSHL = 121; // - + int ISHR = 122; // - + int LSHR = 123; // - + int IUSHR = 124; // - + int LUSHR = 125; // - + int IAND = 126; // - + int LAND = 127; // - + int IOR = 128; // - + int LOR = 129; // - + int IXOR = 130; // - + int LXOR = 131; // - + int IINC = 132; // visitIincInsn + int I2L = 133; // visitInsn + int I2F = 134; // - + int I2D = 135; // - + int L2I = 136; // - + int L2F = 137; // - + int L2D = 138; // - + int F2I = 139; // - + int F2L = 140; // - + int F2D = 141; // - + int D2I = 142; // - + int D2L = 143; // - + int D2F = 144; // - + int I2B = 145; // - + int I2C = 146; // - + int I2S = 147; // - + int LCMP = 148; // - + int FCMPL = 149; // - + int FCMPG = 150; // - + int DCMPL = 151; // - + int DCMPG = 152; // - + int IFEQ = 153; // visitJumpInsn + int IFNE = 154; // - + int IFLT = 155; // - + int IFGE = 156; // - + int IFGT = 157; // - + int IFLE = 158; // - + int IF_ICMPEQ = 159; // - + int IF_ICMPNE = 160; // - + int IF_ICMPLT = 161; // - + int IF_ICMPGE = 162; // - + int IF_ICMPGT = 163; // - + int IF_ICMPLE = 164; // - + int IF_ACMPEQ = 165; // - + int IF_ACMPNE = 166; // - + int GOTO = 167; // - + int JSR = 168; // - + int RET = 169; // visitVarInsn + int TABLESWITCH = 170; // visiTableSwitchInsn + int LOOKUPSWITCH = 171; // visitLookupSwitch + int IRETURN = 172; // visitInsn + int LRETURN = 173; // - + int FRETURN = 174; // - + int DRETURN = 175; // - + int ARETURN = 176; // - + int RETURN = 177; // - + int GETSTATIC = 178; // visitFieldInsn + int PUTSTATIC = 179; // - + int GETFIELD = 180; // - + int PUTFIELD = 181; // - + int INVOKEVIRTUAL = 182; // visitMethodInsn + int INVOKESPECIAL = 183; // - + int INVOKESTATIC = 184; // - + int INVOKEINTERFACE = 185; // - + // int UNUSED = 186; // NOT VISITED + int NEW = 187; // visitTypeInsn + int NEWARRAY = 188; // visitIntInsn + int ANEWARRAY = 189; // visitTypeInsn + int ARRAYLENGTH = 190; // visitInsn + int ATHROW = 191; // - + int CHECKCAST = 192; // visitTypeInsn + int INSTANCEOF = 193; // - + int MONITORENTER = 194; // visitInsn + int MONITOREXIT = 195; // - + // int WIDE = 196; // NOT VISITED + int MULTIANEWARRAY = 197; // visitMultiANewArrayInsn + int IFNULL = 198; // visitJumpInsn + int IFNONNULL = 199; // - + // int GOTO_W = 200; // - + // int JSR_W = 201; // - +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/ws/org/objectweb/asm/Type.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,824 @@ +/* + * Copyright 2005-2009 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2007 INRIA, France Telecom + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.sun.xml.internal.ws.org.objectweb.asm; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; + +/** + * A Java type. This class can be used to make it easier to manipulate type and + * method descriptors. + * + * @author Eric Bruneton + * @author Chris Nokleberg + */ +public class Type { + + /** + * The sort of the <tt>void</tt> type. See {@link #getSort getSort}. + */ + public static final int VOID = 0; + + /** + * The sort of the <tt>boolean</tt> type. See {@link #getSort getSort}. + */ + public static final int BOOLEAN = 1; + + /** + * The sort of the <tt>char</tt> type. See {@link #getSort getSort}. + */ + public static final int CHAR = 2; + + /** + * The sort of the <tt>byte</tt> type. See {@link #getSort getSort}. + */ + public static final int BYTE = 3; + + /** + * The sort of the <tt>short</tt> type. See {@link #getSort getSort}. + */ + public static final int SHORT = 4; + + /** + * The sort of the <tt>int</tt> type. See {@link #getSort getSort}. + */ + public static final int INT = 5; + + /** + * The sort of the <tt>float</tt> type. See {@link #getSort getSort}. + */ + public static final int FLOAT = 6; + + /** + * The sort of the <tt>long</tt> type. See {@link #getSort getSort}. + */ + public static final int LONG = 7; + + /** + * The sort of the <tt>double</tt> type. See {@link #getSort getSort}. + */ + public static final int DOUBLE = 8; + + /** + * The sort of array reference types. See {@link #getSort getSort}. + */ + public static final int ARRAY = 9; + + /** + * The sort of object reference type. See {@link #getSort getSort}. + */ + public static final int OBJECT = 10; + + /** + * The <tt>void</tt> type. + */ + public static final Type VOID_TYPE = new Type(VOID); + + /** + * The <tt>boolean</tt> type. + */ + public static final Type BOOLEAN_TYPE = new Type(BOOLEAN); + + /** + * The <tt>char</tt> type. + */ + public static final Type CHAR_TYPE = new Type(CHAR); + + /** + * The <tt>byte</tt> type. + */ + public static final Type BYTE_TYPE = new Type(BYTE); + + /** + * The <tt>short</tt> type. + */ + public static final Type SHORT_TYPE = new Type(SHORT); + + /** + * The <tt>int</tt> type. + */ + public static final Type INT_TYPE = new Type(INT); + + /** + * The <tt>float</tt> type. + */ + public static final Type FLOAT_TYPE = new Type(FLOAT); + + /** + * The <tt>long</tt> type. + */ + public static final Type LONG_TYPE = new Type(LONG); + + /** + * The <tt>double</tt> type. + */ + public static final Type DOUBLE_TYPE = new Type(DOUBLE); + + // ------------------------------------------------------------------------ + // Fields + // ------------------------------------------------------------------------ + + /** + * The sort of this Java type. + */ + private final int sort; + + /** + * A buffer containing the internal name of this Java type. This field is + * only used for reference types. + */ + private final char[] buf; + + /** + * The offset of the internal name of this Java type in {@link #buf buf}. + * This field is only used for reference types. + */ + private final int off; + + /** + * The length of the internal name of this Java type. This field is only + * used for reference types. + */ + private final int len; + + // ------------------------------------------------------------------------ + // Constructors + // ------------------------------------------------------------------------ + + /** + * Constructs a primitive type. + * + * @param sort the sort of the primitive type to be constructed. + */ + private Type(final int sort) { + this(sort, null, 0, 1); + } + + /** + * Constructs a reference type. + * + * @param sort the sort of the reference type to be constructed. + * @param buf a buffer containing the descriptor of the previous type. + * @param off the offset of this descriptor in the previous buffer. + * @param len the length of this descriptor. + */ + private Type(final int sort, final char[] buf, final int off, final int len) + { + this.sort = sort; + this.buf = buf; + this.off = off; + this.len = len; + } + + /** + * Returns the Java type corresponding to the given type descriptor. + * + * @param typeDescriptor a type descriptor. + * @return the Java type corresponding to the given type descriptor. + */ + public static Type getType(final String typeDescriptor) { + return getType(typeDescriptor.toCharArray(), 0); + } + + /** + * Returns the Java type corresponding to the given internal name. + * + * @param internalName an internal name. + * @return the Java type corresponding to the given internal name. + */ + public static Type getObjectType(final String internalName) { + char[] buf = internalName.toCharArray(); + return new Type(buf[0] == '[' ? ARRAY : OBJECT, buf, 0, buf.length); + } + + /** + * Returns the Java type corresponding to the given class. + * + * @param c a class. + * @return the Java type corresponding to the given class. + */ + public static Type getType(final Class c) { + if (c.isPrimitive()) { + if (c == Integer.TYPE) { + return INT_TYPE; + } else if (c == Void.TYPE) { + return VOID_TYPE; + } else if (c == Boolean.TYPE) { + return BOOLEAN_TYPE; + } else if (c == Byte.TYPE) { + return BYTE_TYPE; + } else if (c == Character.TYPE) { + return CHAR_TYPE; + } else if (c == Short.TYPE) { + return SHORT_TYPE; + } else if (c == Double.TYPE) { + return DOUBLE_TYPE; + } else if (c == Float.TYPE) { + return FLOAT_TYPE; + } else /* if (c == Long.TYPE) */{ + return LONG_TYPE; + } + } else { + return getType(getDescriptor(c)); + } + } + + /** + * Returns the Java types corresponding to the argument types of the given + * method descriptor. + * + * @param methodDescriptor a method descriptor. + * @return the Java types corresponding to the argument types of the given + * method descriptor. + */ + public static Type[] getArgumentTypes(final String methodDescriptor) { + char[] buf = methodDescriptor.toCharArray(); + int off = 1; + int size = 0; + while (true) { + char car = buf[off++]; + if (car == ')') { + break; + } else if (car == 'L') { + while (buf[off++] != ';') { + } + ++size; + } else if (car != '[') { + ++size; + } + } + Type[] args = new Type[size]; + off = 1; + size = 0; + while (buf[off] != ')') { + args[size] = getType(buf, off); + off += args[size].len + (args[size].sort == OBJECT ? 2 : 0); + size += 1; + } + return args; + } + + /** + * Returns the Java types corresponding to the argument types of the given + * method. + * + * @param method a method. + * @return the Java types corresponding to the argument types of the given + * method. + */ + public static Type[] getArgumentTypes(final Method method) { + Class[] classes = method.getParameterTypes(); + Type[] types = new Type[classes.length]; + for (int i = classes.length - 1; i >= 0; --i) { + types[i] = getType(classes[i]); + } + return types; + } + + /** + * Returns the Java type corresponding to the return type of the given + * method descriptor. + * + * @param methodDescriptor a method descriptor. + * @return the Java type corresponding to the return type of the given + * method descriptor. + */ + public static Type getReturnType(final String methodDescriptor) { + char[] buf = methodDescriptor.toCharArray(); + return getType(buf, methodDescriptor.indexOf(')') + 1); + } + + /** + * Returns the Java type corresponding to the return type of the given + * method. + * + * @param method a method. + * @return the Java type corresponding to the return type of the given + * method. + */ + public static Type getReturnType(final Method method) { + return getType(method.getReturnType()); + } + + /** + * Returns the Java type corresponding to the given type descriptor. + * + * @param buf a buffer containing a type descriptor. + * @param off the offset of this descriptor in the previous buffer. + * @return the Java type corresponding to the given type descriptor. + */ + private static Type getType(final char[] buf, final int off) { + int len; + switch (buf[off]) { + case 'V': + return VOID_TYPE; + case 'Z': + return BOOLEAN_TYPE; + case 'C': + return CHAR_TYPE; + case 'B': + return BYTE_TYPE; + case 'S': + return SHORT_TYPE; + case 'I': + return INT_TYPE; + case 'F': + return FLOAT_TYPE; + case 'J': + return LONG_TYPE; + case 'D': + return DOUBLE_TYPE; + case '[': + len = 1; + while (buf[off + len] == '[') { + ++len; + } + if (buf[off + len] == 'L') { + ++len; + while (buf[off + len] != ';') { + ++len; + } + } + return new Type(ARRAY, buf, off, len + 1); + // case 'L': + default: + len = 1; + while (buf[off + len] != ';') { + ++len; + } + return new Type(OBJECT, buf, off + 1, len - 1); + } + } + + // ------------------------------------------------------------------------ + // Accessors + // ------------------------------------------------------------------------ + + /** + * Returns the sort of this Java type. + * + * @return {@link #VOID VOID}, {@link #BOOLEAN BOOLEAN}, + * {@link #CHAR CHAR}, {@link #BYTE BYTE}, {@link #SHORT SHORT}, + * {@link #INT INT}, {@link #FLOAT FLOAT}, {@link #LONG LONG}, + * {@link #DOUBLE DOUBLE}, {@link #ARRAY ARRAY} or + * {@link #OBJECT OBJECT}. + */ + public int getSort() { + return sort; + } + + /** + * Returns the number of dimensions of this array type. This method should + * only be used for an array type. + * + * @return the number of dimensions of this array type. + */ + public int getDimensions() { + int i = 1; + while (buf[off + i] == '[') { + ++i; + } + return i; + } + + /** + * Returns the type of the elements of this array type. This method should + * only be used for an array type. + * + * @return Returns the type of the elements of this array type. + */ + public Type getElementType() { + return getType(buf, off + getDimensions()); + } + + /** + * Returns the name of the class corresponding to this type. + * + * @return the fully qualified name of the class corresponding to this type. + */ + public String getClassName() { + switch (sort) { + case VOID: + return "void"; + case BOOLEAN: + return "boolean"; + case CHAR: + return "char"; + case BYTE: + return "byte"; + case SHORT: + return "short"; + case INT: + return "int"; + case FLOAT: + return "float"; + case LONG: + return "long"; + case DOUBLE: + return "double"; + case ARRAY: + StringBuffer b = new StringBuffer(getElementType().getClassName()); + for (int i = getDimensions(); i > 0; --i) { + b.append("[]"); + } + return b.toString(); + // case OBJECT: + default: + return new String(buf, off, len).replace('/', '.'); + } + } + + /** + * Returns the internal name of the class corresponding to this object or + * array type. The internal name of a class is its fully qualified name (as + * returned by Class.getName(), where '.' are replaced by '/'. This method + * should only be used for an object or array type. + * + * @return the internal name of the class corresponding to this object type. + */ + public String getInternalName() { + return new String(buf, off, len); + } + + // ------------------------------------------------------------------------ + // Conversion to type descriptors + // ------------------------------------------------------------------------ + + /** + * Returns the descriptor corresponding to this Java type. + * + * @return the descriptor corresponding to this Java type. + */ + public String getDescriptor() { + StringBuffer buf = new StringBuffer(); + getDescriptor(buf); + return buf.toString(); + } + + /** + * Returns the descriptor corresponding to the given argument and return + * types. + * + * @param returnType the return type of the method. + * @param argumentTypes the argument types of the method. + * @return the descriptor corresponding to the given argument and return + * types. + */ + public static String getMethodDescriptor( + final Type returnType, + final Type[] argumentTypes) + { + StringBuffer buf = new StringBuffer(); + buf.append('('); + for (int i = 0; i < argumentTypes.length; ++i) { + argumentTypes[i].getDescriptor(buf); + } + buf.append(')'); + returnType.getDescriptor(buf); + return buf.toString(); + } + + /** + * Appends the descriptor corresponding to this Java type to the given + * string buffer. + * + * @param buf the string buffer to which the descriptor must be appended. + */ + private void getDescriptor(final StringBuffer buf) { + switch (sort) { + case VOID: + buf.append('V'); + return; + case BOOLEAN: + buf.append('Z'); + return; + case CHAR: + buf.append('C'); + return; + case BYTE: + buf.append('B'); + return; + case SHORT: + buf.append('S'); + return; + case INT: + buf.append('I'); + return; + case FLOAT: + buf.append('F'); + return; + case LONG: + buf.append('J'); + return; + case DOUBLE: + buf.append('D'); + return; + case ARRAY: + buf.append(this.buf, off, len); + return; + // case OBJECT: + default: + buf.append('L'); + buf.append(this.buf, off, len); + buf.append(';'); + } + } + + // ------------------------------------------------------------------------ + // Direct conversion from classes to type descriptors, + // without intermediate Type objects + // ------------------------------------------------------------------------ + + /** + * Returns the internal name of the given class. The internal name of a + * class is its fully qualified name, as returned by Class.getName(), where + * '.' are replaced by '/'. + * + * @param c an object or array class. + * @return the internal name of the given class. + */ + public static String getInternalName(final Class c) { + return c.getName().replace('.', '/'); + } + + /** + * Returns the descriptor corresponding to the given Java type. + * + * @param c an object class, a primitive class or an array class. + * @return the descriptor corresponding to the given class. + */ + public static String getDescriptor(final Class c) { + StringBuffer buf = new StringBuffer(); + getDescriptor(buf, c); + return buf.toString(); + } + + /** + * Returns the descriptor corresponding to the given constructor. + * + * @param c a {@link Constructor Constructor} object. + * @return the descriptor of the given constructor. + */ + public static String getConstructorDescriptor(final Constructor c) { + Class[] parameters = c.getParameterTypes(); + StringBuffer buf = new StringBuffer(); + buf.append('('); + for (int i = 0; i < parameters.length; ++i) { + getDescriptor(buf, parameters[i]); + } + return buf.append(")V").toString(); + } + + /** + * Returns the descriptor corresponding to the given method. + * + * @param m a {@link Method Method} object. + * @return the descriptor of the given method. + */ + public static String getMethodDescriptor(final Method m) { + Class[] parameters = m.getParameterTypes(); + StringBuffer buf = new StringBuffer(); + buf.append('('); + for (int i = 0; i < parameters.length; ++i) { + getDescriptor(buf, parameters[i]); + } + buf.append(')'); + getDescriptor(buf, m.getReturnType()); + return buf.toString(); + } + + /** + * Appends the descriptor of the given class to the given string buffer. + * + * @param buf the string buffer to which the descriptor must be appended. + * @param c the class whose descriptor must be computed. + */ + private static void getDescriptor(final StringBuffer buf, final Class c) { + Class d = c; + while (true) { + if (d.isPrimitive()) { + char car; + if (d == Integer.TYPE) { + car = 'I'; + } else if (d == Void.TYPE) { + car = 'V'; + } else if (d == Boolean.TYPE) { + car = 'Z'; + } else if (d == Byte.TYPE) { + car = 'B'; + } else if (d == Character.TYPE) { + car = 'C'; + } else if (d == Short.TYPE) { + car = 'S'; + } else if (d == Double.TYPE) { + car = 'D'; + } else if (d == Float.TYPE) { + car = 'F'; + } else /* if (d == Long.TYPE) */{ + car = 'J'; + } + buf.append(car); + return; + } else if (d.isArray()) { + buf.append('['); + d = d.getComponentType(); + } else { + buf.append('L'); + String name = d.getName(); + int len = name.length(); + for (int i = 0; i < len; ++i) { + char car = name.charAt(i); + buf.append(car == '.' ? '/' : car); + } + buf.append(';'); + return; + } + } + } + + // ------------------------------------------------------------------------ + // Corresponding size and opcodes + // ------------------------------------------------------------------------ + + /** + * Returns the size of values of this type. + * + * @return the size of values of this type, i.e., 2 for <tt>long</tt> and + * <tt>double</tt>, and 1 otherwise. + */ + public int getSize() { + return sort == LONG || sort == DOUBLE ? 2 : 1; + } + + /** + * Returns a JVM instruction opcode adapted to this Java type. + * + * @param opcode a JVM instruction opcode. This opcode must be one of ILOAD, + * ISTORE, IALOAD, IASTORE, IADD, ISUB, IMUL, IDIV, IREM, INEG, ISHL, + * ISHR, IUSHR, IAND, IOR, IXOR and IRETURN. + * @return an opcode that is similar to the given opcode, but adapted to + * this Java type. For example, if this type is <tt>float</tt> and + * <tt>opcode</tt> is IRETURN, this method returns FRETURN. + */ + public int getOpcode(final int opcode) { + if (opcode == Opcodes.IALOAD || opcode == Opcodes.IASTORE) { + switch (sort) { + case BOOLEAN: + case BYTE: + return opcode + 5; + case CHAR: + return opcode + 6; + case SHORT: + return opcode + 7; + case INT: + return opcode; + case FLOAT: + return opcode + 2; + case LONG: + return opcode + 1; + case DOUBLE: + return opcode + 3; + // case ARRAY: + // case OBJECT: + default: + return opcode + 4; + } + } else { + switch (sort) { + case VOID: + return opcode + 5; + case BOOLEAN: + case CHAR: + case BYTE: + case SHORT: + case INT: + return opcode; + case FLOAT: + return opcode + 2; + case LONG: + return opcode + 1; + case DOUBLE: + return opcode + 3; + // case ARRAY: + // case OBJECT: + default: + return opcode + 4; + } + } + } + + // ------------------------------------------------------------------------ + // Equals, hashCode and toString + // ------------------------------------------------------------------------ + + /** + * Tests if the given object is equal to this type. + * + * @param o the object to be compared to this type. + * @return <tt>true</tt> if the given object is equal to this type. + */ + public boolean equals(final Object o) { + if (this == o) { + return true; + } + if (!(o instanceof Type)) { + return false; + } + Type t = (Type) o; + if (sort != t.sort) { + return false; + } + if (sort == OBJECT || sort == ARRAY) { + if (len != t.len) { + return false; + } + for (int i = off, j = t.off, end = i + len; i < end; i++, j++) { + if (buf[i] != t.buf[j]) { + return false; + } + } + } + return true; + } + + /** + * Returns a hash code value for this type. + * + * @return a hash code value for this type. + */ + public int hashCode() { + int hc = 13 * sort; + if (sort == OBJECT || sort == ARRAY) { + for (int i = off, end = i + len; i < end; i++) { + hc = 17 * (hc + buf[i]); + } + } + return hc; + } + + /** + * Returns a string representation of this type. + * + * @return the descriptor of this type. + */ + public String toString() { + return getDescriptor(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/ws/protocol/soap/MessageCreationException.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,60 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.xml.internal.ws.protocol.soap; + +import com.sun.xml.internal.ws.api.SOAPVersion; +import com.sun.xml.internal.ws.api.message.ExceptionHasMessage; +import com.sun.xml.internal.ws.api.message.Message; +import com.sun.xml.internal.ws.fault.SOAPFaultBuilder; + +import javax.xml.namespace.QName; + +/** + * This is used to represent Message creation exception when a {@link com.sun.xml.internal.ws.api.pipe.Codec} + * trying to create a {@link Message}. + * + * @author Jitendra Kotamraju + */ +public class MessageCreationException extends ExceptionHasMessage { + + private final SOAPVersion soapVersion; + + public MessageCreationException(SOAPVersion soapVersion, Object... args) { + super("soap.msg.create.err", args); + this.soapVersion = soapVersion; + } + + public String getDefaultResourceBundleName() { + return "com.sun.xml.internal.ws.resources.soap"; + } + + public Message getFaultMessage() { + QName faultCode = soapVersion.faultCodeClient; + return SOAPFaultBuilder.createSOAPFaultMessage( + soapVersion, getLocalizedMessage(), faultCode); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/ws/server/DraconianValidationErrorHandler.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,47 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.xml.internal.ws.server; + +import com.sun.xml.internal.ws.developer.ValidationErrorHandler; +import org.xml.sax.SAXParseException; +import org.xml.sax.SAXException; + +/** + * @author Jitendra Kotamraju + */ +public class DraconianValidationErrorHandler extends ValidationErrorHandler { + public void warning(SAXParseException e) throws SAXException { + throw e; + } + + public void error(SAXParseException e) throws SAXException { + throw e; + } + + public void fatalError(SAXParseException e) throws SAXException { + ; // noop + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/ws/server/JMXAgent.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,87 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * JAXWSServerAgent.java + * + * Created on February 7, 2007, 6:37 PM + */ + +package com.sun.xml.internal.ws.server; + +import com.sun.xml.internal.ws.util.RuntimeVersionMBean; +import com.sun.xml.internal.ws.util.RuntimeVersion; +import com.sun.xml.internal.ws.transport.http.HttpDump; + +import javax.management.ObjectName; +import javax.management.MBeanServer; +import java.lang.management.ManagementFactory; + +/** + * + * @author Jitendra Kotamraju + */ +public class JMXAgent { + + // Platform MBeanServer used to register your MBeans + private final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); + + // Singleton instance + private static JMXAgent singleton; + + /** + * Instantiate and register your MBeans. + */ + public void init() throws Exception { + + RuntimeVersionMBean mbean = new RuntimeVersion(); + ObjectName mbeanName = new ObjectName("com.sun.xml.internal.ws.util:type=RuntimeVersion"); + if (!getMBeanServer().isRegistered(mbeanName)) { + getMBeanServer().registerMBean(mbean, mbeanName); + } + + HttpDump dump = new HttpDump(); + ObjectName dumpName = new ObjectName("com.sun.xml.internal.ws.transport.http:type=HttpDump"); + if (!getMBeanServer().isRegistered(dumpName)) { + getMBeanServer().registerMBean(dump, dumpName); + } + } + + /** + * Returns an agent singleton. + */ + public synchronized static JMXAgent getDefault() throws Exception { + if(singleton == null) { + singleton = new JMXAgent(); + singleton.init(); + } + return singleton; + } + + private MBeanServer getMBeanServer() { + return mbs; + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/ws/server/ServerSchemaValidationTube.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,319 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.xml.internal.ws.server; + +import com.sun.istack.internal.Nullable; +import com.sun.xml.internal.ws.api.WSBinding; +import com.sun.xml.internal.ws.api.pipe.Tube; +import com.sun.xml.internal.ws.api.pipe.TubeCloner; +import com.sun.xml.internal.ws.api.pipe.helper.AbstractTubeImpl; +import com.sun.xml.internal.ws.api.server.SDDocument; +import com.sun.xml.internal.ws.api.server.SDDocumentSource; +import com.sun.xml.internal.ws.api.server.ServiceDefinition; +import com.sun.xml.internal.ws.api.server.WSEndpoint; +import com.sun.xml.internal.ws.util.ByteArrayBuffer; +import com.sun.xml.internal.ws.util.MetadataUtil; +import com.sun.xml.internal.ws.util.pipe.AbstractSchemaValidationTube; +import com.sun.xml.internal.ws.util.xml.MetadataDocument; +import org.w3c.dom.*; +import org.w3c.dom.ls.LSInput; +import org.w3c.dom.ls.LSResourceResolver; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.NamespaceSupport; + +import javax.xml.XMLConstants; +import javax.xml.namespace.QName; +import javax.xml.transform.Source; +import javax.xml.transform.dom.DOMSource; +import javax.xml.validation.Schema; +import javax.xml.validation.SchemaFactory; +import javax.xml.validation.Validator; +import javax.xml.ws.WebServiceException; +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.*; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * {@link Tube} that does the schema validation on the server side. + * + * @author Jitendra Kotamraju + */ +public class ServerSchemaValidationTube extends AbstractSchemaValidationTube { + + private static final Logger LOGGER = Logger.getLogger(ServerSchemaValidationTube.class.getName()); + + //private final ServiceDefinition docs; + private final Schema schema; + private final Validator validator; + + private final boolean noValidation; + + public ServerSchemaValidationTube(WSEndpoint endpoint, WSBinding binding, Tube next) { + super(binding, next); + //docs = endpoint.getServiceDefinition(); + SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); + Source[] sources = getSchemaSources(endpoint.getServiceDefinition()); + for(Source source : sources) { + LOGGER.fine("Constructing validation Schema from = "+source.getSystemId()); + //printDOM((DOMSource)source); + } + if (sources.length != 0) { + noValidation = false; + sf.setResourceResolver(new MetadataResolverImpl(endpoint.getServiceDefinition())); + try { + schema = sf.newSchema(sources); + } catch(SAXException e) { + throw new WebServiceException(e); + } + validator = schema.newValidator(); + } else { + noValidation = true; + schema = null; + validator = null; + } + } + + /** + * Constructs list of schema documents as follows: + * - all <xsd:schema> fragements from all WSDL documents. + * - all schema documents in the application(from WAR etc) + * + * @return list of root schema documents + */ + private Source[] getSchemaSources(ServiceDefinition sd) { + String primary = sd.getPrimary().getURL().toExternalForm(); + MetadataUtil.MetadataResolver mdresolver = new MetadataResolverImpl(sd); + Map<String, SDDocument> docs = MetadataUtil.getMetadataClosure(primary, mdresolver, true); + + List<Source> list = new ArrayList<Source>(); + for(Map.Entry<String, SDDocument> entry : docs.entrySet()) { + SDDocument doc = entry.getValue(); + // Add all xsd:schema fragments from all WSDLs. That should form a closure of schemas. + if (doc.isWSDL()) { + Document dom = createDOM(doc); + // Get xsd:schema node from WSDL's DOM + addSchemaFragmentSource(dom, doc.getURL().toExternalForm(), list); + } else if (doc.isSchema()) { + // If there are multiple schemas with the same targetnamespace, + // JAXP works only with the first one. Above, all schema fragments may have the same targetnamespace, + // and that means it will not include all the schemas. Since we have a list of schemas, just add them. + Document dom = createDOM(doc); + list.add(new DOMSource(dom, doc.getURL().toExternalForm())); + } + } + //addSchemaSource(list); + return list.toArray(new Source[list.size()]) ; + } + + private class MetadataResolverImpl implements MetadataUtil.MetadataResolver, LSResourceResolver { + + Map<String, SDDocument> docs = new HashMap<String, SDDocument>(); + + MetadataResolverImpl(ServiceDefinition sd) { + for(SDDocument doc : sd) { + SDDocument sdi = doc; + docs.put(sdi.getURL().toExternalForm(), sdi); + } + } + + public SDDocument resolveEntity(String systemId) { + SDDocument sdi = docs.get(systemId); + if (sdi == null) { + SDDocumentSource sds; + try { + sds = SDDocumentSource.create(new URL(systemId)); + } catch(MalformedURLException e) { + throw new WebServiceException(e); + } + sdi = MetadataDocument.create(sds, new QName(""), new QName("")); + docs.put(systemId, sdi); + } + return sdi; + } + + public LSInput resolveResource(String type, String namespaceURI, String publicId, final String systemId, final String baseURI) { + LOGGER.fine("type="+type+ " namespaceURI="+namespaceURI+" publicId="+publicId+" systemId="+systemId+" baseURI="+baseURI); + try { + URL base = baseURI == null ? null : new URL(baseURI); + final URL rel = new URL(base, systemId); + final SDDocument doc = docs.get(rel.toExternalForm()); + if (doc != null) { + return new LSInput() { + + public Reader getCharacterStream() { + return null; + } + + public void setCharacterStream(Reader characterStream) { + throw new UnsupportedOperationException(); + } + + public InputStream getByteStream() { + ByteArrayBuffer bab = new ByteArrayBuffer(); + try { + doc.writeTo(null, resolver, bab); + } catch (IOException ioe) { + throw new WebServiceException(ioe); + } + return bab.newInputStream(); + } + + public void setByteStream(InputStream byteStream) { + throw new UnsupportedOperationException(); + } + + public String getStringData() { + return null; + } + + public void setStringData(String stringData) { + throw new UnsupportedOperationException(); + } + + public String getSystemId() { + return rel.toExternalForm(); + } + + public void setSystemId(String systemId) { + throw new UnsupportedOperationException(); + } + + public String getPublicId() { + return null; + } + + public void setPublicId(String publicId) { + throw new UnsupportedOperationException(); + } + + public String getBaseURI() { + return rel.toExternalForm(); + } + + public void setBaseURI(String baseURI) { + throw new UnsupportedOperationException(); + } + + public String getEncoding() { + return null; + } + + public void setEncoding(String encoding) { + throw new UnsupportedOperationException(); + } + + public boolean getCertifiedText() { + return false; + } + + public void setCertifiedText(boolean certifiedText) { + throw new UnsupportedOperationException(); + } + }; + } + } catch(Exception e) { + LOGGER.log(Level.WARNING, "Exception in LSResourceResolver impl", e); + } + LOGGER.fine("Don't know about systemId="+systemId+" baseURI="+baseURI); + return null; + } + + } + + + protected Validator getValidator() { + return validator; + } + + protected boolean isNoValidation() { + return noValidation; + } + + /** + * Recursively visit ancestors and build up {@link org.xml.sax.helpers.NamespaceSupport} oject. + */ + private void buildNamespaceSupport(NamespaceSupport nss, Node node) { + if(node==null || node.getNodeType()!=Node.ELEMENT_NODE) + return; + + buildNamespaceSupport( nss, node.getParentNode() ); + + nss.pushContext(); + NamedNodeMap atts = node.getAttributes(); + for( int i=0; i<atts.getLength(); i++ ) { + Attr a = (Attr)atts.item(i); + if( "xmlns".equals(a.getPrefix()) ) { + nss.declarePrefix( a.getLocalName(), a.getValue() ); + continue; + } + if( "xmlns".equals(a.getName()) ) { + nss.declarePrefix( "", a.getValue() ); + continue; + } + } + } + + /** + * Adds inscope namespaces as attributes to <xsd:schema> fragment nodes. + * + * @param nss namespace context info + * @param elem that is patched with inscope namespaces + */ + private @Nullable void patchDOMFragment(NamespaceSupport nss, Element elem) { + NamedNodeMap atts = elem.getAttributes(); + for( Enumeration en = nss.getPrefixes(); en.hasMoreElements(); ) { + String prefix = (String)en.nextElement(); + + for( int i=0; i<atts.getLength(); i++ ) { + Attr a = (Attr)atts.item(i); + if (!"xmlns".equals(a.getPrefix()) || !a.getLocalName().equals("prefix")) { + LOGGER.fine("Patching with xmlns:"+prefix+"="+nss.getURI(prefix)); + elem.setAttributeNS(XMLConstants.XMLNS_ATTRIBUTE_NS_URI, "xmlns:"+prefix, nss.getURI(prefix)); + } + } + } + } + + + + + protected ServerSchemaValidationTube(ServerSchemaValidationTube that, TubeCloner cloner) { + super(that,cloner); + //this.docs = that.docs; + this.schema = that.schema; + this.validator = schema.newValidator(); + this.noValidation = that.noValidation; + } + + public AbstractTubeImpl copy(TubeCloner cloner) { + return new ServerSchemaValidationTube(this,cloner); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/ws/server/sei/SOAPActionBasedDispatcher.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,76 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.xml.internal.ws.server.sei; + +import com.sun.istack.internal.Nullable; +import com.sun.xml.internal.ws.api.WSBinding; +import com.sun.xml.internal.ws.api.message.Packet; +import com.sun.xml.internal.ws.model.AbstractSEIModelImpl; +import com.sun.xml.internal.ws.model.JavaMethodImpl; + +import javax.xml.namespace.QName; +import java.util.HashMap; +import java.util.Map; + +/** + * An {@link EndpointMethodDispatcher} that uses SOAPAction as the key for dispatching. + * <p/> + * A map of all SOAPAction on the port and the corresponding {@link EndpointMethodHandler} + * is initialized in the constructor. The SOAPAction from the + * request {@link Packet} is used as the key to return the correct handler. + * + * @author Jitendra Kotamraju + */ +final class SOAPActionBasedDispatcher implements EndpointMethodDispatcher { + private final Map<String, EndpointMethodHandler> methodHandlers; + + public SOAPActionBasedDispatcher(AbstractSEIModelImpl model, WSBinding binding, SEIInvokerTube invokerTube) { + // Find if any SOAPAction repeat for operations + Map<String, Integer> unique = new HashMap<String, Integer>(); + for(JavaMethodImpl m : model.getJavaMethods()) { + String soapAction = m.getOperation().getSOAPAction(); + Integer count = unique.get(soapAction); + if (count == null) { + unique.put(soapAction, 1); + } else { + unique.put(soapAction, ++count); + } + } + methodHandlers = new HashMap<String, EndpointMethodHandler>(); + for( JavaMethodImpl m : model.getJavaMethods() ) { + String soapAction = m.getOperation().getSOAPAction(); + // Set up method handlers only for unique SOAPAction values so + // that dispatching happens consistently for a method + if (unique.get(soapAction) == 1) { + methodHandlers.put('"'+soapAction+'"', new EndpointMethodHandler(invokerTube,m,binding)); + } + } + } + + public @Nullable EndpointMethodHandler getEndpointMethodHandler(Packet request) { + return request.soapAction == null ? null : methodHandlers.get(request.soapAction); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/ws/streaming/MtomStreamWriter.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,44 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.xml.internal.ws.streaming; + +import com.sun.xml.internal.ws.message.jaxb.JAXBMessage; +import com.sun.xml.internal.ws.encoding.MtomCodec; + +import javax.xml.bind.attachment.AttachmentMarshaller; +import javax.xml.stream.XMLStreamWriter; + +/** + * A {@link XMLStreamWriter} that used for MTOM encoding may provide its own + * {@link AttachmentMarshaller}. The marshaller could do processing based on + * MTOM threshold, and make decisions about inlining the attachment data or not. + * + * @author Jitendra Kotamraju + * @see JAXBMessage + * @see MtomCodec + */ +public interface MtomStreamWriter { + AttachmentMarshaller getAttachmentMarshaller(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/ws/transport/http/HttpDump.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,40 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.xml.internal.ws.transport.http; + +/** + * @author Jitendra Kotamraju + * + */ +public class HttpDump implements HttpDumpMBean { + public void setDump(boolean dump) { + HttpAdapter.dump = dump; + } + + public boolean getDump() { + return HttpAdapter.dump; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/ws/transport/http/HttpDumpMBean.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,37 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.xml.internal.ws.transport.http; + +/** + * @author Jitendra Kotamraju + */ +public interface HttpDumpMBean { + + public void setDump(boolean dump); + + public boolean getDump(); + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/ws/transport/http/HttpMetadataPublisher.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,59 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.xml.internal.ws.transport.http; + +import com.sun.istack.internal.NotNull; +import com.sun.xml.internal.ws.api.server.EndpointComponent; +import com.sun.xml.internal.ws.api.server.WSEndpoint; + +import java.io.IOException; + +/** + * Intercepts GET HTTP requests to process the requests. + * + * <p> + * {@link HttpAdapter} looks for this SPI in {@link WSEndpoint#getComponentRegistry()} + * to allow components to expose additional information through HTTP. + * + * @author Kohsuke Kawaguchi + * @see EndpointComponent#getSPI(Class) + * @since 2.1.2 + */ +public abstract class HttpMetadataPublisher { + /** + * When {@link HttpAdapter} receives a GET request with a query string + * (which is a convention for metadata requests, such as '?wsdl' or '?xsd=...'), + * then this method is invoked to allow components to intercept the request. + * + * @param adapter + * Adapter that accepted the connection. + * @param connection + * Represents the current connection. + * @return + * true if the request is processed. If false is returned the default processing kicks in. + */ + public abstract boolean handleMetadataRequest(@NotNull HttpAdapter adapter, @NotNull WSHTTPConnection connection) throws IOException; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/ws/util/MetadataUtil.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,92 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.xml.internal.ws.util; + +import com.sun.istack.internal.NotNull; +import com.sun.xml.internal.ws.api.server.SDDocument; +import com.sun.xml.internal.ws.server.SDDocumentImpl; +import org.xml.sax.EntityResolver; + +import java.util.*; + +/** + * WSDL, schema document metadata utility class. + * + * @author Jitendra Kotamraju + */ +public class MetadataUtil { + + /** + * Gets closure of all the referenced documents from the primary document(typically + * the service WSDL). It traverses the WSDL and schema imports and builds a closure + * set of documents. + * + * @param systemId primary wsdl or the any root document + * @param resolver used to get SDDocumentImpl for a document + * @param onlyTopLevelSchemas if true, the imported schemas from a schema would be ignored + * @return all the documents + */ + public static Map<String, SDDocument> getMetadataClosure(@NotNull String systemId, + @NotNull MetadataResolver resolver, boolean onlyTopLevelSchemas) { + Map <String, SDDocument> closureDocs = new HashMap<String, SDDocument>(); + Set<String> remaining = new HashSet<String>(); + remaining.add(systemId); + + while(!remaining.isEmpty()) { + Iterator<String> it = remaining.iterator(); + String current = it.next(); + remaining.remove(current); + + SDDocument currentDoc = resolver.resolveEntity(current); + SDDocument old = closureDocs.put(currentDoc.getURL().toExternalForm(), currentDoc); + assert old == null; + + Set<String> imports = currentDoc.getImports(); + if (!currentDoc.isSchema() || !onlyTopLevelSchemas) { + for(String importedDoc : imports) { + if (closureDocs.get(importedDoc) == null) { + remaining.add(importedDoc); + } + } + } + } + + return closureDocs; + } + + public interface MetadataResolver { + /** + * returns {@link SDDocumentImpl} for the give systemId. It + * parses the document and categorises as WSDL, schema etc. + * The implementation could use a catlog resolver or an entity + * resolver {@link EntityResolver} before parsing. + * + * @param systemId document's systemId + * @return document for the systemId + */ + @NotNull SDDocument resolveEntity(String systemId); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/ws/util/RuntimeVersionMBean.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,43 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + + + +package com.sun.xml.internal.ws.util; + +import javax.management.*; +import com.sun.xml.internal.ws.util.RuntimeVersion; + +/** + * @author Jitendra Kotamraju + */ +public interface RuntimeVersionMBean { + + /** + * Get JAX-WS runtime version + */ + public String getVersion(); + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/ws/util/pipe/AbstractSchemaValidationTube.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,261 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.xml.internal.ws.util.pipe; + +import com.sun.istack.internal.NotNull; +import com.sun.istack.internal.Nullable; +import com.sun.xml.internal.ws.api.WSBinding; +import com.sun.xml.internal.ws.api.message.Message; +import com.sun.xml.internal.ws.api.message.Packet; +import com.sun.xml.internal.ws.api.pipe.NextAction; +import com.sun.xml.internal.ws.api.pipe.Tube; +import com.sun.xml.internal.ws.api.pipe.TubeCloner; +import com.sun.xml.internal.ws.api.pipe.helper.AbstractFilterTubeImpl; +import com.sun.xml.internal.ws.api.server.DocumentAddressResolver; +import com.sun.xml.internal.ws.api.server.SDDocument; +import com.sun.xml.internal.ws.developer.SchemaValidationFeature; +import com.sun.xml.internal.ws.developer.ValidationErrorHandler; +import com.sun.xml.internal.ws.util.ByteArrayBuffer; +import com.sun.xml.internal.ws.util.xml.XmlUtil; +import com.sun.xml.internal.ws.wsdl.parser.WSDLConstants; +import org.w3c.dom.*; +import org.xml.sax.helpers.NamespaceSupport; + +import javax.xml.XMLConstants; +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.DOMResult; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; +import javax.xml.transform.stream.StreamSource; +import javax.xml.validation.Validator; +import javax.xml.ws.WebServiceException; +import java.io.IOException; +import java.util.Enumeration; +import java.util.List; +import java.util.logging.Logger; + +/** + * {@link Tube} that does the schema validation. + * + * @author Jitendra Kotamraju + */ +public abstract class AbstractSchemaValidationTube extends AbstractFilterTubeImpl { + + private static final Logger LOGGER = Logger.getLogger(AbstractSchemaValidationTube.class.getName()); + + protected final WSBinding binding; + protected final SchemaValidationFeature feature; + protected final DocumentAddressResolver resolver = new ValidationDocumentAddressResolver(); + + public AbstractSchemaValidationTube(WSBinding binding, Tube next) { + super(next); + this.binding = binding; + feature = binding.getFeature(SchemaValidationFeature.class); + } + + protected AbstractSchemaValidationTube(AbstractSchemaValidationTube that, TubeCloner cloner) { + super(that, cloner); + this.binding = that.binding; + this.feature = that.feature; + } + + protected abstract Validator getValidator(); + + protected abstract boolean isNoValidation(); + + private static class ValidationDocumentAddressResolver implements DocumentAddressResolver { + + @Nullable + public String getRelativeAddressFor(@NotNull SDDocument current, @NotNull SDDocument referenced) { + LOGGER.fine("Current = "+current.getURL()+" resolved relative="+referenced.getURL()); + return referenced.getURL().toExternalForm(); + } + } + + protected Document createDOM(SDDocument doc) { + // Get infoset + ByteArrayBuffer bab = new ByteArrayBuffer(); + try { + doc.writeTo(null, resolver, bab); + } catch (IOException ioe) { + throw new WebServiceException(ioe); + } + + // Convert infoset to DOM + Transformer trans = XmlUtil.newTransformer(); + Source source = new StreamSource(bab.newInputStream(), null); //doc.getURL().toExternalForm()); + DOMResult result = new DOMResult(); + try { + trans.transform(source, result); + } catch(TransformerException te) { + throw new WebServiceException(te); + } + return (Document)result.getNode(); + } + + + /** + * Locates xsd:schema elements in the WSDL and creates DOMSource and adds them to the list + * + * @param doc WSDL document + * @param systemId systemId for WSDL document + * @param list xsd:schema DOMSource list + */ + protected @Nullable void addSchemaFragmentSource(Document doc, String systemId, List<Source> list) { + + Element e = doc.getDocumentElement(); + assert e.getNamespaceURI().equals(WSDLConstants.NS_WSDL); + assert e.getLocalName().equals("definitions"); + + NodeList typesList = e.getElementsByTagNameNS(WSDLConstants.NS_WSDL, "types"); + for(int i=0; i < typesList.getLength(); i++) { + NodeList schemaList = ((Element)typesList.item(i)).getElementsByTagNameNS(WSDLConstants.NS_XMLNS, "schema"); + for(int j=0; j < schemaList.getLength(); j++) { + Element elem = (Element)schemaList.item(j); + NamespaceSupport nss = new NamespaceSupport(); + buildNamespaceSupport(nss, elem); + patchDOMFragment(nss, elem); + list.add(new DOMSource(elem, systemId+"#schema"+j)); + } + } + } + + + /** + * Recursively visit ancestors and build up {@link org.xml.sax.helpers.NamespaceSupport} oject. + */ + private void buildNamespaceSupport(NamespaceSupport nss, Node node) { + if(node==null || node.getNodeType()!=Node.ELEMENT_NODE) + return; + + buildNamespaceSupport( nss, node.getParentNode() ); + + nss.pushContext(); + NamedNodeMap atts = node.getAttributes(); + for( int i=0; i<atts.getLength(); i++ ) { + Attr a = (Attr)atts.item(i); + if( "xmlns".equals(a.getPrefix()) ) { + nss.declarePrefix( a.getLocalName(), a.getValue() ); + continue; + } + if( "xmlns".equals(a.getName()) ) { + nss.declarePrefix( "", a.getValue() ); + continue; + } + } + } + + /** + * Adds inscope namespaces as attributes to <xsd:schema> fragment nodes. + * + * @param nss namespace context info + * @param elem that is patched with inscope namespaces + */ + private @Nullable void patchDOMFragment(NamespaceSupport nss, Element elem) { + NamedNodeMap atts = elem.getAttributes(); + for( Enumeration en = nss.getPrefixes(); en.hasMoreElements(); ) { + String prefix = (String)en.nextElement(); + + for( int i=0; i<atts.getLength(); i++ ) { + Attr a = (Attr)atts.item(i); + if (!"xmlns".equals(a.getPrefix()) || !a.getLocalName().equals("prefix")) { + LOGGER.fine("Patching with xmlns:"+prefix+"="+nss.getURI(prefix)); + elem.setAttributeNS(XMLConstants.XMLNS_ATTRIBUTE_NS_URI, "xmlns:"+prefix, nss.getURI(prefix)); + } + } + } + } + + @Override + public NextAction processRequest(Packet request) { + if (isNoValidation() || !request.getMessage().hasPayload() || request.getMessage().isFault()) { + return super.processRequest(request); + } + doProcess(request); + return super.processRequest(request); + } + + @Override + public NextAction processResponse(Packet response) { + if (isNoValidation() || response.getMessage() == null || !response.getMessage().hasPayload() || response.getMessage().isFault()) { + return super.processResponse(response); + } + doProcess(response); + return super.processResponse(response); + } + + private void doProcess(Packet packet) { + getValidator().reset(); + Class<? extends ValidationErrorHandler> handlerClass = feature.getErrorHandler(); + ValidationErrorHandler handler; + try { + handler = handlerClass.newInstance(); + } catch(Exception e) { + throw new WebServiceException(e); + } + handler.setPacket(packet); + getValidator().setErrorHandler(handler); + Message msg = packet.getMessage().copy(); + Source source = msg.readPayloadAsSource(); + try { + // Validator javadoc allows ONLY SAX, and DOM Sources + // But the impl seems to handle all kinds. + getValidator().validate(source); + } catch(Exception e) { + throw new WebServiceException(e); + } + } + + protected DOMSource toDOMSource(Source source) { + if (source instanceof DOMSource) { + return (DOMSource)source; + } + Transformer trans = XmlUtil.newTransformer(); + DOMResult result = new DOMResult(); + try { + trans.transform(source, result); + } catch(TransformerException te) { + throw new WebServiceException(te); + } + return new DOMSource(result.getNode()); + } + + protected static void printDOM(DOMSource src) { + try { + ByteArrayBuffer bos = new ByteArrayBuffer(); + StreamResult sr = new StreamResult(bos ); + Transformer trans = TransformerFactory.newInstance().newTransformer(); + trans.transform(src, sr); + LOGGER.info("**** src ******"+bos.toString()); + bos.close(); + } catch(Exception e) { + e.printStackTrace(); + } + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/ws/util/xml/MetadataDocument.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,317 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.xml.internal.ws.util.xml; + +import com.sun.xml.internal.ws.api.server.*; +import com.sun.xml.internal.ws.api.streaming.XMLStreamWriterFactory; +import com.sun.xml.internal.ws.streaming.XMLStreamReaderUtil; +import com.sun.xml.internal.ws.util.RuntimeVersion; +import com.sun.xml.internal.ws.wsdl.parser.ParserUtil; +import com.sun.xml.internal.ws.wsdl.parser.WSDLConstants; +import com.sun.xml.internal.ws.server.ServerRtException; + +import javax.xml.namespace.QName; +import javax.xml.stream.*; +import javax.xml.ws.WebServiceException; +import java.io.IOException; +import java.io.OutputStream; +import java.net.URL; +import java.util.HashSet; +import java.util.Set; + +/** + * {@link com.sun.xml.internal.ws.api.server.SDDocument} implmentation. + * + * <p> + * This extends from {@link com.sun.xml.internal.ws.api.server.SDDocumentSource} so that + * JAX-WS server runtime code can use {@link com.sun.xml.internal.ws.api.server.SDDocument} + * as {@link com.sun.xml.internal.ws.api.server.SDDocumentSource}. + * + * @author Kohsuke Kawaguchi + * @author Jitendra Kotamraju + */ +public class MetadataDocument extends SDDocumentSource implements SDDocument { + + private static final String NS_XSD = "http://www.w3.org/2001/XMLSchema"; + private static final QName SCHEMA_INCLUDE_QNAME = new QName(NS_XSD, "include"); + private static final QName SCHEMA_IMPORT_QNAME = new QName(NS_XSD, "import"); + private static final QName SCHEMA_REDEFINE_QNAME = new QName(NS_XSD, "redefine"); + private static final String VERSION_COMMENT = + " Published by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is "+RuntimeVersion.VERSION+". "; + + /** + * Creates {@link com.sun.xml.internal.ws.api.server.SDDocument} from {@link com.sun.xml.internal.ws.api.server.SDDocumentSource}. + * @param src WSDL document infoset + * @param serviceName wsdl:service name + * @param portTypeName + * The information about the port of {@link com.sun.xml.internal.ws.api.server.WSEndpoint} to which this document is built for. + * These values are used to determine which document is the concrete and abstract WSDLs + * for this endpoint. + * + * @return null + * Always non-null. + */ + public static SDDocument create(SDDocumentSource src, QName serviceName, QName portTypeName) { + URL systemId = src.getSystemId(); + + try { + // RuntimeWSDLParser parser = new RuntimeWSDLParser(null); + XMLStreamReader reader = src.read(); + try { + XMLStreamReaderUtil.nextElementContent(reader); + + QName rootName = reader.getName(); + if(rootName.equals(WSDLConstants.QNAME_SCHEMA)) { + String tns = ParserUtil.getMandatoryNonEmptyAttribute(reader, WSDLConstants.ATTR_TNS); + Set<String> importedDocs = new HashSet<String>(); + while (XMLStreamReaderUtil.nextContent(reader) != XMLStreamConstants.END_DOCUMENT) { + if (reader.getEventType() != XMLStreamConstants.START_ELEMENT) + continue; + QName name = reader.getName(); + if (SCHEMA_INCLUDE_QNAME.equals(name) || SCHEMA_IMPORT_QNAME.equals(name) || + SCHEMA_REDEFINE_QNAME.equals(name)) { + String importedDoc = reader.getAttributeValue(null, "schemaLocation"); + if (importedDoc != null) { + importedDocs.add(new URL(src.getSystemId(), importedDoc).toString()); + } + } + } + return new SchemaImpl(rootName,systemId,src,tns,importedDocs); + } else if (rootName.equals(WSDLConstants.QNAME_DEFINITIONS)) { + String tns = ParserUtil.getMandatoryNonEmptyAttribute(reader, WSDLConstants.ATTR_TNS); + + boolean hasPortType = false; + boolean hasService = false; + Set<String> importedDocs = new HashSet<String>(); + Set<QName> allServices = new HashSet<QName>(); + + // if WSDL, parse more + while (XMLStreamReaderUtil.nextContent(reader) != XMLStreamConstants.END_DOCUMENT) { + if(reader.getEventType() != XMLStreamConstants.START_ELEMENT) + continue; + + QName name = reader.getName(); + if (WSDLConstants.QNAME_PORT_TYPE.equals(name)) { + String pn = ParserUtil.getMandatoryNonEmptyAttribute(reader, WSDLConstants.ATTR_NAME); + if (portTypeName != null) { + if(portTypeName.getLocalPart().equals(pn)&&portTypeName.getNamespaceURI().equals(tns)) { + hasPortType = true; + } + } + } else if (WSDLConstants.QNAME_SERVICE.equals(name)) { + String sn = ParserUtil.getMandatoryNonEmptyAttribute(reader, WSDLConstants.ATTR_NAME); + QName sqn = new QName(tns,sn); + allServices.add(sqn); + if(serviceName.equals(sqn)) { + hasService = true; + } + } else if (WSDLConstants.QNAME_IMPORT.equals(name)) { + String importedDoc = reader.getAttributeValue(null, "location"); + if (importedDoc != null) { + importedDocs.add(new URL(src.getSystemId(), importedDoc).toString()); + } + } else if (SCHEMA_INCLUDE_QNAME.equals(name) || SCHEMA_IMPORT_QNAME.equals(name) || + SCHEMA_REDEFINE_QNAME.equals(name)) { + String importedDoc = reader.getAttributeValue(null, "schemaLocation"); + if (importedDoc != null) { + importedDocs.add(new URL(src.getSystemId(), importedDoc).toString()); + } + } + } + return new WSDLImpl( + rootName,systemId,src,tns,hasPortType,hasService,importedDocs,allServices); + } else { + return new MetadataDocument(rootName,systemId,src); + } + } finally { + reader.close(); + } + } catch (WebServiceException e) { + throw new ServerRtException("runtime.parser.wsdl", systemId,e); + } catch (IOException e) { + throw new ServerRtException("runtime.parser.wsdl", systemId,e); + } catch (XMLStreamException e) { + throw new ServerRtException("runtime.parser.wsdl", systemId,e); + } + } + + + private final QName rootName; + private final SDDocumentSource source; + + /** + * The original system ID of this document. + * + * When this document contains relative references to other resources, + * this field is used to find which {@link com.sun.xml.internal.ws.server.SDDocumentImpl} it refers to. + * + * Must not be null. + */ + private final URL url; + private final Set<String> imports; + + protected MetadataDocument(QName rootName, URL url, SDDocumentSource source) { + this(rootName, url, source, new HashSet<String>()); + } + + protected MetadataDocument(QName rootName, URL url, SDDocumentSource source, Set<String> imports) { + assert url!=null; + this.rootName = rootName; + this.source = source; + this.url = url; + this.imports = imports; + } + + public QName getRootName() { + return rootName; + } + + public boolean isWSDL() { + return false; + } + + public boolean isSchema() { + return false; + } + + public URL getURL() { + return url; + } + + public XMLStreamReader read(XMLInputFactory xif) throws IOException, XMLStreamException { + return source.read(xif); + } + + public XMLStreamReader read() throws IOException, XMLStreamException { + return source.read(); + } + + public URL getSystemId() { + return url; + } + + public Set<String> getImports() { + return imports; + } + + public void writeTo(PortAddressResolver portAddressResolver, DocumentAddressResolver resolver, OutputStream os) throws IOException { + XMLStreamWriter w = null; + try { + //generate the WSDL with utf-8 encoding and XML version 1.0 + w = XMLStreamWriterFactory.create(os, "UTF-8"); + w.writeStartDocument("UTF-8", "1.0"); + writeTo(portAddressResolver,resolver,w); + w.writeEndDocument(); + } catch (XMLStreamException e) { + IOException ioe = new IOException(e.getMessage()); + ioe.initCause(e); + throw ioe; + } finally { + try { + if (w != null) + w.close(); + } catch (XMLStreamException e) { + IOException ioe = new IOException(e.getMessage()); + ioe.initCause(e); + throw ioe; + } + } + } + + public void writeTo(PortAddressResolver portAddressResolver, DocumentAddressResolver resolver, XMLStreamWriter out) throws XMLStreamException, IOException { + + XMLStreamReader xsr = source.read(); + try { + out.writeComment(VERSION_COMMENT); + new XMLStreamReaderToXMLStreamWriter().bridge(xsr, out); + } finally { + xsr.close(); + } + } + + + /** + * {@link com.sun.xml.internal.ws.api.server.SDDocument.Schema} implementation. + * + * @author Kohsuke Kawaguchi + */ + private static final class SchemaImpl extends MetadataDocument implements Schema { + private final String targetNamespace; + + public SchemaImpl(QName rootName, URL url, SDDocumentSource source, String targetNamespace, + Set<String> imports) { + super(rootName, url, source, imports); + this.targetNamespace = targetNamespace; + } + + public String getTargetNamespace() { + return targetNamespace; + } + + public boolean isSchema() { + return true; + } + } + + + private static final class WSDLImpl extends MetadataDocument implements WSDL { + private final String targetNamespace; + private final boolean hasPortType; + private final boolean hasService; + private final Set<QName> allServices; + + public WSDLImpl(QName rootName, URL url, SDDocumentSource source, String targetNamespace, boolean hasPortType, + boolean hasService, Set<String> imports, Set<QName> allServices) { + super(rootName, url, source, imports); + this.targetNamespace = targetNamespace; + this.hasPortType = hasPortType; + this.hasService = hasService; + this.allServices = allServices; + } + + public String getTargetNamespace() { + return targetNamespace; + } + + public boolean hasPortType() { + return hasPortType; + } + + public boolean hasService() { + return hasService; + } + + public Set<QName> getAllServices() { + return allServices; + } + + public boolean isWSDL() { + return true; + } + } + + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/xml/internal/ws/wsdl/parser/W3CAddressingMetadataWSDLParserExtension.java Thu Aug 06 00:33:48 2009 +0100 @@ -0,0 +1,106 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.xml.internal.ws.wsdl.parser; + +import com.sun.xml.internal.ws.api.model.wsdl.*; +import com.sun.xml.internal.ws.model.wsdl.WSDLOperationImpl; +import com.sun.xml.internal.ws.model.wsdl.WSDLBoundPortTypeImpl; +import javax.xml.stream.XMLStreamReader; +import javax.xml.namespace.QName; + +/** + * W3C WS-Addressing Runtime WSDL parser extension that parses + * WS-Addressing Metadata wsdl extensibility elements + * This mainly reads wsam:Action element on input/output/fault messages in wsdl. + * + * @author Rama Pulavarthi + */ +public class W3CAddressingMetadataWSDLParserExtension extends W3CAddressingWSDLParserExtension { + + String METADATA_WSDL_EXTN_NS = "http://www.w3.org/2007/05/addressing/metadata"; + QName METADATA_WSDL_ACTION_TAG = new QName(METADATA_WSDL_EXTN_NS, "Action", "wsam"); + + @Override + public boolean bindingElements(WSDLBoundPortType binding, XMLStreamReader reader) { + return false; + } + + @Override + public boolean portElements(WSDLPort port, XMLStreamReader reader) { + return false; + } + + @Override + public boolean bindingOperationElements(WSDLBoundOperation operation, XMLStreamReader reader) { + return false; + } + + @Override + public boolean portTypeOperationInput(WSDLOperation o, XMLStreamReader reader) { + WSDLOperationImpl impl = (WSDLOperationImpl) o; + + String action = ParserUtil.getAttribute(reader, METADATA_WSDL_ACTION_TAG); + if (action != null) { + impl.getInput().setAction(action); + impl.getInput().setDefaultAction(false); + } + + return false; + } + + @Override + public boolean portTypeOperationOutput(WSDLOperation o, XMLStreamReader reader) { + WSDLOperationImpl impl = (WSDLOperationImpl) o; + + String action = ParserUtil.getAttribute(reader, METADATA_WSDL_ACTION_TAG); + if (action != null) { + impl.getOutput().setAction(action); + } + + return false; + } + + @Override + public boolean portTypeOperationFault(WSDLOperation o, XMLStreamReader reader) { + WSDLOperationImpl impl = (WSDLOperationImpl) o; + + String action = ParserUtil.getAttribute(reader, METADATA_WSDL_ACTION_TAG); + if (action != null) { + String name = ParserUtil.getMandatoryNonEmptyAttribute(reader, "name"); + impl.getFaultActionMap().put(name, action); + } + + return false; + } + + @Override + protected void patchAnonymousDefault(WSDLBoundPortTypeImpl binding) { + } + + @Override + protected String getNamespaceURI() { + return METADATA_WSDL_EXTN_NS; + } +}