diff --git a/jaxws/README b/jaxws/README index f5462658425..4d65125b34c 100644 --- a/jaxws/README +++ b/jaxws/README @@ -17,9 +17,3 @@ Simple Build Instructions: "dist" directory. Help information is available by running "ant -projecthelp" or "make help". -Drop Repository: - This repository builds sources from a created "drop" source directory. - These files will normally be copied from a shared directory area or - downloaded from a public website. - See the ant build script (build.xml) for more details. - diff --git a/jaxws/build-defs.xml b/jaxws/build-defs.xml deleted file mode 100644 index 49c9d817d67..00000000000 --- a/jaxws/build-defs.xml +++ /dev/null @@ -1,150 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/jaxws/build-drop-template.xml b/jaxws/build-drop-template.xml deleted file mode 100644 index a593b428d13..00000000000 --- a/jaxws/build-drop-template.xml +++ /dev/null @@ -1,144 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Checksum on file ${@DROP@.bundle.copy} is - ${@DROP@.bundle.md5.checksum.is}, not ${@DROP@.bundle.md5.checksum} - - - - - - - - - - - - - - - - - - - diff --git a/jaxws/build.properties b/jaxws/build.properties index a468f8175fc..9240acc57f8 100644 --- a/jaxws/build.properties +++ b/jaxws/build.properties @@ -23,10 +23,6 @@ # questions. # -# Base locations where bundles are located -slashjava=/java -drops.dir=${slashjava}/devtools/share/jdk8-drops - # This is the JDK used to build and run the bootstrap version of javac. # The bootstrap javac is used to compile both boostrap versions of the # other tools, and product versions of all the tools. @@ -68,15 +64,6 @@ dist.lib.dir=${dist.dir}/lib dist.classes.jar=${dist.lib.dir}/classes.jar dist.src.zip=${dist.lib.dir}/src.zip -# Where all drop sources get placed when downloaded and unzipped -drop.expanded.dir=${output.dir}/drop - -# Location if the sources were included already -drop.included.dir=./drop_included - -# Where patches to drop bundle sources live -patches.dir=patches - # Sanity information sanity.info= Sanity Settings:${line.separator}\ ant.home=${ant.home}${line.separator}\ @@ -100,28 +87,6 @@ sanity.info= Sanity Settings:${line.separator}\ output.dir=${output.dir}${line.separator}\ build.dir=${build.dir}${line.separator}\ dist.dir=${dist.dir}${line.separator}\ - drop.dir=${drop.dir}${line.separator}\ - drops.dir=${drops.dir}${line.separator}\ -${line.separator} - -# Failure messages when source cannot be found on the file system -failed.nourl.src.message=\ -ERROR: Cannot find source for project ${ant.project.name}.\ -${line.separator}${line.separator}\ -HINT: Try setting drops.dir to indicate where the bundles can be found, \ -or try setting the ant property allow.downloads=true to download the bundle from the URL.\ -${line.separator}\ -e.g. ant -Dallow.downloads=true -OR- ant -Ddrops.dir=some_directory \ -${line.separator} - -# Failure message when source cannot be downloaded -failed.url.src.message=\ -ERROR: Cannot find source for project ${ant.project.name}.\ -${line.separator}${line.separator}\ -HINT: Try setting drops.dir to indicate where the bundles can be found, \ -or try checking the URL with your browser.\ -${line.separator}\ -e.g. ant -Ddrops.dir=some_directory \ ${line.separator} #------------------------------------------------------------ diff --git a/jaxws/build.xml b/jaxws/build.xml index 818c939478f..afea552e3b8 100644 --- a/jaxws/build.xml +++ b/jaxws/build.xml @@ -36,9 +36,6 @@ javac.debug - true or false for debug classfiles javac.target - classfile version target javac.source - source version - drops.dir - directory that holds source drop bundles - allow.download - permit downloads from public url (default is false) - (used if bundles not found in drops.dir) Run 'make help' for help using the Makefile. @@ -46,15 +43,12 @@ - - - - - - - + + + + + + @@ -79,14 +73,20 @@ unless="javac.jar.exists"> + + + + + + + depends="init"> @@ -97,14 +97,39 @@ - + + + + + + + + + + + + + + + + + + + @@ -112,7 +137,7 @@ depends="compile, -build-setup"> + depends="init"> + depends="init, dist"> - - - - - - - - @@ -163,7 +178,6 @@ - diff --git a/jaxws/make/Makefile b/jaxws/make/Makefile index b2574d7d6da..12f13281abf 100644 --- a/jaxws/make/Makefile +++ b/jaxws/make/Makefile @@ -91,23 +91,6 @@ else endif endif -# Do we have the drops already downloaded? -# Check ALT_DROPS_DIR for a full path first, -# before trying to use the devtools path, -# either via ALT_JDK_DEVTOOLS_DIR or /java/devtools. -ifdef ALT_DROPS_DIR - DROPS_DIR = $(ALT_DROPS_DIR) -else - ifdef ALT_JDK_DEVTOOLS_DIR - DROPS_DIR = $(ALT_JDK_DEVTOOLS_DIR)/share/jdk8-drops - else - DROPS_DIR = $(_SLASHJAVA)/devtools/share/jdk8-drops - endif -endif - -# Add in path to drops already downloaded -ANT_OPTIONS += -Ddrops.dir=$(DROPS_DIR) - ifdef ALT_OUTPUTDIR OUTPUTDIR = $(ALT_OUTPUTDIR) ANT_OPTIONS += -Doutput.dir=$(ALT_OUTPUTDIR) @@ -144,13 +127,17 @@ endif default: all # All ant targets of interest -ANT_TARGETS = all source drop_included build dist clobber clean sanity +ANT_TARGETS = all build dist clobber clean sanity # Create a make target for each $(ANT_TARGETS): cd .. && $(ANT_JAVA_HOME) $(ANT) $(ANT_OPTIONS) -version cd .. && $(ANT_JAVA_HOME) $(ANT) $(ANT_OPTIONS) $@ +# Just for compat reasons, delete in future. +drop_included: +source: + # Help target define helpenvline @echo " $1";echo " $2" @@ -164,8 +151,6 @@ help: @echo " $(ANT_TARGETS)" @echo " " @echo " Environment or command line variables (all optional):" - $(call helpenvline, ALT_DROPS_DIR,\ - "Directory that contains the drop source bundles i.e. drops.dir") $(call helpenvline, ALT_BOOTDIR,\ "JAVA_HOME to use when running ant") $(call helpenvline, ALT_LANGTOOLS_DIST,\ diff --git a/jaxws/make/scripts/update_src.sh b/jaxws/make/scripts/update_src.sh new file mode 100644 index 00000000000..6a642fb99f6 --- /dev/null +++ b/jaxws/make/scripts/update_src.sh @@ -0,0 +1,90 @@ +# +# Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +# This script was used to copy the former drop source bundle source into +# the repository. Exists as a form of documentation. + +curdir="`(cd . && pwd)`" + +# Whitespace normalizer script is in the top repository. +normalizer="perl ${curdir}/../make/scripts/normalizer.pl" + +# Locations for bundle and root of source tree +tmp=/tmp +srcroot=${curdir}/src +mkdir -p ${srcroot} + +# Bundle information +drops_dir="/java/devtools/share/jdk8-drops" +url1="http://download.java.net/glassfish/components/jax-ws/openjdk/jdk8" +bundle1="jdk8-jaxws-2_2-SNAPSHOT-2012_01_11-patched.zip" +srcdir1="${srcroot}/share/jaxws_classes" +url2="http://download.java.net/glassfish/components/jax-ws/openjdk/jdk8" +bundle2="jdk8-jaf-2011_07_22.zip" +srcdir2="${srcroot}/share/jaf_classes" + +# Function to get a bundle and explode it and normalize the source files. +getBundle() # drops_dir url bundlename bundledestdir srcrootdir +{ + # Get the bundle from drops_dir or downloaded + mkdir -p $4 + rm -f $4/$3 + if [ -f $1/$3 ] ; then + echo "Copy over bundle: $1/$3" + cp $1/$3 $4 + else + echo "Downloading bundle: $2/$3" + (cd $4 && wget $2/$3) + fi + # Fail if it does not exist + if [ ! -f $4/$3 ] ; then + echo "ERROR: Could not get $3" + exit 1 + fi + # Wipe it out completely + echo "Cleaning up $5" + rm -f -r $5 + mkdir -p $5 + echo "Unzipping $4/$3" + ( cd $5 && unzip -q $4/$3 && mv src/* . && rmdir src && rm LICENSE ) + # Run whitespace normalizer + echo "Normalizing the sources in $5" + ( cd $5 && ${normalizer} . ) + # Delete the bundle and leftover files + rm -f $4/$3 $5/filelist +} + +# Process the bundles. +getBundle "${drops_dir}" "${url1}" "${bundle1}" ${tmp} ${srcdir1} +getBundle "${drops_dir}" "${url2}" "${bundle2}" ${tmp} ${srcdir2} +echo "Completed bundle extraction." +echo " " + +# Appropriate Mercurial commands needed to run: +echo "Run: hg addremove src" +echo "Run: ksh ../make/scripts/webrev.ksh -N -o ${HOME}/webrev" +echo "Get reviewer, get CR, then..." +echo "Run: hg commit" + diff --git a/jaxws/patches/jaxws_src/README b/jaxws/patches/jaxws_src/README deleted file mode 100644 index 644dff0223b..00000000000 --- a/jaxws/patches/jaxws_src/README +++ /dev/null @@ -1,5 +0,0 @@ - -This directory will hold any patches that need to be applied to the drop files. - -The patch order is defined in the ant build script properties. - diff --git a/jaxws/src/share/jaf_classes/META-INF/mailcap.default b/jaxws/src/share/jaf_classes/META-INF/mailcap.default new file mode 100644 index 00000000000..542de7deb93 --- /dev/null +++ b/jaxws/src/share/jaf_classes/META-INF/mailcap.default @@ -0,0 +1,7 @@ +# +# This is a very simple 'mailcap' file +# +image/gif;; x-java-view=com.sun.activation.viewers.ImageViewer +image/jpeg;; x-java-view=com.sun.activation.viewers.ImageViewer +text/*;; x-java-view=com.sun.activation.viewers.TextViewer +text/*;; x-java-edit=com.sun.activation.viewers.TextEditor diff --git a/jaxws/src/share/jaf_classes/META-INF/mimetypes.default b/jaxws/src/share/jaf_classes/META-INF/mimetypes.default new file mode 100644 index 00000000000..0c22eb2efb8 --- /dev/null +++ b/jaxws/src/share/jaf_classes/META-INF/mimetypes.default @@ -0,0 +1,24 @@ +# +# A simple, old format, mime.types file +# +text/html html htm HTML HTM +text/plain txt text TXT TEXT +image/gif gif GIF +image/ief ief +image/jpeg jpeg jpg jpe JPG +image/tiff tiff tif +image/x-xwindowdump xwd +application/postscript ai eps ps +application/rtf rtf +application/x-tex tex +application/x-texinfo texinfo texi +application/x-troff t tr roff +audio/basic au +audio/midi midi mid +audio/x-aifc aifc +audio/x-aiff aif aiff +audio/x-mpeg mpeg mpg +audio/x-wav wav +video/mpeg mpeg mpg mpe +video/quicktime qt mov +video/x-msvideo avi diff --git a/jaxws/src/share/jaf_classes/com/sun/activation/registries/LogSupport.java b/jaxws/src/share/jaf_classes/com/sun/activation/registries/LogSupport.java new file mode 100644 index 00000000000..97d381d2b6a --- /dev/null +++ b/jaxws/src/share/jaf_classes/com/sun/activation/registries/LogSupport.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.activation.registries; + +import java.io.*; +import java.util.logging.*; + +/** + * Logging related methods. + */ +public class LogSupport { + private static boolean debug = false; + private static Logger logger; + private static final Level level = Level.FINE; + + static { + try { + debug = Boolean.getBoolean("javax.activation.debug"); + } catch (Throwable t) { + // ignore any errors + } + logger = Logger.getLogger("javax.activation"); + } + + /** + * Constructor. + */ + private LogSupport() { + // private constructor, can't create instances + } + + public static void log(String msg) { + if (debug) + System.out.println(msg); + logger.log(level, msg); + } + + public static void log(String msg, Throwable t) { + if (debug) + System.out.println(msg + "; Exception: " + t); + logger.log(level, msg, t); + } + + public static boolean isLoggable() { + return debug || logger.isLoggable(level); + } +} diff --git a/jaxws/src/share/jaf_classes/com/sun/activation/registries/MailcapFile.java b/jaxws/src/share/jaf_classes/com/sun/activation/registries/MailcapFile.java new file mode 100644 index 00000000000..8b998b0e4cb --- /dev/null +++ b/jaxws/src/share/jaf_classes/com/sun/activation/registries/MailcapFile.java @@ -0,0 +1,563 @@ +/* + * Copyright (c) 1997, 2005, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.activation.registries; + +import java.io.*; +import java.util.*; + +public class MailcapFile { + + /** + * A Map indexed by MIME type (string) that references + * a Map of commands for each type. The comand Map + * is indexed by the command name and references a List of + * class names (strings) for each command. + */ + private Map type_hash = new HashMap(); + + /** + * Another Map like above, but for fallback entries. + */ + private Map fallback_hash = new HashMap(); + + /** + * A Map indexed by MIME type (string) that references + * a List of native commands (string) corresponding to the type. + */ + private Map native_commands = new HashMap(); + + private static boolean addReverse = false; + + static { + try { + addReverse = Boolean.getBoolean("javax.activation.addreverse"); + } catch (Throwable t) { + // ignore any errors + } + } + + /** + * The constructor that takes a filename as an argument. + * + * @param new_fname The file name of the mailcap file. + */ + public MailcapFile(String new_fname) throws IOException { + if (LogSupport.isLoggable()) + LogSupport.log("new MailcapFile: file " + new_fname); + FileReader reader = null; + try { + reader = new FileReader(new_fname); + parse(new BufferedReader(reader)); + } finally { + if (reader != null) { + try { + reader.close(); + } catch (IOException ex) { } + } + } + } + + /** + * The constructor that takes an input stream as an argument. + * + * @param is the input stream + */ + public MailcapFile(InputStream is) throws IOException { + if (LogSupport.isLoggable()) + LogSupport.log("new MailcapFile: InputStream"); + parse(new BufferedReader(new InputStreamReader(is, "iso-8859-1"))); + } + + /** + * Mailcap file default constructor. + */ + public MailcapFile() { + if (LogSupport.isLoggable()) + LogSupport.log("new MailcapFile: default"); + } + + /** + * Get the Map of MailcapEntries based on the MIME type. + * + *

+ * Semantics: First check for the literal mime type, + * if that fails looks for wildcard /\* and return that. Return the + * list of all that hit. + */ + public Map getMailcapList(String mime_type) { + Map search_result = null; + Map wildcard_result = null; + + // first try the literal + search_result = (Map)type_hash.get(mime_type); + + // ok, now try the wildcard + int separator = mime_type.indexOf('/'); + String subtype = mime_type.substring(separator + 1); + if (!subtype.equals("*")) { + String type = mime_type.substring(0, separator + 1) + "*"; + wildcard_result = (Map)type_hash.get(type); + + if (wildcard_result != null) { // damn, we have to merge!!! + if (search_result != null) + search_result = + mergeResults(search_result, wildcard_result); + else + search_result = wildcard_result; + } + } + return search_result; + } + + /** + * Get the Map of fallback MailcapEntries based on the MIME type. + * + *

+ * Semantics: First check for the literal mime type, + * if that fails looks for wildcard /\* and return that. Return the + * list of all that hit. + */ + public Map getMailcapFallbackList(String mime_type) { + Map search_result = null; + Map wildcard_result = null; + + // first try the literal + search_result = (Map)fallback_hash.get(mime_type); + + // ok, now try the wildcard + int separator = mime_type.indexOf('/'); + String subtype = mime_type.substring(separator + 1); + if (!subtype.equals("*")) { + String type = mime_type.substring(0, separator + 1) + "*"; + wildcard_result = (Map)fallback_hash.get(type); + + if (wildcard_result != null) { // damn, we have to merge!!! + if (search_result != null) + search_result = + mergeResults(search_result, wildcard_result); + else + search_result = wildcard_result; + } + } + return search_result; + } + + /** + * Return all the MIME types known to this mailcap file. + */ + public String[] getMimeTypes() { + Set types = new HashSet(type_hash.keySet()); + types.addAll(fallback_hash.keySet()); + types.addAll(native_commands.keySet()); + String[] mts = new String[types.size()]; + mts = (String[])types.toArray(mts); + return mts; + } + + /** + * Return all the native comands for the given MIME type. + */ + public String[] getNativeCommands(String mime_type) { + String[] cmds = null; + List v = + (List)native_commands.get(mime_type.toLowerCase(Locale.ENGLISH)); + if (v != null) { + cmds = new String[v.size()]; + cmds = (String[])v.toArray(cmds); + } + return cmds; + } + + /** + * Merge the first hash into the second. + * This merge will only effect the hashtable that is + * returned, we don't want to touch the one passed in since + * its integrity must be maintained. + */ + private Map mergeResults(Map first, Map second) { + Iterator verb_enum = second.keySet().iterator(); + Map clonedHash = new HashMap(first); + + // iterate through the verbs in the second map + while (verb_enum.hasNext()) { + String verb = (String)verb_enum.next(); + List cmdVector = (List)clonedHash.get(verb); + if (cmdVector == null) { + clonedHash.put(verb, second.get(verb)); + } else { + // merge the two + List oldV = (List)second.get(verb); + cmdVector = new ArrayList(cmdVector); + cmdVector.addAll(oldV); + clonedHash.put(verb, cmdVector); + } + } + return clonedHash; + } + + /** + * appendToMailcap: Append to this Mailcap DB, use the mailcap + * format: + * Comment == "# comment string + * Entry == "mimetype; javabeanclass + * + * Example: + * # this is a comment + * image/gif jaf.viewers.ImageViewer + */ + public void appendToMailcap(String mail_cap) { + if (LogSupport.isLoggable()) + LogSupport.log("appendToMailcap: " + mail_cap); + try { + parse(new StringReader(mail_cap)); + } catch (IOException ex) { + // can't happen + } + } + + /** + * parse file into a hash table of MC Type Entry Obj + */ + private void parse(Reader reader) throws IOException { + BufferedReader buf_reader = new BufferedReader(reader); + String line = null; + String continued = null; + + while ((line = buf_reader.readLine()) != null) { + // LogSupport.log("parsing line: " + line); + + line = line.trim(); + + try { + if (line.charAt(0) == '#') + continue; + if (line.charAt(line.length() - 1) == '\\') { + if (continued != null) + continued += line.substring(0, line.length() - 1); + else + continued = line.substring(0, line.length() - 1); + } else if (continued != null) { + // handle the two strings + continued = continued + line; + // LogSupport.log("parse: " + continued); + try { + parseLine(continued); + } catch (MailcapParseException e) { + //e.printStackTrace(); + } + continued = null; + } + else { + // LogSupport.log("parse: " + line); + try { + parseLine(line); + // LogSupport.log("hash.size = " + type_hash.size()); + } catch (MailcapParseException e) { + //e.printStackTrace(); + } + } + } catch (StringIndexOutOfBoundsException e) {} + } + } + + /** + * A routine to parse individual entries in a Mailcap file. + * + * Note that this routine does not handle line continuations. + * They should have been handled prior to calling this routine. + */ + protected void parseLine(String mailcapEntry) + throws MailcapParseException, IOException { + MailcapTokenizer tokenizer = new MailcapTokenizer(mailcapEntry); + tokenizer.setIsAutoquoting(false); + + if (LogSupport.isLoggable()) + LogSupport.log("parse: " + mailcapEntry); + // parse the primary type + int currentToken = tokenizer.nextToken(); + if (currentToken != MailcapTokenizer.STRING_TOKEN) { + reportParseError(MailcapTokenizer.STRING_TOKEN, currentToken, + tokenizer.getCurrentTokenValue()); + } + String primaryType = + tokenizer.getCurrentTokenValue().toLowerCase(Locale.ENGLISH); + String subType = "*"; + + // parse the '/' between primary and sub + // if it's not present that's ok, we just don't have a subtype + currentToken = tokenizer.nextToken(); + if ((currentToken != MailcapTokenizer.SLASH_TOKEN) && + (currentToken != MailcapTokenizer.SEMICOLON_TOKEN)) { + reportParseError(MailcapTokenizer.SLASH_TOKEN, + MailcapTokenizer.SEMICOLON_TOKEN, currentToken, + tokenizer.getCurrentTokenValue()); + } + + // only need to look for a sub type if we got a '/' + if (currentToken == MailcapTokenizer.SLASH_TOKEN) { + // parse the sub type + currentToken = tokenizer.nextToken(); + if (currentToken != MailcapTokenizer.STRING_TOKEN) { + reportParseError(MailcapTokenizer.STRING_TOKEN, + currentToken, tokenizer.getCurrentTokenValue()); + } + subType = + tokenizer.getCurrentTokenValue().toLowerCase(Locale.ENGLISH); + + // get the next token to simplify the next step + currentToken = tokenizer.nextToken(); + } + + String mimeType = primaryType + "/" + subType; + + if (LogSupport.isLoggable()) + LogSupport.log(" Type: " + mimeType); + + // now setup the commands hashtable + Map commands = new LinkedHashMap(); // keep commands in order found + + // parse the ';' that separates the type from the parameters + if (currentToken != MailcapTokenizer.SEMICOLON_TOKEN) { + reportParseError(MailcapTokenizer.SEMICOLON_TOKEN, + currentToken, tokenizer.getCurrentTokenValue()); + } + // eat it + + // parse the required view command + tokenizer.setIsAutoquoting(true); + currentToken = tokenizer.nextToken(); + tokenizer.setIsAutoquoting(false); + if ((currentToken != MailcapTokenizer.STRING_TOKEN) && + (currentToken != MailcapTokenizer.SEMICOLON_TOKEN)) { + reportParseError(MailcapTokenizer.STRING_TOKEN, + MailcapTokenizer.SEMICOLON_TOKEN, currentToken, + tokenizer.getCurrentTokenValue()); + } + + if (currentToken == MailcapTokenizer.STRING_TOKEN) { + // have a native comand, save the entire mailcap entry + //String nativeCommand = tokenizer.getCurrentTokenValue(); + List v = (List)native_commands.get(mimeType); + if (v == null) { + v = new ArrayList(); + v.add(mailcapEntry); + native_commands.put(mimeType, v); + } else { + // XXX - check for duplicates? + v.add(mailcapEntry); + } + } + + // only have to get the next token if the current one isn't a ';' + if (currentToken != MailcapTokenizer.SEMICOLON_TOKEN) { + currentToken = tokenizer.nextToken(); + } + + // look for a ';' which will indicate whether + // a parameter list is present or not + if (currentToken == MailcapTokenizer.SEMICOLON_TOKEN) { + boolean isFallback = false; + do { + // eat the ';' + + // parse the parameter name + currentToken = tokenizer.nextToken(); + if (currentToken != MailcapTokenizer.STRING_TOKEN) { + reportParseError(MailcapTokenizer.STRING_TOKEN, + currentToken, tokenizer.getCurrentTokenValue()); + } + String paramName = tokenizer.getCurrentTokenValue(). + toLowerCase(Locale.ENGLISH); + + // parse the '=' which separates the name from the value + currentToken = tokenizer.nextToken(); + if ((currentToken != MailcapTokenizer.EQUALS_TOKEN) && + (currentToken != MailcapTokenizer.SEMICOLON_TOKEN) && + (currentToken != MailcapTokenizer.EOI_TOKEN)) { + reportParseError(MailcapTokenizer.EQUALS_TOKEN, + MailcapTokenizer.SEMICOLON_TOKEN, + MailcapTokenizer.EOI_TOKEN, + currentToken, tokenizer.getCurrentTokenValue()); + } + + // we only have a useful command if it is named + if (currentToken == MailcapTokenizer.EQUALS_TOKEN) { + // eat it + + // parse the parameter value (which is autoquoted) + tokenizer.setIsAutoquoting(true); + currentToken = tokenizer.nextToken(); + tokenizer.setIsAutoquoting(false); + if (currentToken != MailcapTokenizer.STRING_TOKEN) { + reportParseError(MailcapTokenizer.STRING_TOKEN, + currentToken, tokenizer.getCurrentTokenValue()); + } + String paramValue = + tokenizer.getCurrentTokenValue(); + + // add the class to the list iff it is one we care about + if (paramName.startsWith("x-java-")) { + String commandName = paramName.substring(7); + // 7 == "x-java-".length + + if (commandName.equals("fallback-entry") && + paramValue.equalsIgnoreCase("true")) { + isFallback = true; + } else { + + // setup the class entry list + if (LogSupport.isLoggable()) + LogSupport.log(" Command: " + commandName + + ", Class: " + paramValue); + List classes = (List)commands.get(commandName); + if (classes == null) { + classes = new ArrayList(); + commands.put(commandName, classes); + } + if (addReverse) + classes.add(0, paramValue); + else + classes.add(paramValue); + } + } + + // set up the next iteration + currentToken = tokenizer.nextToken(); + } + } while (currentToken == MailcapTokenizer.SEMICOLON_TOKEN); + + Map masterHash = isFallback ? fallback_hash : type_hash; + Map curcommands = + (Map)masterHash.get(mimeType); + if (curcommands == null) { + masterHash.put(mimeType, commands); + } else { + if (LogSupport.isLoggable()) + LogSupport.log("Merging commands for type " + mimeType); + // have to merge current and new commands + // first, merge list of classes for commands already known + Iterator cn = curcommands.keySet().iterator(); + while (cn.hasNext()) { + String cmdName = (String)cn.next(); + List ccv = (List)curcommands.get(cmdName); + List cv = (List)commands.get(cmdName); + if (cv == null) + continue; + // add everything in cv to ccv, if it's not already there + Iterator cvn = cv.iterator(); + while (cvn.hasNext()) { + String clazz = (String)cvn.next(); + if (!ccv.contains(clazz)) + if (addReverse) + ccv.add(0, clazz); + else + ccv.add(clazz); + } + } + // now, add commands not previously known + cn = commands.keySet().iterator(); + while (cn.hasNext()) { + String cmdName = (String)cn.next(); + if (curcommands.containsKey(cmdName)) + continue; + List cv = (List)commands.get(cmdName); + curcommands.put(cmdName, cv); + } + } + } else if (currentToken != MailcapTokenizer.EOI_TOKEN) { + reportParseError(MailcapTokenizer.EOI_TOKEN, + MailcapTokenizer.SEMICOLON_TOKEN, + currentToken, tokenizer.getCurrentTokenValue()); + } + } + + protected static void reportParseError(int expectedToken, int actualToken, + String actualTokenValue) throws MailcapParseException { + throw new MailcapParseException("Encountered a " + + MailcapTokenizer.nameForToken(actualToken) + " token (" + + actualTokenValue + ") while expecting a " + + MailcapTokenizer.nameForToken(expectedToken) + " token."); + } + + protected static void reportParseError(int expectedToken, + int otherExpectedToken, int actualToken, String actualTokenValue) + throws MailcapParseException { + throw new MailcapParseException("Encountered a " + + MailcapTokenizer.nameForToken(actualToken) + " token (" + + actualTokenValue + ") while expecting a " + + MailcapTokenizer.nameForToken(expectedToken) + " or a " + + MailcapTokenizer.nameForToken(otherExpectedToken) + " token."); + } + + protected static void reportParseError(int expectedToken, + int otherExpectedToken, int anotherExpectedToken, int actualToken, + String actualTokenValue) throws MailcapParseException { + if (LogSupport.isLoggable()) + LogSupport.log("PARSE ERROR: " + "Encountered a " + + MailcapTokenizer.nameForToken(actualToken) + " token (" + + actualTokenValue + ") while expecting a " + + MailcapTokenizer.nameForToken(expectedToken) + ", a " + + MailcapTokenizer.nameForToken(otherExpectedToken) + ", or a " + + MailcapTokenizer.nameForToken(anotherExpectedToken) + " token."); + throw new MailcapParseException("Encountered a " + + MailcapTokenizer.nameForToken(actualToken) + " token (" + + actualTokenValue + ") while expecting a " + + MailcapTokenizer.nameForToken(expectedToken) + ", a " + + MailcapTokenizer.nameForToken(otherExpectedToken) + ", or a " + + MailcapTokenizer.nameForToken(anotherExpectedToken) + " token."); + } + + /** for debugging + public static void main(String[] args) throws Exception { + Map masterHash = new HashMap(); + for (int i = 0; i < args.length; ++i) { + System.out.println("Entry " + i + ": " + args[i]); + parseLine(args[i], masterHash); + } + + Enumeration types = masterHash.keys(); + while (types.hasMoreElements()) { + String key = (String)types.nextElement(); + System.out.println("MIME Type: " + key); + + Map commandHash = (Map)masterHash.get(key); + Enumeration commands = commandHash.keys(); + while (commands.hasMoreElements()) { + String command = (String)commands.nextElement(); + System.out.println(" Command: " + command); + + Vector classes = (Vector)commandHash.get(command); + for (int i = 0; i < classes.size(); ++i) { + System.out.println(" Class: " + + (String)classes.elementAt(i)); + } + } + + System.out.println(""); + } + } + */ +} diff --git a/jaxws/src/share/jaf_classes/com/sun/activation/registries/MailcapParseException.java b/jaxws/src/share/jaf_classes/com/sun/activation/registries/MailcapParseException.java new file mode 100644 index 00000000000..15d06a7bd24 --- /dev/null +++ b/jaxws/src/share/jaf_classes/com/sun/activation/registries/MailcapParseException.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 1997, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.activation.registries; + +/** + * A class to encapsulate Mailcap parsing related exceptions + */ +public class MailcapParseException extends Exception { + + public MailcapParseException() { + super(); + } + + public MailcapParseException(String inInfo) { + super(inInfo); + } +} diff --git a/jaxws/src/share/jaf_classes/com/sun/activation/registries/MailcapTokenizer.java b/jaxws/src/share/jaf_classes/com/sun/activation/registries/MailcapTokenizer.java new file mode 100644 index 00000000000..38807ed5a48 --- /dev/null +++ b/jaxws/src/share/jaf_classes/com/sun/activation/registries/MailcapTokenizer.java @@ -0,0 +1,321 @@ +/* + * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.activation.registries; + +/** + * A tokenizer for strings in the form of "foo/bar; prop1=val1; ... ". + * Useful for parsing MIME content types. + */ +public class MailcapTokenizer { + + public static final int UNKNOWN_TOKEN = 0; + public static final int START_TOKEN = 1; + public static final int STRING_TOKEN = 2; + public static final int EOI_TOKEN = 5; + public static final int SLASH_TOKEN = '/'; + public static final int SEMICOLON_TOKEN = ';'; + public static final int EQUALS_TOKEN = '='; + + /** + * Constructor + * + * @parameter inputString the string to tokenize + */ + public MailcapTokenizer(String inputString) { + data = inputString; + dataIndex = 0; + dataLength = inputString.length(); + + currentToken = START_TOKEN; + currentTokenValue = ""; + + isAutoquoting = false; + autoquoteChar = ';'; + } + + /** + * Set whether auto-quoting is on or off. + * + * Auto-quoting means that all characters after the first + * non-whitespace, non-control character up to the auto-quote + * terminator character or EOI (minus any whitespace immediatley + * preceeding it) is considered a token. + * + * This is required for handling command strings in a mailcap entry. + */ + public void setIsAutoquoting(boolean value) { + isAutoquoting = value; + } + + /** + * Retrieve current token. + * + * @returns The current token value + */ + public int getCurrentToken() { + return currentToken; + } + + /* + * Get a String that describes the given token. + */ + public static String nameForToken(int token) { + String name = "really unknown"; + + switch(token) { + case UNKNOWN_TOKEN: + name = "unknown"; + break; + case START_TOKEN: + name = "start"; + break; + case STRING_TOKEN: + name = "string"; + break; + case EOI_TOKEN: + name = "EOI"; + break; + case SLASH_TOKEN: + name = "'/'"; + break; + case SEMICOLON_TOKEN: + name = "';'"; + break; + case EQUALS_TOKEN: + name = "'='"; + break; + } + + return name; + } + + /* + * Retrieve current token value. + * + * @returns A String containing the current token value + */ + public String getCurrentTokenValue() { + return currentTokenValue; + } + /* + * Process the next token. + * + * @returns the next token + */ + public int nextToken() { + if (dataIndex < dataLength) { + // skip white space + while ((dataIndex < dataLength) && + (isWhiteSpaceChar(data.charAt(dataIndex)))) { + ++dataIndex; + } + + if (dataIndex < dataLength) { + // examine the current character and see what kind of token we have + char c = data.charAt(dataIndex); + if (isAutoquoting) { + if (c == ';' || c == '=') { + currentToken = c; + currentTokenValue = new Character(c).toString(); + ++dataIndex; + } else { + processAutoquoteToken(); + } + } else { + if (isStringTokenChar(c)) { + processStringToken(); + } else if ((c == '/') || (c == ';') || (c == '=')) { + currentToken = c; + currentTokenValue = new Character(c).toString(); + ++dataIndex; + } else { + currentToken = UNKNOWN_TOKEN; + currentTokenValue = new Character(c).toString(); + ++dataIndex; + } + } + } else { + currentToken = EOI_TOKEN; + currentTokenValue = null; + } + } else { + currentToken = EOI_TOKEN; + currentTokenValue = null; + } + + return currentToken; + } + + private void processStringToken() { + // capture the initial index + int initialIndex = dataIndex; + + // skip to 1st non string token character + while ((dataIndex < dataLength) && + isStringTokenChar(data.charAt(dataIndex))) { + ++dataIndex; + } + + currentToken = STRING_TOKEN; + currentTokenValue = data.substring(initialIndex, dataIndex); + } + + private void processAutoquoteToken() { + // capture the initial index + int initialIndex = dataIndex; + + // now skip to the 1st non-escaped autoquote termination character + // XXX - doesn't actually consider escaping + boolean foundTerminator = false; + while ((dataIndex < dataLength) && !foundTerminator) { + char c = data.charAt(dataIndex); + if (c != autoquoteChar) { + ++dataIndex; + } else { + foundTerminator = true; + } + } + + currentToken = STRING_TOKEN; + currentTokenValue = + fixEscapeSequences(data.substring(initialIndex, dataIndex)); + } + + private static boolean isSpecialChar(char c) { + boolean lAnswer = false; + + switch(c) { + case '(': + case ')': + case '<': + case '>': + case '@': + case ',': + case ';': + case ':': + case '\\': + case '"': + case '/': + case '[': + case ']': + case '?': + case '=': + lAnswer = true; + break; + } + + return lAnswer; + } + + private static boolean isControlChar(char c) { + return Character.isISOControl(c); + } + + private static boolean isWhiteSpaceChar(char c) { + return Character.isWhitespace(c); + } + + private static boolean isStringTokenChar(char c) { + return !isSpecialChar(c) && !isControlChar(c) && !isWhiteSpaceChar(c); + } + + private static String fixEscapeSequences(String inputString) { + int inputLength = inputString.length(); + StringBuffer buffer = new StringBuffer(); + buffer.ensureCapacity(inputLength); + + for (int i = 0; i < inputLength; ++i) { + char currentChar = inputString.charAt(i); + if (currentChar != '\\') { + buffer.append(currentChar); + } else { + if (i < inputLength - 1) { + char nextChar = inputString.charAt(i + 1); + buffer.append(nextChar); + + // force a skip over the next character too + ++i; + } else { + buffer.append(currentChar); + } + } + } + + return buffer.toString(); + } + + private String data; + private int dataIndex; + private int dataLength; + private int currentToken; + private String currentTokenValue; + private boolean isAutoquoting; + private char autoquoteChar; + + /* + public static void main(String[] args) { + for (int i = 0; i < args.length; ++i) { + MailcapTokenizer tokenizer = new MailcapTokenizer(args[i]); + + System.out.println("Original: |" + args[i] + "|"); + + int currentToken = tokenizer.nextToken(); + while (currentToken != EOI_TOKEN) { + switch(currentToken) { + case UNKNOWN_TOKEN: + System.out.println(" Unknown Token: |" + tokenizer.getCurrentTokenValue() + "|"); + break; + case START_TOKEN: + System.out.println(" Start Token: |" + tokenizer.getCurrentTokenValue() + "|"); + break; + case STRING_TOKEN: + System.out.println(" String Token: |" + tokenizer.getCurrentTokenValue() + "|"); + break; + case EOI_TOKEN: + System.out.println(" EOI Token: |" + tokenizer.getCurrentTokenValue() + "|"); + break; + case SLASH_TOKEN: + System.out.println(" Slash Token: |" + tokenizer.getCurrentTokenValue() + "|"); + break; + case SEMICOLON_TOKEN: + System.out.println(" Semicolon Token: |" + tokenizer.getCurrentTokenValue() + "|"); + break; + case EQUALS_TOKEN: + System.out.println(" Equals Token: |" + tokenizer.getCurrentTokenValue() + "|"); + break; + default: + System.out.println(" Really Unknown Token: |" + tokenizer.getCurrentTokenValue() + "|"); + break; + } + + currentToken = tokenizer.nextToken(); + } + + System.out.println(""); + } + } + */ +} diff --git a/jaxws/src/share/jaf_classes/com/sun/activation/registries/MimeTypeEntry.java b/jaxws/src/share/jaf_classes/com/sun/activation/registries/MimeTypeEntry.java new file mode 100644 index 00000000000..0e34b1846d9 --- /dev/null +++ b/jaxws/src/share/jaf_classes/com/sun/activation/registries/MimeTypeEntry.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 1997, 1998, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.activation.registries; + +import java.lang.*; + +public class MimeTypeEntry { + private String type; + private String extension; + + public MimeTypeEntry(String mime_type, String file_ext) { + type = mime_type; + extension = file_ext; + } + + public String getMIMEType() { + return type; + } + + public String getFileExtension() { + return extension; + } + + public String toString() { + return "MIMETypeEntry: " + type + ", " + extension; + } +} diff --git a/jaxws/src/share/jaf_classes/com/sun/activation/registries/MimeTypeFile.java b/jaxws/src/share/jaf_classes/com/sun/activation/registries/MimeTypeFile.java new file mode 100644 index 00000000000..aa69c35b1b5 --- /dev/null +++ b/jaxws/src/share/jaf_classes/com/sun/activation/registries/MimeTypeFile.java @@ -0,0 +1,317 @@ +/* + * Copyright (c) 1997, 2003, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.activation.registries; + +import java.io.*; +import java.util.*; + +public class MimeTypeFile { + private String fname = null; + private Hashtable type_hash = new Hashtable(); + + /** + * The construtor that takes a filename as an argument. + * + * @param new_fname The file name of the mime types file. + */ + public MimeTypeFile(String new_fname) throws IOException { + File mime_file = null; + FileReader fr = null; + + fname = new_fname; // remember the file name + + mime_file = new File(fname); // get a file object + + fr = new FileReader(mime_file); + + try { + parse(new BufferedReader(fr)); + } finally { + try { + fr.close(); // close it + } catch (IOException e) { + // ignore it + } + } + } + + public MimeTypeFile(InputStream is) throws IOException { + parse(new BufferedReader(new InputStreamReader(is, "iso-8859-1"))); + } + + /** + * Creates an empty DB. + */ + public MimeTypeFile() { + } + + /** + * get the MimeTypeEntry based on the file extension + */ + public MimeTypeEntry getMimeTypeEntry(String file_ext) { + return (MimeTypeEntry)type_hash.get((Object)file_ext); + } + + /** + * Get the MIME type string corresponding to the file extension. + */ + public String getMIMETypeString(String file_ext) { + MimeTypeEntry entry = this.getMimeTypeEntry(file_ext); + + if (entry != null) + return entry.getMIMEType(); + else + return null; + } + + /** + * Appends string of entries to the types registry, must be valid + * .mime.types format. + * A mime.types entry is one of two forms: + * + * type/subtype ext1 ext2 ... + * or + * type=type/subtype desc="description of type" exts=ext1,ext2,... + * + * Example: + * # this is a test + * audio/basic au + * text/plain txt text + * type=application/postscript exts=ps,eps + */ + public void appendToRegistry(String mime_types) { + try { + parse(new BufferedReader(new StringReader(mime_types))); + } catch (IOException ex) { + // can't happen + } + } + + /** + * Parse a stream of mime.types entries. + */ + private void parse(BufferedReader buf_reader) throws IOException { + String line = null, prev = null; + + while ((line = buf_reader.readLine()) != null) { + if (prev == null) + prev = line; + else + prev += line; + int end = prev.length(); + if (prev.length() > 0 && prev.charAt(end - 1) == '\\') { + prev = prev.substring(0, end - 1); + continue; + } + this.parseEntry(prev); + prev = null; + } + if (prev != null) + this.parseEntry(prev); + } + + /** + * Parse single mime.types entry. + */ + private void parseEntry(String line) { + String mime_type = null; + String file_ext = null; + line = line.trim(); + + if (line.length() == 0) // empty line... + return; // BAIL! + + // check to see if this is a comment line? + if (line.charAt(0) == '#') + return; // then we are done! + + // is it a new format line or old format? + if (line.indexOf('=') > 0) { + // new format + LineTokenizer lt = new LineTokenizer(line); + while (lt.hasMoreTokens()) { + String name = lt.nextToken(); + String value = null; + if (lt.hasMoreTokens() && lt.nextToken().equals("=") && + lt.hasMoreTokens()) + value = lt.nextToken(); + if (value == null) { + if (LogSupport.isLoggable()) + LogSupport.log("Bad .mime.types entry: " + line); + return; + } + if (name.equals("type")) + mime_type = value; + else if (name.equals("exts")) { + StringTokenizer st = new StringTokenizer(value, ","); + while (st.hasMoreTokens()) { + file_ext = st.nextToken(); + MimeTypeEntry entry = + new MimeTypeEntry(mime_type, file_ext); + type_hash.put(file_ext, entry); + if (LogSupport.isLoggable()) + LogSupport.log("Added: " + entry.toString()); + } + } + } + } else { + // old format + // count the tokens + StringTokenizer strtok = new StringTokenizer(line); + int num_tok = strtok.countTokens(); + + if (num_tok == 0) // empty line + return; + + mime_type = strtok.nextToken(); // get the MIME type + + while (strtok.hasMoreTokens()) { + MimeTypeEntry entry = null; + + file_ext = strtok.nextToken(); + entry = new MimeTypeEntry(mime_type, file_ext); + type_hash.put(file_ext, entry); + if (LogSupport.isLoggable()) + LogSupport.log("Added: " + entry.toString()); + } + } + } + + // for debugging + /* + public static void main(String[] argv) throws Exception { + MimeTypeFile mf = new MimeTypeFile(argv[0]); + System.out.println("ext " + argv[1] + " type " + + mf.getMIMETypeString(argv[1])); + System.exit(0); + } + */ +} + +class LineTokenizer { + private int currentPosition; + private int maxPosition; + private String str; + private Vector stack = new Vector(); + private static final String singles = "="; // single character tokens + + /** + * Constructs a tokenizer for the specified string. + *

+ * + * @param str a string to be parsed. + */ + public LineTokenizer(String str) { + currentPosition = 0; + this.str = str; + maxPosition = str.length(); + } + + /** + * Skips white space. + */ + private void skipWhiteSpace() { + while ((currentPosition < maxPosition) && + Character.isWhitespace(str.charAt(currentPosition))) { + currentPosition++; + } + } + + /** + * Tests if there are more tokens available from this tokenizer's string. + * + * @return true if there are more tokens available from this + * tokenizer's string; false otherwise. + */ + public boolean hasMoreTokens() { + if (stack.size() > 0) + return true; + skipWhiteSpace(); + return (currentPosition < maxPosition); + } + + /** + * Returns the next token from this tokenizer. + * + * @return the next token from this tokenizer. + * @exception NoSuchElementException if there are no more tokens in this + * tokenizer's string. + */ + public String nextToken() { + int size = stack.size(); + if (size > 0) { + String t = (String)stack.elementAt(size - 1); + stack.removeElementAt(size - 1); + return t; + } + skipWhiteSpace(); + + if (currentPosition >= maxPosition) { + throw new NoSuchElementException(); + } + + int start = currentPosition; + char c = str.charAt(start); + if (c == '"') { + currentPosition++; + boolean filter = false; + while (currentPosition < maxPosition) { + c = str.charAt(currentPosition++); + if (c == '\\') { + currentPosition++; + filter = true; + } else if (c == '"') { + String s; + + if (filter) { + StringBuffer sb = new StringBuffer(); + for (int i = start + 1; i < currentPosition - 1; i++) { + c = str.charAt(i); + if (c != '\\') + sb.append(c); + } + s = sb.toString(); + } else + s = str.substring(start + 1, currentPosition - 1); + return s; + } + } + } else if (singles.indexOf(c) >= 0) { + currentPosition++; + } else { + while ((currentPosition < maxPosition) && + singles.indexOf(str.charAt(currentPosition)) < 0 && + !Character.isWhitespace(str.charAt(currentPosition))) { + currentPosition++; + } + } + return str.substring(start, currentPosition); + } + + public void pushToken(String token) { + stack.addElement(token); + } +} diff --git a/jaxws/src/share/jaf_classes/javax/activation/ActivationDataFlavor.java b/jaxws/src/share/jaf_classes/javax/activation/ActivationDataFlavor.java new file mode 100644 index 00000000000..500dc77c0fa --- /dev/null +++ b/jaxws/src/share/jaf_classes/javax/activation/ActivationDataFlavor.java @@ -0,0 +1,250 @@ +/* + * Copyright (c) 1997, 2005, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package javax.activation; + +import java.awt.datatransfer.DataFlavor; +import java.io.IOException; +import javax.activation.MimeType; + +/** + * The ActivationDataFlavor class is a special subclass of + * java.awt.datatransfer.DataFlavor. It allows the JAF to + * set all three values stored by the DataFlavor class via a new + * constructor. It also contains improved MIME parsing in the equals + * method. Except for the improved parsing, its semantics are + * identical to that of the JDK's DataFlavor class. + * + * @since 1.6 + */ + +public class ActivationDataFlavor extends DataFlavor { + + /* + * Raison d'etre: + * + * The DataFlavor class included in JDK 1.1 has several limitations + * including piss poor MIME type parsing, and the limitation of + * only supporting serialized objects and InputStreams as + * representation objects. This class 'fixes' that. + */ + + // I think for now I'll keep copies of all the variables and + // then later I may choose try to better coexist with the base + // class *sigh* + private String mimeType = null; + private MimeType mimeObject = null; + private String humanPresentableName = null; + private Class representationClass = null; + + /** + * Construct a DataFlavor that represents an arbitrary + * Java object. This constructor is an extension of the + * JDK's DataFlavor in that it allows the explicit setting + * of all three DataFlavor attributes. + *

+ * The returned DataFlavor will have the following characteristics: + *

+ * representationClass = representationClass
+ * mimeType = mimeType
+ * humanName = humanName + *

+ * + * @param representationClass the class used in this DataFlavor + * @param mimeType the MIME type of the data represented by this class + * @param humanPresentableName the human presentable name of the flavor + */ + public ActivationDataFlavor(Class representationClass, + String mimeType, String humanPresentableName) { + super(mimeType, humanPresentableName); // need to call super + + // init private variables: + this.mimeType = mimeType; + this.humanPresentableName = humanPresentableName; + this.representationClass = representationClass; + } + + /** + * Construct a DataFlavor that represents a MimeType. + *

+ * The returned DataFlavor will have the following characteristics: + *

+ * If the mimeType is "application/x-java-serialized-object; + * class=", the result is the same as calling new + * DataFlavor(Class.forName()) as above. + *

+ * otherwise: + *

+ * representationClass = InputStream

+ * mimeType = mimeType

+ * + * @param representationClass the class used in this DataFlavor + * @param humanPresentableName the human presentable name of the flavor + */ + public ActivationDataFlavor(Class representationClass, + String humanPresentableName) { + super(representationClass, humanPresentableName); + this.mimeType = super.getMimeType(); + this.representationClass = representationClass; + this.humanPresentableName = humanPresentableName; + } + + /** + * Construct a DataFlavor that represents a MimeType. + *

+ * The returned DataFlavor will have the following characteristics: + *

+ * If the mimeType is "application/x-java-serialized-object; class=", + * the result is the same as calling new DataFlavor(Class.forName()) as + * above, otherwise: + *

+ * representationClass = InputStream

+ * mimeType = mimeType + * + * @param mimeType the MIME type of the data represented by this class + * @param humanPresentableName the human presentable name of the flavor + */ + public ActivationDataFlavor(String mimeType, String humanPresentableName) { + super(mimeType, humanPresentableName); + this.mimeType = mimeType; + try { + this.representationClass = Class.forName("java.io.InputStream"); + } catch (ClassNotFoundException ex) { + // XXX - should never happen, ignore it + } + this.humanPresentableName = humanPresentableName; + } + + /** + * Return the MIME type for this DataFlavor. + * + * @return the MIME type + */ + public String getMimeType() { + return mimeType; + } + + /** + * Return the representation class. + * + * @return the representation class + */ + public Class getRepresentationClass() { + return representationClass; + } + + /** + * Return the Human Presentable name. + * + * @return the human presentable name + */ + public String getHumanPresentableName() { + return humanPresentableName; + } + + /** + * Set the human presentable name. + * + * @param humanPresentableName the name to set + */ + public void setHumanPresentableName(String humanPresentableName) { + this.humanPresentableName = humanPresentableName; + } + + /** + * Compares the DataFlavor passed in with this DataFlavor; calls + * the isMimeTypeEqual method. + * + * @param dataFlavor the DataFlavor to compare with + * @return true if the MIME type and representation class + * are the same + */ + public boolean equals(DataFlavor dataFlavor) { + return (isMimeTypeEqual(dataFlavor) && + dataFlavor.getRepresentationClass() == representationClass); + } + + /** + * Is the string representation of the MIME type passed in equivalent + * to the MIME type of this DataFlavor.

+ * + * ActivationDataFlavor delegates the comparison of MIME types to + * the MimeType class included as part of the JavaBeans Activation + * Framework. This provides a more robust comparison than is normally + * available in the DataFlavor class. + * + * @param mimeType the MIME type + * @return true if the same MIME type + */ + public boolean isMimeTypeEqual(String mimeType) { + MimeType mt = null; + try { + if (mimeObject == null) + mimeObject = new MimeType(this.mimeType); + mt = new MimeType(mimeType); + } catch (MimeTypeParseException e) { + // something didn't parse, do a crude comparison + return this.mimeType.equalsIgnoreCase(mimeType); + } + + return mimeObject.match(mt); + } + + /** + * Called on DataFlavor for every MIME Type parameter to allow DataFlavor + * subclasses to handle special parameters like the text/plain charset + * parameters, whose values are case insensitive. (MIME type parameter + * values are supposed to be case sensitive). + *

+ * This method is called for each parameter name/value pair and should + * return the normalized representation of the parameterValue. + * This method is never invoked by this implementation. + * + * @param parameterName the parameter name + * @param parameterValue the parameter value + * @return the normalized parameter value + * @deprecated + */ + protected String normalizeMimeTypeParameter(String parameterName, + String parameterValue) { + return parameterValue; + } + + /** + * Called for each MIME type string to give DataFlavor subtypes the + * opportunity to change how the normalization of MIME types is + * accomplished. + * One possible use would be to add default parameter/value pairs in cases + * where none are present in the MIME type string passed in. + * This method is never invoked by this implementation. + * + * @param mimeType the MIME type + * @return the normalized MIME type + * @deprecated + */ + protected String normalizeMimeType(String mimeType) { + return mimeType; + } +} diff --git a/jaxws/src/share/jaf_classes/javax/activation/CommandInfo.java b/jaxws/src/share/jaf_classes/javax/activation/CommandInfo.java new file mode 100644 index 00000000000..475de00eb59 --- /dev/null +++ b/jaxws/src/share/jaf_classes/javax/activation/CommandInfo.java @@ -0,0 +1,138 @@ +/* + * Copyright (c) 1997, 1999, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package javax.activation; + +import java.io.*; +import java.beans.Beans; + +/** + * The CommandInfo class is used by CommandMap implementations to + * describe the results of command requests. It provides the requestor + * with both the verb requested, as well as an instance of the + * bean. There is also a method that will return the name of the + * class that implements the command but it is not guaranteed to + * return a valid value. The reason for this is to allow CommandMap + * implmentations that subclass CommandInfo to provide special + * behavior. For example a CommandMap could dynamically generate + * JavaBeans. In this case, it might not be possible to create an + * object with all the correct state information solely from the class + * name. + * + * @since 1.6 + */ + +public class CommandInfo { + private String verb; + private String className; + + /** + * The Constructor for CommandInfo. + * @param verb The command verb this CommandInfo decribes. + * @param className The command's fully qualified class name. + */ + public CommandInfo(String verb, String className) { + this.verb = verb; + this.className = className; + } + + /** + * Return the command verb. + * + * @return the command verb. + */ + public String getCommandName() { + return verb; + } + + /** + * Return the command's class name. This method MAY return null in + * cases where a CommandMap subclassed CommandInfo for its + * own purposes. In other words, it might not be possible to + * create the correct state in the command by merely knowing + * its class name. DO NOT DEPEND ON THIS METHOD RETURNING + * A VALID VALUE! + * + * @return The class name of the command, or null + */ + public String getCommandClass() { + return className; + } + + /** + * Return the instantiated JavaBean component. + *

+ * Begin by instantiating the component with + * Beans.instantiate(). + *

+ * If the bean implements the javax.activation.CommandObject + * interface, call its setCommandContext method. + *

+ * If the DataHandler parameter is null, then the bean is + * instantiated with no data. NOTE: this may be useful + * if for some reason the DataHandler that is passed in + * throws IOExceptions when this method attempts to + * access its InputStream. It will allow the caller to + * retrieve a reference to the bean if it can be + * instantiated. + *

+ * If the bean does NOT implement the CommandObject interface, + * this method will check if it implements the + * java.io.Externalizable interface. If it does, the bean's + * readExternal method will be called if an InputStream + * can be acquired from the DataHandler.

+ * + * @param dh The DataHandler that describes the data to be + * passed to the command. + * @param loader The ClassLoader to be used to instantiate the bean. + * @return The bean + * @see java.beans.Beans#instantiate + * @see javax.activation.CommandObject + */ + public Object getCommandObject(DataHandler dh, ClassLoader loader) + throws IOException, ClassNotFoundException { + Object new_bean = null; + + // try to instantiate the bean + new_bean = java.beans.Beans.instantiate(loader, className); + + // if we got one and it is a CommandObject + if (new_bean != null) { + if (new_bean instanceof CommandObject) { + ((CommandObject)new_bean).setCommandContext(verb, dh); + } else if (new_bean instanceof Externalizable) { + if (dh != null) { + InputStream is = dh.getInputStream(); + if (is != null) { + ((Externalizable)new_bean).readExternal( + new ObjectInputStream(is)); + } + } + } + } + + return new_bean; + } +} diff --git a/jaxws/src/share/jaf_classes/javax/activation/CommandMap.java b/jaxws/src/share/jaf_classes/javax/activation/CommandMap.java new file mode 100644 index 00000000000..95ab5d364ff --- /dev/null +++ b/jaxws/src/share/jaf_classes/javax/activation/CommandMap.java @@ -0,0 +1,220 @@ +/* + * Copyright (c) 1997, 2005, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package javax.activation; + + +/** + * The CommandMap class provides an interface to a registry of + * command objects available in the system. + * Developers are expected to either use the CommandMap + * implementation included with this package (MailcapCommandMap) or + * develop their own. Note that some of the methods in this class are + * abstract. + * + * @since 1.6 + */ +public abstract class CommandMap { + private static CommandMap defaultCommandMap = null; + + /** + * Get the default CommandMap. + *

+ * + *

    + *
  • In cases where a CommandMap instance has been previously set + * to some value (via setDefaultCommandMap) + * return the CommandMap. + *
  • + * In cases where no CommandMap has been set, the CommandMap + * creates an instance of MailcapCommandMap and + * set that to the default, returning its value. + * + *
+ * + * @return the CommandMap + */ + public static CommandMap getDefaultCommandMap() { + if (defaultCommandMap == null) + defaultCommandMap = new MailcapCommandMap(); + + return defaultCommandMap; + } + + /** + * Set the default CommandMap. Reset the CommandMap to the default by + * calling this method with null. + * + * @param commandMap The new default CommandMap. + * @exception SecurityException if the caller doesn't have permission + * to change the default + */ + public static void setDefaultCommandMap(CommandMap commandMap) { + SecurityManager security = System.getSecurityManager(); + if (security != null) { + try { + // if it's ok with the SecurityManager, it's ok with me... + security.checkSetFactory(); + } catch (SecurityException ex) { + // otherwise, we also allow it if this code and the + // factory come from the same class loader (e.g., + // the JAF classes were loaded with the applet classes). + if (CommandMap.class.getClassLoader() != + commandMap.getClass().getClassLoader()) + throw ex; + } + } + defaultCommandMap = commandMap; + } + + /** + * Get the preferred command list from a MIME Type. The actual semantics + * are determined by the implementation of the CommandMap. + * + * @param mimeType the MIME type + * @return the CommandInfo classes that represent the command Beans. + */ + abstract public CommandInfo[] getPreferredCommands(String mimeType); + + /** + * Get the preferred command list from a MIME Type. The actual semantics + * are determined by the implementation of the CommandMap.

+ * + * The DataSource provides extra information, such as + * the file name, that a CommandMap implementation may use to further + * refine the list of commands that are returned. The implementation + * in this class simply calls the getPreferredCommands + * method that ignores this argument. + * + * @param mimeType the MIME type + * @param ds a DataSource for the data + * @return the CommandInfo classes that represent the command Beans. + * @since JAF 1.1 + */ + public CommandInfo[] getPreferredCommands(String mimeType, DataSource ds) { + return getPreferredCommands(mimeType); + } + + /** + * Get all the available commands for this type. This method + * should return all the possible commands for this MIME type. + * + * @param mimeType the MIME type + * @return the CommandInfo objects representing all the commands. + */ + abstract public CommandInfo[] getAllCommands(String mimeType); + + /** + * Get all the available commands for this type. This method + * should return all the possible commands for this MIME type.

+ * + * The DataSource provides extra information, such as + * the file name, that a CommandMap implementation may use to further + * refine the list of commands that are returned. The implementation + * in this class simply calls the getAllCommands + * method that ignores this argument. + * + * @param mimeType the MIME type + * @param ds a DataSource for the data + * @return the CommandInfo objects representing all the commands. + * @since JAF 1.1 + */ + public CommandInfo[] getAllCommands(String mimeType, DataSource ds) { + return getAllCommands(mimeType); + } + + /** + * Get the default command corresponding to the MIME type. + * + * @param mimeType the MIME type + * @param cmdName the command name + * @return the CommandInfo corresponding to the command. + */ + abstract public CommandInfo getCommand(String mimeType, String cmdName); + + /** + * Get the default command corresponding to the MIME type.

+ * + * The DataSource provides extra information, such as + * the file name, that a CommandMap implementation may use to further + * refine the command that is chosen. The implementation + * in this class simply calls the getCommand + * method that ignores this argument. + * + * @param mimeType the MIME type + * @param cmdName the command name + * @param ds a DataSource for the data + * @return the CommandInfo corresponding to the command. + * @since JAF 1.1 + */ + public CommandInfo getCommand(String mimeType, String cmdName, + DataSource ds) { + return getCommand(mimeType, cmdName); + } + + /** + * Locate a DataContentHandler that corresponds to the MIME type. + * The mechanism and semantics for determining this are determined + * by the implementation of the particular CommandMap. + * + * @param mimeType the MIME type + * @return the DataContentHandler for the MIME type + */ + abstract public DataContentHandler createDataContentHandler(String + mimeType); + + /** + * Locate a DataContentHandler that corresponds to the MIME type. + * The mechanism and semantics for determining this are determined + * by the implementation of the particular CommandMap.

+ * + * The DataSource provides extra information, such as + * the file name, that a CommandMap implementation may use to further + * refine the choice of DataContentHandler. The implementation + * in this class simply calls the createDataContentHandler + * method that ignores this argument. + * + * @param mimeType the MIME type + * @param ds a DataSource for the data + * @return the DataContentHandler for the MIME type + * @since JAF 1.1 + */ + public DataContentHandler createDataContentHandler(String mimeType, + DataSource ds) { + return createDataContentHandler(mimeType); + } + + /** + * Get all the MIME types known to this command map. + * If the command map doesn't support this operation, + * null is returned. + * + * @return array of MIME types as strings, or null if not supported + * @since JAF 1.1 + */ + public String[] getMimeTypes() { + return null; + } +} diff --git a/jaxws/src/share/jaf_classes/javax/activation/CommandObject.java b/jaxws/src/share/jaf_classes/javax/activation/CommandObject.java new file mode 100644 index 00000000000..3f7edd847d6 --- /dev/null +++ b/jaxws/src/share/jaf_classes/javax/activation/CommandObject.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 1997, 2005, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package javax.activation; + +import java.io.IOException; + +/** + * JavaBeans components that are Activation Framework aware implement + * this interface to find out which command verb they're being asked + * to perform, and to obtain the DataHandler representing the + * data they should operate on. JavaBeans that don't implement + * this interface may be used as well. Such commands may obtain + * the data using the Externalizable interface, or using an + * application-specific method.

+ * + * @since 1.6 + */ +public interface CommandObject { + + /** + * Initialize the Command with the verb it is requested to handle + * and the DataHandler that describes the data it will + * operate on. NOTE: it is acceptable for the caller + * to pass null as the value for DataHandler. + * + * @param verb The Command Verb this object refers to. + * @param dh The DataHandler. + */ + public void setCommandContext(String verb, DataHandler dh) + throws IOException; +} diff --git a/jaxws/src/share/jaf_classes/javax/activation/DataContentHandler.java b/jaxws/src/share/jaf_classes/javax/activation/DataContentHandler.java new file mode 100644 index 00000000000..ef87142863d --- /dev/null +++ b/jaxws/src/share/jaf_classes/javax/activation/DataContentHandler.java @@ -0,0 +1,101 @@ +/* + * Copyright (c) 1997, 2005, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package javax.activation; + +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.UnsupportedFlavorException; +import java.io.InputStream; +import java.io.IOException; +import java.io.OutputStream; +import javax.activation.DataSource; + +/** + * The DataContentHandler interface is implemented by objects that can + * be used to extend the capabilities of the DataHandler's implementation + * of the Transferable interface. Through DataContentHandlers + * the framework can be extended to convert streams in to objects, and + * to write objects to streams.

+ * + * Applications don't generally call the methods in DataContentHandlers + * directly. Instead, an application calls the equivalent methods in + * DataHandler. The DataHandler will attempt to find an appropriate + * DataContentHandler that corresponds to its MIME type using the + * current DataContentHandlerFactory. The DataHandler then calls + * through to the methods in the DataContentHandler. + * + * @since 1.6 + */ + +public interface DataContentHandler { + /** + * 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(); + + /** + * 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. + * @exception UnsupportedFlavorException if the handler doesn't + * support the requested flavor + * @exception IOException if the data can't be accessed + */ + public Object getTransferData(DataFlavor df, DataSource ds) + throws UnsupportedFlavorException, IOException; + + /** + * 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 getTransferDataFlavors method. + * + * @param ds The DataSource representing the data to be converted. + * @return The constructed Object. + * @exception IOException if the data can't be accessed + */ + public Object getContent(DataSource ds) throws IOException; + + /** + * 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 mimeType The requested MIME type of the resulting byte stream. + * @param os The output stream into which to write the converted + * byte stream. + * @exception IOException errors writing to the stream + */ + public void writeTo(Object obj, String mimeType, OutputStream os) + throws IOException; +} diff --git a/jaxws/src/share/jaf_classes/javax/activation/DataContentHandlerFactory.java b/jaxws/src/share/jaf_classes/javax/activation/DataContentHandlerFactory.java new file mode 100644 index 00000000000..78f70058fa0 --- /dev/null +++ b/jaxws/src/share/jaf_classes/javax/activation/DataContentHandlerFactory.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 1997, 2005, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package javax.activation; + +/** + * This interface defines a factory for DataContentHandlers. An + * implementation of this interface should map a MIME type into an + * instance of DataContentHandler. The design pattern for classes implementing + * this interface is the same as for the ContentHandler mechanism used in + * java.net.URL. + * + * @since 1.6 + */ + +public interface DataContentHandlerFactory { + + /** + * Creates a new DataContentHandler object for the MIME type. + * + * @param mimeType the MIME type to create the DataContentHandler for. + * @return The new DataContentHandler, or null + * if none are found. + */ + public DataContentHandler createDataContentHandler(String mimeType); +} diff --git a/jaxws/src/share/jaf_classes/javax/activation/DataHandler.java b/jaxws/src/share/jaf_classes/javax/activation/DataHandler.java new file mode 100644 index 00000000000..28038560ea2 --- /dev/null +++ b/jaxws/src/share/jaf_classes/javax/activation/DataHandler.java @@ -0,0 +1,894 @@ +/* + * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package javax.activation; + +import java.io.InputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.io.PipedInputStream; +import java.io.PipedOutputStream; +import java.io.OutputStreamWriter; +import java.net.URL; +import java.awt.datatransfer.Transferable; +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.UnsupportedFlavorException; + +/** + * The DataHandler class provides a consistent interface to data + * available in many different sources and formats. + * It manages simple stream to string conversions and related operations + * using DataContentHandlers. + * It provides access to commands that can operate on the data. + * The commands are found using a CommandMap.

+ * + * DataHandler and the Transferable Interface

+ * DataHandler implements the Transferable interface so that data can + * be used in AWT data transfer operations, such as cut and paste and + * drag and drop. The implementation of the Transferable interface + * relies on the availability of an installed DataContentHandler + * object corresponding to the MIME type of the data represented in + * the specific instance of the DataHandler.

+ * + * DataHandler and CommandMaps

+ * The DataHandler keeps track of the current CommandMap that it uses to + * service requests for commands (getCommand, + * getAllCommands, getPreferredCommands). + * Each instance of a DataHandler may have a CommandMap associated with + * it using the setCommandMap method. If a CommandMap was + * not set, DataHandler calls the getDefaultCommandMap + * method in CommandMap and uses the value it returns. See + * CommandMap for more information.

+ * + * DataHandler and URLs

+ * The current DataHandler implementation creates a private + * instance of URLDataSource when it is constructed with a URL. + * + * @see javax.activation.CommandMap + * @see javax.activation.DataContentHandler + * @see javax.activation.DataSource + * @see javax.activation.URLDataSource + * + * @since 1.6 + */ + +public class DataHandler implements Transferable { + + // Use the datasource to indicate whether we were started via the + // DataSource constructor or the object constructor. + private DataSource dataSource = null; + private DataSource objDataSource = null; + + // The Object and mimetype from the constructor (if passed in). + // object remains null if it was instantiated with a + // DataSource. + private Object object = null; + private String objectMimeType = null; + + // Keep track of the CommandMap + private CommandMap currentCommandMap = null; + + // our transfer flavors + private static final DataFlavor emptyFlavors[] = new DataFlavor[0]; + private DataFlavor transferFlavors[] = emptyFlavors; + + // our DataContentHandler + private DataContentHandler dataContentHandler = null; + private DataContentHandler factoryDCH = null; + + // our DataContentHandlerFactory + private static DataContentHandlerFactory factory = null; + private DataContentHandlerFactory oldFactory = null; + // the short representation of the ContentType (sans params) + private String shortType = null; + + /** + * Create a DataHandler instance referencing the + * specified DataSource. The data exists in a byte stream form. + * The DataSource will provide an InputStream to access the data. + * + * @param ds the DataSource + */ + public DataHandler(DataSource ds) { + // save a reference to the incoming DS + dataSource = ds; + oldFactory = factory; // keep track of the factory + } + + /** + * Create a DataHandler instance representing an object + * of this MIME type. This constructor is + * used when the application already has an in-memory representation + * of the data in the form of a Java Object. + * + * @param obj the Java Object + * @param mimeType the MIME type of the object + */ + public DataHandler(Object obj, String mimeType) { + object = obj; + objectMimeType = mimeType; + oldFactory = factory; // keep track of the factory + } + + /** + * Create a DataHandler instance referencing a URL. + * The DataHandler internally creates a URLDataSource + * instance to represent the URL. + * + * @param url a URL object + */ + public DataHandler(URL url) { + dataSource = new URLDataSource(url); + oldFactory = factory; // keep track of the factory + } + + /** + * Return the CommandMap for this instance of DataHandler. + */ + private synchronized CommandMap getCommandMap() { + if (currentCommandMap != null) + return currentCommandMap; + else + return CommandMap.getDefaultCommandMap(); + } + + /** + * Return the DataSource associated with this instance + * of DataHandler. + *

+ * For DataHandlers that have been instantiated with a DataSource, + * this method returns the DataSource that was used to create the + * DataHandler object. In other cases the DataHandler + * constructs a DataSource from the data used to construct + * the DataHandler. DataSources created for DataHandlers not + * instantiated with a DataSource are cached for performance + * reasons. + * + * @return a valid DataSource object for this DataHandler + */ + public DataSource getDataSource() { + if (dataSource == null) { + // create one on the fly + if (objDataSource == null) + objDataSource = new DataHandlerDataSource(this); + return objDataSource; + } + return dataSource; + } + + /** + * Return the name of the data object. If this DataHandler + * was created with a DataSource, this method calls through + * to the DataSource.getName method, otherwise it + * returns null. + * + * @return the name of the object + */ + public String getName() { + if (dataSource != null) + return dataSource.getName(); + else + return null; + } + + /** + * Return the MIME type of this object as retrieved from + * the source object. Note that this is the full + * type with parameters. + * + * @return the MIME type + */ + public String getContentType() { + if (dataSource != null) // data source case + return dataSource.getContentType(); + else + return objectMimeType; // obj/type case + } + + /** + * Get the InputStream for this object.

+ * + * For DataHandlers instantiated with a DataSource, the DataHandler + * calls the DataSource.getInputStream method and + * returns the result to the caller. + *

+ * For DataHandlers instantiated with an Object, the DataHandler + * first attempts to find a DataContentHandler for the Object. If + * the DataHandler can not find a DataContentHandler for this MIME + * type, it throws an UnsupportedDataTypeException. If it is + * successful, it creates a pipe and a thread. The thread uses the + * DataContentHandler's writeTo method to write the + * stream data into one end of the pipe. The other end of the pipe + * is returned to the caller. Because a thread is created to copy + * the data, IOExceptions that may occur during the copy can not be + * propagated back to the caller. The result is an empty stream.

+ * + * @return the InputStream representing this data + * @exception IOException if an I/O error occurs + * + * @see javax.activation.DataContentHandler#writeTo + * @see javax.activation.UnsupportedDataTypeException + */ + public InputStream getInputStream() throws IOException { + InputStream ins = null; + + if (dataSource != null) { + ins = dataSource.getInputStream(); + } else { + DataContentHandler dch = getDataContentHandler(); + // we won't even try if we can't get a dch + if (dch == null) + throw new UnsupportedDataTypeException( + "no DCH for MIME type " + getBaseType()); + + if (dch instanceof ObjectDataContentHandler) { + if (((ObjectDataContentHandler)dch).getDCH() == null) + throw new UnsupportedDataTypeException( + "no object DCH for MIME type " + getBaseType()); + } + // there is none but the default^^^^^^^^^^^^^^^^ + final DataContentHandler fdch = dch; + + // from bill s. + // ce n'est pas une pipe! + // + // NOTE: This block of code needs to throw exceptions, but + // can't because it is in another thread!!! ARG! + // + final PipedOutputStream pos = new PipedOutputStream(); + PipedInputStream pin = new PipedInputStream(pos); + new Thread( + new Runnable() { + public void run() { + try { + fdch.writeTo(object, objectMimeType, pos); + } catch (IOException e) { + + } finally { + try { + pos.close(); + } catch (IOException ie) { } + } + } + }, + "DataHandler.getInputStream").start(); + ins = pin; + } + + return ins; + } + + /** + * Write the data to an OutputStream.

+ * + * If the DataHandler was created with a DataSource, writeTo + * retrieves the InputStream and copies the bytes from the + * InputStream to the OutputStream passed in. + *

+ * If the DataHandler was created with an object, writeTo + * retrieves the DataContentHandler for the object's type. + * If the DataContentHandler was found, it calls the + * writeTo method on the DataContentHandler. + * + * @param os the OutputStream to write to + * @exception IOException if an I/O error occurs + */ + public void writeTo(OutputStream os) throws IOException { + // for the DataSource case + if (dataSource != null) { + InputStream is = null; + byte data[] = new byte[8*1024]; + int bytes_read; + + is = dataSource.getInputStream(); + + try { + while ((bytes_read = is.read(data)) > 0) { + os.write(data, 0, bytes_read); + } + } finally { + is.close(); + is = null; + } + } else { // for the Object case + DataContentHandler dch = getDataContentHandler(); + dch.writeTo(object, objectMimeType, os); + } + } + + /** + * Get an OutputStream for this DataHandler to allow overwriting + * the underlying data. + * If the DataHandler was created with a DataSource, the + * DataSource's getOutputStream method is called. + * Otherwise, null is returned. + * + * @return the OutputStream + * + * @see javax.activation.DataSource#getOutputStream + * @see javax.activation.URLDataSource + */ + public OutputStream getOutputStream() throws IOException { + if (dataSource != null) + return dataSource.getOutputStream(); + else + return null; + } + + /** + * Return the DataFlavors in which this data is available.

+ * + * Returns an array of DataFlavor objects indicating the flavors + * the data can be provided in. The array is usually ordered + * according to preference for providing the data, from most + * richly descriptive to least richly descriptive.

+ * + * The DataHandler attempts to find a DataContentHandler that + * corresponds to the MIME type of the data. If one is located, + * the DataHandler calls the DataContentHandler's + * getTransferDataFlavors method.

+ * + * If a DataContentHandler can not be located, and if the + * DataHandler was created with a DataSource (or URL), one + * DataFlavor is returned that represents this object's MIME type + * and the java.io.InputStream class. If the + * DataHandler was created with an object and a MIME type, + * getTransferDataFlavors returns one DataFlavor that represents + * this object's MIME type and the object's class. + * + * @return an array of data flavors in which this data can be transferred + * @see javax.activation.DataContentHandler#getTransferDataFlavors + */ + public synchronized DataFlavor[] getTransferDataFlavors() { + if (factory != oldFactory) // if the factory has changed, clear cache + transferFlavors = emptyFlavors; + + // if it's not set, set it... + if (transferFlavors == emptyFlavors) + transferFlavors = getDataContentHandler().getTransferDataFlavors(); + return transferFlavors; + } + + /** + * Returns whether the specified data flavor is supported + * for this object.

+ * + * This method iterates through the DataFlavors returned from + * getTransferDataFlavors, comparing each with + * the specified flavor. + * + * @param flavor the requested flavor for the data + * @return true if the data flavor is supported + * @see javax.activation.DataHandler#getTransferDataFlavors + */ + public boolean isDataFlavorSupported(DataFlavor flavor) { + DataFlavor[] lFlavors = getTransferDataFlavors(); + + for (int i = 0; i < lFlavors.length; i++) { + if (lFlavors[i].equals(flavor)) + return true; + } + return false; + } + + /** + * Returns an object that represents the data to be + * transferred. The class of the object returned is defined by the + * representation class of the data flavor.

+ * + * For DataHandler's created with DataSources or URLs:

+ * + * The DataHandler attempts to locate a DataContentHandler + * for this MIME type. If one is found, the passed in DataFlavor + * and the type of the data are passed to its getTransferData + * method. If the DataHandler fails to locate a DataContentHandler + * and the flavor specifies this object's MIME type and the + * java.io.InputStream class, this object's InputStream + * is returned. + * Otherwise it throws an UnsupportedFlavorException.

+ * + * For DataHandler's created with Objects:

+ * + * The DataHandler attempts to locate a DataContentHandler + * for this MIME type. If one is found, the passed in DataFlavor + * and the type of the data are passed to its getTransferData + * method. If the DataHandler fails to locate a DataContentHandler + * and the flavor specifies this object's MIME type and its class, + * this DataHandler's referenced object is returned. + * Otherwise it throws an UnsupportedFlavorException. + * + * @param flavor the requested flavor for the data + * @return the object + * @exception UnsupportedFlavorException if the data could not be + * converted to the requested flavor + * @exception IOException if an I/O error occurs + * @see javax.activation.ActivationDataFlavor + */ + public Object getTransferData(DataFlavor flavor) + throws UnsupportedFlavorException, IOException { + return getDataContentHandler().getTransferData(flavor, dataSource); + } + + /** + * Set the CommandMap for use by this DataHandler. + * Setting it to null causes the CommandMap to revert + * to the CommandMap returned by the + * CommandMap.getDefaultCommandMap method. + * Changing the CommandMap, or setting it to null, + * clears out any data cached from the previous CommandMap. + * + * @param commandMap the CommandMap to use in this DataHandler + * + * @see javax.activation.CommandMap#setDefaultCommandMap + */ + public synchronized void setCommandMap(CommandMap commandMap) { + if (commandMap != currentCommandMap || commandMap == null) { + // clear cached values... + transferFlavors = emptyFlavors; + dataContentHandler = null; + + currentCommandMap = commandMap; + } + } + + /** + * Return the preferred commands for this type of data. + * This method calls the getPreferredCommands method + * in the CommandMap associated with this instance of DataHandler. + * This method returns an array that represents a subset of + * available commands. In cases where multiple commands for the + * MIME type represented by this DataHandler are present, the + * installed CommandMap chooses the appropriate commands. + * + * @return the CommandInfo objects representing the preferred commands + * + * @see javax.activation.CommandMap#getPreferredCommands + */ + public CommandInfo[] getPreferredCommands() { + if (dataSource != null) + return getCommandMap().getPreferredCommands(getBaseType(), + dataSource); + else + return getCommandMap().getPreferredCommands(getBaseType()); + } + + /** + * Return all the commands for this type of data. + * This method returns an array containing all commands + * for the type of data represented by this DataHandler. The + * MIME type for the underlying data represented by this DataHandler + * is used to call through to the getAllCommands method + * of the CommandMap associated with this DataHandler. + * + * @return the CommandInfo objects representing all the commands + * + * @see javax.activation.CommandMap#getAllCommands + */ + public CommandInfo[] getAllCommands() { + if (dataSource != null) + return getCommandMap().getAllCommands(getBaseType(), dataSource); + else + return getCommandMap().getAllCommands(getBaseType()); + } + + /** + * Get the command cmdName. Use the search semantics as + * defined by the CommandMap installed in this DataHandler. The + * MIME type for the underlying data represented by this DataHandler + * is used to call through to the getCommand method + * of the CommandMap associated with this DataHandler. + * + * @param cmdName the command name + * @return the CommandInfo corresponding to the command + * + * @see javax.activation.CommandMap#getCommand + */ + public CommandInfo getCommand(String cmdName) { + if (dataSource != null) + return getCommandMap().getCommand(getBaseType(), cmdName, + dataSource); + else + return getCommandMap().getCommand(getBaseType(), cmdName); + } + + /** + * Return the data in its preferred Object form.

+ * + * If the DataHandler was instantiated with an object, return + * the object.

+ * + * If the DataHandler was instantiated with a DataSource, + * this method uses a DataContentHandler to return the content + * object for the data represented by this DataHandler. If no + * DataContentHandler can be found for the + * the type of this data, the DataHandler returns an + * InputStream for the data. + * + * @return the content. + * @exception IOException if an IOException occurs during + * this operation. + */ + public Object getContent() throws IOException { + if (object != null) + return object; + else + return getDataContentHandler().getContent(getDataSource()); + } + + /** + * A convenience method that takes a CommandInfo object + * and instantiates the corresponding command, usually + * a JavaBean component. + *

+ * This method calls the CommandInfo's getCommandObject + * method with the ClassLoader used to load + * the javax.activation.DataHandler class itself. + * + * @param cmdinfo the CommandInfo corresponding to a command + * @return the instantiated command object + */ + public Object getBean(CommandInfo cmdinfo) { + Object bean = null; + + try { + // make the bean + ClassLoader cld = null; + // First try the "application's" class loader. + cld = SecuritySupport.getContextClassLoader(); + if (cld == null) + cld = this.getClass().getClassLoader(); + bean = cmdinfo.getCommandObject(this, cld); + } catch (IOException e) { + } catch (ClassNotFoundException e) { } + + return bean; + } + + /** + * Get the DataContentHandler for this DataHandler:

+ * + * If a DataContentHandlerFactory is set, use it. + * Otherwise look for an object to serve DCH in the + * following order:

+ * + * 1) if a factory is set, use it

+ * 2) if a CommandMap is set, use it

+ * 3) use the default CommandMap

+ * + * In any case, wrap the real DataContentHandler with one of our own + * to handle any missing cases, fill in defaults, and to ensure that + * we always have a non-null DataContentHandler. + * + * @return the requested DataContentHandler + */ + private synchronized DataContentHandler getDataContentHandler() { + + // make sure the factory didn't change + if (factory != oldFactory) { + oldFactory = factory; + factoryDCH = null; + dataContentHandler = null; + transferFlavors = emptyFlavors; + } + + if (dataContentHandler != null) + return dataContentHandler; + + String simpleMT = getBaseType(); + + if (factoryDCH == null && factory != null) + factoryDCH = factory.createDataContentHandler(simpleMT); + + if (factoryDCH != null) + dataContentHandler = factoryDCH; + + if (dataContentHandler == null) { + if (dataSource != null) + dataContentHandler = getCommandMap(). + createDataContentHandler(simpleMT, dataSource); + else + dataContentHandler = getCommandMap(). + createDataContentHandler(simpleMT); + } + + // getDataContentHandler always uses these 'wrapper' handlers + // to make sure it returns SOMETHING meaningful... + if (dataSource != null) + dataContentHandler = new DataSourceDataContentHandler( + dataContentHandler, + dataSource); + else + dataContentHandler = new ObjectDataContentHandler( + dataContentHandler, + object, + objectMimeType); + return dataContentHandler; + } + + /** + * Use the MimeType class to extract the MIME type/subtype, + * ignoring the parameters. The type is cached. + */ + private synchronized String getBaseType() { + if (shortType == null) { + String ct = getContentType(); + try { + MimeType mt = new MimeType(ct); + shortType = mt.getBaseType(); + } catch (MimeTypeParseException e) { + shortType = ct; + } + } + return shortType; + } + + /** + * Sets the DataContentHandlerFactory. The DataContentHandlerFactory + * is called first to find DataContentHandlers. + * The DataContentHandlerFactory can only be set once. + *

+ * If the DataContentHandlerFactory has already been set, + * this method throws an Error. + * + * @param newFactory the DataContentHandlerFactory + * @exception Error if the factory has already been defined. + * + * @see javax.activation.DataContentHandlerFactory + */ + public static synchronized void setDataContentHandlerFactory( + DataContentHandlerFactory newFactory) { + if (factory != null) + throw new Error("DataContentHandlerFactory already defined"); + + SecurityManager security = System.getSecurityManager(); + if (security != null) { + try { + // if it's ok with the SecurityManager, it's ok with me... + security.checkSetFactory(); + } catch (SecurityException ex) { + // otherwise, we also allow it if this code and the + // factory come from the same class loader (e.g., + // the JAF classes were loaded with the applet classes). + if (DataHandler.class.getClassLoader() != + newFactory.getClass().getClassLoader()) + throw ex; + } + } + factory = newFactory; + } +} + +/** + * The DataHanderDataSource class implements the + * DataSource interface when the DataHandler is constructed + * with an Object and a mimeType string. + */ +class DataHandlerDataSource implements DataSource { + DataHandler dataHandler = null; + + /** + * The constructor. + */ + public DataHandlerDataSource(DataHandler dh) { + this.dataHandler = dh; + } + + /** + * Returns an InputStream representing this object. + * @return the InputStream + */ + public InputStream getInputStream() throws IOException { + return dataHandler.getInputStream(); + } + + /** + * Returns the OutputStream for this object. + * @return the OutputStream + */ + public OutputStream getOutputStream() throws IOException { + return dataHandler.getOutputStream(); + } + + /** + * Returns the MIME type of the data represented by this object. + * @return the MIME type + */ + public String getContentType() { + return dataHandler.getContentType(); + } + + /** + * Returns the name of this object. + * @return the name of this object + */ + public String getName() { + return dataHandler.getName(); // what else would it be? + } +} + +/* + * DataSourceDataContentHandler + * + * This is a private DataContentHandler that wraps the real + * DataContentHandler in the case where the DataHandler was instantiated + * with a DataSource. + */ +class DataSourceDataContentHandler implements DataContentHandler { + private DataSource ds = null; + private DataFlavor transferFlavors[] = null; + private DataContentHandler dch = null; + + /** + * The constructor. + */ + public DataSourceDataContentHandler(DataContentHandler dch, DataSource ds) { + this.ds = ds; + this.dch = dch; + } + + /** + * Return the DataFlavors for this DataContentHandler. + * @return the DataFlavors + */ + public DataFlavor[] getTransferDataFlavors() { + + if (transferFlavors == null) { + if (dch != null) { // is there a dch? + transferFlavors = dch.getTransferDataFlavors(); + } else { + transferFlavors = new DataFlavor[1]; + transferFlavors[0] = + new ActivationDataFlavor(ds.getContentType(), + ds.getContentType()); + } + } + return transferFlavors; + } + + /** + * Return the Transfer Data of type DataFlavor from InputStream. + * @param df the DataFlavor + * @param ds the DataSource + * @return the constructed Object + */ + public Object getTransferData(DataFlavor df, DataSource ds) throws + UnsupportedFlavorException, IOException { + + if (dch != null) + return dch.getTransferData(df, ds); + else if (df.equals(getTransferDataFlavors()[0])) // only have one now + return ds.getInputStream(); + else + throw new UnsupportedFlavorException(df); + } + + public Object getContent(DataSource ds) throws IOException { + + if (dch != null) + return dch.getContent(ds); + else + return ds.getInputStream(); + } + + /** + * Write the object to the output stream. + */ + public void writeTo(Object obj, String mimeType, OutputStream os) + throws IOException { + if (dch != null) + dch.writeTo(obj, mimeType, os); + else + throw new UnsupportedDataTypeException( + "no DCH for content type " + ds.getContentType()); + } +} + +/* + * ObjectDataContentHandler + * + * This is a private DataContentHandler that wraps the real + * DataContentHandler in the case where the DataHandler was instantiated + * with an object. + */ +class ObjectDataContentHandler implements DataContentHandler { + private DataFlavor transferFlavors[] = null; + private Object obj; + private String mimeType; + private DataContentHandler dch = null; + + /** + * The constructor. + */ + public ObjectDataContentHandler(DataContentHandler dch, + Object obj, String mimeType) { + this.obj = obj; + this.mimeType = mimeType; + this.dch = dch; + } + + /** + * Return the DataContentHandler for this object. + * Used only by the DataHandler class. + */ + public DataContentHandler getDCH() { + return dch; + } + + /** + * Return the DataFlavors for this DataContentHandler. + * @return the DataFlavors + */ + public synchronized DataFlavor[] getTransferDataFlavors() { + if (transferFlavors == null) { + if (dch != null) { + transferFlavors = dch.getTransferDataFlavors(); + } else { + transferFlavors = new DataFlavor[1]; + transferFlavors[0] = new ActivationDataFlavor(obj.getClass(), + mimeType, mimeType); + } + } + return transferFlavors; + } + + /** + * Return the Transfer Data of type DataFlavor from InputStream. + * @param df the DataFlavor + * @param ds the DataSource + * @return the constructed Object + */ + public Object getTransferData(DataFlavor df, DataSource ds) + throws UnsupportedFlavorException, IOException { + + if (dch != null) + return dch.getTransferData(df, ds); + else if (df.equals(getTransferDataFlavors()[0])) // only have one now + return obj; + else + throw new UnsupportedFlavorException(df); + + } + + public Object getContent(DataSource ds) { + return obj; + } + + /** + * Write the object to the output stream. + */ + public void writeTo(Object obj, String mimeType, OutputStream os) + throws IOException { + if (dch != null) + dch.writeTo(obj, mimeType, os); + else if (obj instanceof byte[]) + os.write((byte[])obj); + else if (obj instanceof String) { + OutputStreamWriter osw = new OutputStreamWriter(os); + osw.write((String)obj); + osw.flush(); + } else throw new UnsupportedDataTypeException( + "no object DCH for MIME type " + this.mimeType); + } +} diff --git a/jaxws/src/share/jaf_classes/javax/activation/DataSource.java b/jaxws/src/share/jaf_classes/javax/activation/DataSource.java new file mode 100644 index 00000000000..340daaafd8b --- /dev/null +++ b/jaxws/src/share/jaf_classes/javax/activation/DataSource.java @@ -0,0 +1,86 @@ +/* + * Copyright (c) 1997, 2005, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package javax.activation; + +import java.io.InputStream; +import java.io.OutputStream; +import java.io.IOException; + +/** + * The DataSource interface provides the JavaBeans Activation Framework + * with an abstraction of an arbitrary collection of data. It + * provides a type for that data as well as access + * to it in the form of InputStreams and + * OutputStreams where appropriate. + * + * @since 1.6 + */ + +public interface DataSource { + + /** + * This method returns an InputStream representing + * the data and throws the appropriate exception if it can + * not do so. Note that a new InputStream object must be + * returned each time this method is called, and the stream must be + * positioned at the beginning of the data. + * + * @return an InputStream + */ + public InputStream getInputStream() throws IOException; + + /** + * This method returns an OutputStream where the + * data can be written and throws the appropriate exception if it can + * not do so. Note that a new OutputStream object must + * be returned each time this method is called, and the stream must + * be positioned at the location the data is to be written. + * + * @return an OutputStream + */ + public OutputStream getOutputStream() throws IOException; + + /** + * This method returns the MIME type of the data in the form of a + * string. It should always return a valid type. It is suggested + * that getContentType return "application/octet-stream" if the + * DataSource implementation can not determine the data type. + * + * @return the MIME Type + */ + public String getContentType(); + + /** + * Return the name of this object where the name of the object + * is dependant on the nature of the underlying objects. DataSources + * encapsulating files may choose to return the filename of the object. + * (Typically this would be the last component of the filename, not an + * entire pathname.) + * + * @return the name of the object. + */ + public String getName(); +} diff --git a/jaxws/src/share/jaf_classes/javax/activation/FileDataSource.java b/jaxws/src/share/jaf_classes/javax/activation/FileDataSource.java new file mode 100644 index 00000000000..7d4d84fc5e4 --- /dev/null +++ b/jaxws/src/share/jaf_classes/javax/activation/FileDataSource.java @@ -0,0 +1,158 @@ +/* + * Copyright (c) 1997, 2005, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package javax.activation; + +import java.io.InputStream; +import java.io.OutputStream; +import java.io.File; +import java.io.FileDescriptor; +import java.io.FileNotFoundException; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import com.sun.activation.registries.MimeTypeFile; + +/** + * The FileDataSource class implements a simple DataSource object + * that encapsulates a file. It provides data typing services via + * a FileTypeMap object.

+ * + * FileDataSource Typing Semantics

+ * + * The FileDataSource class delegates data typing of files + * to an object subclassed from the FileTypeMap class. + * The setFileTypeMap method can be used to explicitly + * set the FileTypeMap for an instance of FileDataSource. If no + * FileTypeMap is set, the FileDataSource will call the FileTypeMap's + * getDefaultFileTypeMap method to get the System's default FileTypeMap. + * + * @see javax.activation.DataSource + * @see javax.activation.FileTypeMap + * @see javax.activation.MimetypesFileTypeMap + * + * @since 1.6 + */ +public class FileDataSource implements DataSource { + + // keep track of original 'ref' passed in, non-null + // one indicated which was passed in: + private File _file = null; + private FileTypeMap typeMap = null; + + /** + * Creates a FileDataSource from a File object. Note: + * The file will not actually be opened until a method is + * called that requires the file to be opened. + * + * @param file the file + */ + public FileDataSource(File file) { + _file = file; // save the file Object... + } + + /** + * Creates a FileDataSource from + * the specified path name. Note: + * The file will not actually be opened until a method is + * called that requires the file to be opened. + * + * @param name the system-dependent file name. + */ + public FileDataSource(String name) { + this(new File(name)); // use the file constructor + } + + /** + * This method will return an InputStream representing the + * the data and will throw an IOException if it can + * not do so. This method will return a new + * instance of InputStream with each invocation. + * + * @return an InputStream + */ + public InputStream getInputStream() throws IOException { + return new FileInputStream(_file); + } + + /** + * This method will return an OutputStream representing the + * the data and will throw an IOException if it can + * not do so. This method will return a new instance of + * OutputStream with each invocation. + * + * @return an OutputStream + */ + public OutputStream getOutputStream() throws IOException { + return new FileOutputStream(_file); + } + + /** + * This method returns the MIME type of the data in the form of a + * string. This method uses the currently installed FileTypeMap. If + * there is no FileTypeMap explictly set, the FileDataSource will + * call the getDefaultFileTypeMap method on + * FileTypeMap to acquire a default FileTypeMap. Note: By + * default, the FileTypeMap used will be a MimetypesFileTypeMap. + * + * @return the MIME Type + * @see javax.activation.FileTypeMap#getDefaultFileTypeMap + */ + public String getContentType() { + // check to see if the type map is null? + if (typeMap == null) + return FileTypeMap.getDefaultFileTypeMap().getContentType(_file); + else + return typeMap.getContentType(_file); + } + + /** + * Return the name of this object. The FileDataSource + * will return the file name of the object. + * + * @return the name of the object. + * @see javax.activation.DataSource + */ + public String getName() { + return _file.getName(); + } + + /** + * Return the File object that corresponds to this FileDataSource. + * @return the File object for the file represented by this object. + */ + public File getFile() { + return _file; + } + + /** + * Set the FileTypeMap to use with this FileDataSource + * + * @param map The FileTypeMap for this object. + */ + public void setFileTypeMap(FileTypeMap map) { + typeMap = map; + } +} diff --git a/jaxws/src/share/jaf_classes/javax/activation/FileTypeMap.java b/jaxws/src/share/jaf_classes/javax/activation/FileTypeMap.java new file mode 100644 index 00000000000..17e3d7f4853 --- /dev/null +++ b/jaxws/src/share/jaf_classes/javax/activation/FileTypeMap.java @@ -0,0 +1,118 @@ +/* + * Copyright (c) 1997, 2005, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package javax.activation; + +import java.io.File; + +/** + * The FileTypeMap is an abstract class that provides a data typing + * interface for files. Implementations of this class will + * implement the getContentType methods which will derive a content + * type from a file name or a File object. FileTypeMaps could use any + * scheme to determine the data type, from examining the file extension + * of a file (like the MimetypesFileTypeMap) to opening the file and + * trying to derive its type from the contents of the file. The + * FileDataSource class uses the default FileTypeMap (a MimetypesFileTypeMap + * unless changed) to determine the content type of files. + * + * @see javax.activation.FileTypeMap + * @see javax.activation.FileDataSource + * @see javax.activation.MimetypesFileTypeMap + * + * @since 1.6 + */ + +public abstract class FileTypeMap { + + private static FileTypeMap defaultMap = null; + + /** + * The default constructor. + */ + public FileTypeMap() { + super(); + } + + /** + * Return the type of the file object. This method should + * always return a valid MIME type. + * + * @param file A file to be typed. + * @return The content type. + */ + abstract public String getContentType(File file); + + /** + * Return the type of the file passed in. This method should + * always return a valid MIME type. + * + * @param filename the pathname of the file. + * @return The content type. + */ + abstract public String getContentType(String filename); + + /** + * Sets the default FileTypeMap for the system. This instance + * will be returned to callers of getDefaultFileTypeMap. + * + * @param map The FileTypeMap. + * @exception SecurityException if the caller doesn't have permission + * to change the default + */ + public static void setDefaultFileTypeMap(FileTypeMap map) { + SecurityManager security = System.getSecurityManager(); + if (security != null) { + try { + // if it's ok with the SecurityManager, it's ok with me... + security.checkSetFactory(); + } catch (SecurityException ex) { + // otherwise, we also allow it if this code and the + // factory come from the same class loader (e.g., + // the JAF classes were loaded with the applet classes). + if (FileTypeMap.class.getClassLoader() != + map.getClass().getClassLoader()) + throw ex; + } + } + defaultMap = map; + } + + /** + * Return the default FileTypeMap for the system. + * If setDefaultFileTypeMap was called, return + * that instance, otherwise return an instance of + * MimetypesFileTypeMap. + * + * @return The default FileTypeMap + * @see javax.activation.FileTypeMap#setDefaultFileTypeMap + */ + public static FileTypeMap getDefaultFileTypeMap() { + // XXX - probably should be synchronized + if (defaultMap == null) + defaultMap = new MimetypesFileTypeMap(); + return defaultMap; + } +} diff --git a/jaxws/src/share/jaf_classes/javax/activation/MailcapCommandMap.java b/jaxws/src/share/jaf_classes/javax/activation/MailcapCommandMap.java new file mode 100644 index 00000000000..373014347be --- /dev/null +++ b/jaxws/src/share/jaf_classes/javax/activation/MailcapCommandMap.java @@ -0,0 +1,701 @@ +/* + * Copyright (c) 1997, 2005, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +package javax.activation; + +import java.util.*; +import java.io.*; +import java.net.*; +import com.sun.activation.registries.MailcapFile; +import com.sun.activation.registries.LogSupport; + +/** + * MailcapCommandMap extends the CommandMap + * abstract class. It implements a CommandMap whose configuration + * is based on mailcap files + * (RFC 1524). + * The MailcapCommandMap can be configured both programmatically + * and via configuration files. + *

+ * Mailcap file search order:

+ * The MailcapCommandMap looks in various places in the user's + * system for mailcap file entries. When requests are made + * to search for commands in the MailcapCommandMap, it searches + * mailcap files in the following order: + *

+ *

    + *
  1. Programatically added entries to the MailcapCommandMap instance. + *
  2. The file .mailcap in the user's home directory. + *
  3. The file <java.home>/lib/mailcap. + *
  4. The file or resources named META-INF/mailcap. + *
  5. The file or resource named META-INF/mailcap.default + * (usually found only in the activation.jar file). + *
+ *

+ * Mailcap file format:

+ * + * Mailcap files must conform to the mailcap + * file specification (RFC 1524, A User Agent Configuration Mechanism + * For Multimedia Mail Format Information). + * The file format consists of entries corresponding to + * particular MIME types. In general, the specification + * specifies applications for clients to use when they + * themselves cannot operate on the specified MIME type. The + * MailcapCommandMap extends this specification by using a parameter mechanism + * in mailcap files that allows JavaBeans(tm) components to be specified as + * corresponding to particular commands for a MIME type.

+ * + * When a mailcap file is + * parsed, the MailcapCommandMap recognizes certain parameter signatures, + * specifically those parameter names that begin with x-java-. + * The MailcapCommandMap uses this signature to find + * command entries for inclusion into its registries. + * Parameter names with the form x-java-<name> + * are read by the MailcapCommandMap as identifying a command + * with the name name. When the name is + * content-handler the MailcapCommandMap recognizes the class + * signified by this parameter as a DataContentHandler. + * All other commands are handled generically regardless of command + * name. The command implementation is specified by a fully qualified + * class name of a JavaBean(tm) component. For example; a command for viewing + * some data can be specified as: x-java-view=com.foo.ViewBean.

+ * + * When the command name is fallback-entry, the value of + * the command may be true or false. An + * entry for a MIME type that includes a parameter of + * x-java-fallback-entry=true defines fallback commands + * for that MIME type that will only be used if no non-fallback entry + * can be found. For example, an entry of the form text/*; ; + * x-java-fallback-entry=true; x-java-view=com.sun.TextViewer + * specifies a view command to be used for any text MIME type. This + * view command would only be used if a non-fallback view command for + * the MIME type could not be found.

+ * + * MailcapCommandMap aware mailcap files have the + * following general form:

+ * + * # Comments begin with a '#' and continue to the end of the line.
+ * <mime type>; ; <parameter list>
+ * # Where a parameter list consists of one or more parameters,
+ * # where parameters look like: x-java-view=com.sun.TextViewer
+ * # and a parameter list looks like:
+ * text/plain; ; x-java-view=com.sun.TextViewer; x-java-edit=com.sun.TextEdit + *
+ * # Note that mailcap entries that do not contain 'x-java' parameters
+ * # and comply to RFC 1524 are simply ignored:
+ * image/gif; /usr/dt/bin/sdtimage %s
+ * + *
+ *

+ * + * @author Bart Calder + * @author Bill Shannon + * + * @since 1.6 + */ + +public class MailcapCommandMap extends CommandMap { + /* + * We manage a collection of databases, searched in order. + * The default database is shared between all instances + * of this class. + * XXX - Can we safely share more databases between instances? + */ + private static MailcapFile defDB = null; + private MailcapFile[] DB; + private static final int PROG = 0; // programmatically added entries + + /** + * The default Constructor. + */ + public MailcapCommandMap() { + super(); + List dbv = new ArrayList(5); // usually 5 or less databases + MailcapFile mf = null; + dbv.add(null); // place holder for PROG entry + + LogSupport.log("MailcapCommandMap: load HOME"); + try { + String user_home = System.getProperty("user.home"); + + if (user_home != null) { + String path = user_home + File.separator + ".mailcap"; + mf = loadFile(path); + if (mf != null) + dbv.add(mf); + } + } catch (SecurityException ex) {} + + LogSupport.log("MailcapCommandMap: load SYS"); + try { + // check system's home + String system_mailcap = System.getProperty("java.home") + + File.separator + "lib" + File.separator + "mailcap"; + mf = loadFile(system_mailcap); + if (mf != null) + dbv.add(mf); + } catch (SecurityException ex) {} + + LogSupport.log("MailcapCommandMap: load JAR"); + // load from the app's jar file + loadAllResources(dbv, "META-INF/mailcap"); + + LogSupport.log("MailcapCommandMap: load DEF"); + synchronized (MailcapCommandMap.class) { + // see if another instance has created this yet. + if (defDB == null) + defDB = loadResource("/META-INF/mailcap.default"); + } + + if (defDB != null) + dbv.add(defDB); + + DB = new MailcapFile[dbv.size()]; + DB = (MailcapFile[])dbv.toArray(DB); + } + + /** + * Load from the named resource. + */ + private MailcapFile loadResource(String name) { + InputStream clis = null; + try { + clis = SecuritySupport.getResourceAsStream(this.getClass(), name); + if (clis != null) { + MailcapFile mf = new MailcapFile(clis); + if (LogSupport.isLoggable()) + LogSupport.log("MailcapCommandMap: successfully loaded " + + "mailcap file: " + name); + return mf; + } else { + if (LogSupport.isLoggable()) + LogSupport.log("MailcapCommandMap: not loading " + + "mailcap file: " + name); + } + } catch (IOException e) { + if (LogSupport.isLoggable()) + LogSupport.log("MailcapCommandMap: can't load " + name, e); + } catch (SecurityException sex) { + if (LogSupport.isLoggable()) + LogSupport.log("MailcapCommandMap: can't load " + name, sex); + } finally { + try { + if (clis != null) + clis.close(); + } catch (IOException ex) { } // ignore it + } + return null; + } + + /** + * Load all of the named resource. + */ + private void loadAllResources(List v, String name) { + boolean anyLoaded = false; + try { + URL[] urls; + ClassLoader cld = null; + // First try the "application's" class loader. + cld = SecuritySupport.getContextClassLoader(); + if (cld == null) + cld = this.getClass().getClassLoader(); + if (cld != null) + urls = SecuritySupport.getResources(cld, name); + else + urls = SecuritySupport.getSystemResources(name); + if (urls != null) { + if (LogSupport.isLoggable()) + LogSupport.log("MailcapCommandMap: getResources"); + for (int i = 0; i < urls.length; i++) { + URL url = urls[i]; + InputStream clis = null; + if (LogSupport.isLoggable()) + LogSupport.log("MailcapCommandMap: URL " + url); + try { + clis = SecuritySupport.openStream(url); + if (clis != null) { + v.add(new MailcapFile(clis)); + anyLoaded = true; + if (LogSupport.isLoggable()) + LogSupport.log("MailcapCommandMap: " + + "successfully loaded " + + "mailcap file from URL: " + + url); + } else { + if (LogSupport.isLoggable()) + LogSupport.log("MailcapCommandMap: " + + "not loading mailcap " + + "file from URL: " + url); + } + } catch (IOException ioex) { + if (LogSupport.isLoggable()) + LogSupport.log("MailcapCommandMap: can't load " + + url, ioex); + } catch (SecurityException sex) { + if (LogSupport.isLoggable()) + LogSupport.log("MailcapCommandMap: can't load " + + url, sex); + } finally { + try { + if (clis != null) + clis.close(); + } catch (IOException cex) { } + } + } + } + } catch (Exception ex) { + if (LogSupport.isLoggable()) + LogSupport.log("MailcapCommandMap: can't load " + name, ex); + } + + // if failed to load anything, fall back to old technique, just in case + if (!anyLoaded) { + if (LogSupport.isLoggable()) + LogSupport.log("MailcapCommandMap: !anyLoaded"); + MailcapFile mf = loadResource("/" + name); + if (mf != null) + v.add(mf); + } + } + + /** + * Load from the named file. + */ + private MailcapFile loadFile(String name) { + MailcapFile mtf = null; + + try { + mtf = new MailcapFile(name); + } catch (IOException e) { + // e.printStackTrace(); + } + return mtf; + } + + /** + * Constructor that allows the caller to specify the path + * of a mailcap file. + * + * @param fileName The name of the mailcap file to open + * @exception IOException if the file can't be accessed + */ + public MailcapCommandMap(String fileName) throws IOException { + this(); + + if (LogSupport.isLoggable()) + LogSupport.log("MailcapCommandMap: load PROG from " + fileName); + if (DB[PROG] == null) { + DB[PROG] = new MailcapFile(fileName); + } + } + + + /** + * Constructor that allows the caller to specify an InputStream + * containing a mailcap file. + * + * @param is InputStream of the mailcap file to open + */ + public MailcapCommandMap(InputStream is) { + this(); + + LogSupport.log("MailcapCommandMap: load PROG"); + if (DB[PROG] == null) { + try { + DB[PROG] = new MailcapFile(is); + } catch (IOException ex) { + // XXX - should throw it + } + } + } + + /** + * Get the preferred command list for a MIME Type. The MailcapCommandMap + * searches the mailcap files as described above under + * Mailcap file search order.

+ * + * The result of the search is a proper subset of available + * commands in all mailcap files known to this instance of + * MailcapCommandMap. The first entry for a particular command + * is considered the preferred command. + * + * @param mimeType the MIME type + * @return the CommandInfo objects representing the preferred commands. + */ + public synchronized CommandInfo[] getPreferredCommands(String mimeType) { + List cmdList = new ArrayList(); + if (mimeType != null) + mimeType = mimeType.toLowerCase(Locale.ENGLISH); + + for (int i = 0; i < DB.length; i++) { + if (DB[i] == null) + continue; + Map cmdMap = DB[i].getMailcapList(mimeType); + if (cmdMap != null) + appendPrefCmdsToList(cmdMap, cmdList); + } + + // now add the fallback commands + for (int i = 0; i < DB.length; i++) { + if (DB[i] == null) + continue; + Map cmdMap = DB[i].getMailcapFallbackList(mimeType); + if (cmdMap != null) + appendPrefCmdsToList(cmdMap, cmdList); + } + + CommandInfo[] cmdInfos = new CommandInfo[cmdList.size()]; + cmdInfos = (CommandInfo[])cmdList.toArray(cmdInfos); + + return cmdInfos; + } + + /** + * Put the commands that are in the hash table, into the list. + */ + private void appendPrefCmdsToList(Map cmdHash, List cmdList) { + Iterator verb_enum = cmdHash.keySet().iterator(); + + while (verb_enum.hasNext()) { + String verb = (String)verb_enum.next(); + if (!checkForVerb(cmdList, verb)) { + List cmdList2 = (List)cmdHash.get(verb); // get the list + String className = (String)cmdList2.get(0); + cmdList.add(new CommandInfo(verb, className)); + } + } + } + + /** + * Check the cmdList to see if this command exists, return + * true if the verb is there. + */ + private boolean checkForVerb(List cmdList, String verb) { + Iterator ee = cmdList.iterator(); + while (ee.hasNext()) { + String enum_verb = + (String)((CommandInfo)ee.next()).getCommandName(); + if (enum_verb.equals(verb)) + return true; + } + return false; + } + + /** + * Get all the available commands in all mailcap files known to + * this instance of MailcapCommandMap for this MIME type. + * + * @param mimeType the MIME type + * @return the CommandInfo objects representing all the commands. + */ + public synchronized CommandInfo[] getAllCommands(String mimeType) { + List cmdList = new ArrayList(); + if (mimeType != null) + mimeType = mimeType.toLowerCase(Locale.ENGLISH); + + for (int i = 0; i < DB.length; i++) { + if (DB[i] == null) + continue; + Map cmdMap = DB[i].getMailcapList(mimeType); + if (cmdMap != null) + appendCmdsToList(cmdMap, cmdList); + } + + // now add the fallback commands + for (int i = 0; i < DB.length; i++) { + if (DB[i] == null) + continue; + Map cmdMap = DB[i].getMailcapFallbackList(mimeType); + if (cmdMap != null) + appendCmdsToList(cmdMap, cmdList); + } + + CommandInfo[] cmdInfos = new CommandInfo[cmdList.size()]; + cmdInfos = (CommandInfo[])cmdList.toArray(cmdInfos); + + return cmdInfos; + } + + /** + * Put the commands that are in the hash table, into the list. + */ + private void appendCmdsToList(Map typeHash, List cmdList) { + Iterator verb_enum = typeHash.keySet().iterator(); + + while (verb_enum.hasNext()) { + String verb = (String)verb_enum.next(); + List cmdList2 = (List)typeHash.get(verb); + Iterator cmd_enum = ((List)cmdList2).iterator(); + + while (cmd_enum.hasNext()) { + String cmd = (String)cmd_enum.next(); + cmdList.add(new CommandInfo(verb, cmd)); + // cmdList.add(0, new CommandInfo(verb, cmd)); + } + } + } + + /** + * Get the command corresponding to cmdName for the MIME type. + * + * @param mimeType the MIME type + * @param cmdName the command name + * @return the CommandInfo object corresponding to the command. + */ + public synchronized CommandInfo getCommand(String mimeType, + String cmdName) { + if (mimeType != null) + mimeType = mimeType.toLowerCase(Locale.ENGLISH); + + for (int i = 0; i < DB.length; i++) { + if (DB[i] == null) + continue; + Map cmdMap = DB[i].getMailcapList(mimeType); + if (cmdMap != null) { + // get the cmd list for the cmd + List v = (List)cmdMap.get(cmdName); + if (v != null) { + String cmdClassName = (String)v.get(0); + + if (cmdClassName != null) + return new CommandInfo(cmdName, cmdClassName); + } + } + } + + // now try the fallback list + for (int i = 0; i < DB.length; i++) { + if (DB[i] == null) + continue; + Map cmdMap = DB[i].getMailcapFallbackList(mimeType); + if (cmdMap != null) { + // get the cmd list for the cmd + List v = (List)cmdMap.get(cmdName); + if (v != null) { + String cmdClassName = (String)v.get(0); + + if (cmdClassName != null) + return new CommandInfo(cmdName, cmdClassName); + } + } + } + return null; + } + + /** + * Add entries to the registry. Programmatically + * added entries are searched before other entries.

+ * + * The string that is passed in should be in mailcap + * format. + * + * @param mail_cap a correctly formatted mailcap string + */ + public synchronized void addMailcap(String mail_cap) { + // check to see if one exists + LogSupport.log("MailcapCommandMap: add to PROG"); + if (DB[PROG] == null) + DB[PROG] = new MailcapFile(); + + DB[PROG].appendToMailcap(mail_cap); + } + + /** + * Return the DataContentHandler for the specified MIME type. + * + * @param mimeType the MIME type + * @return the DataContentHandler + */ + public synchronized DataContentHandler createDataContentHandler( + String mimeType) { + if (LogSupport.isLoggable()) + LogSupport.log( + "MailcapCommandMap: createDataContentHandler for " + mimeType); + if (mimeType != null) + mimeType = mimeType.toLowerCase(Locale.ENGLISH); + + for (int i = 0; i < DB.length; i++) { + if (DB[i] == null) + continue; + if (LogSupport.isLoggable()) + LogSupport.log(" search DB #" + i); + Map cmdMap = DB[i].getMailcapList(mimeType); + if (cmdMap != null) { + List v = (List)cmdMap.get("content-handler"); + if (v != null) { + String name = (String)v.get(0); + DataContentHandler dch = getDataContentHandler(name); + if (dch != null) + return dch; + } + } + } + + // now try the fallback entries + for (int i = 0; i < DB.length; i++) { + if (DB[i] == null) + continue; + if (LogSupport.isLoggable()) + LogSupport.log(" search fallback DB #" + i); + Map cmdMap = DB[i].getMailcapFallbackList(mimeType); + if (cmdMap != null) { + List v = (List)cmdMap.get("content-handler"); + if (v != null) { + String name = (String)v.get(0); + DataContentHandler dch = getDataContentHandler(name); + if (dch != null) + return dch; + } + } + } + return null; + } + + private DataContentHandler getDataContentHandler(String name) { + if (LogSupport.isLoggable()) + LogSupport.log(" got content-handler"); + if (LogSupport.isLoggable()) + LogSupport.log(" class " + name); + try { + ClassLoader cld = null; + // First try the "application's" class loader. + cld = SecuritySupport.getContextClassLoader(); + if (cld == null) + cld = this.getClass().getClassLoader(); + Class cl = null; + try { + cl = cld.loadClass(name); + } catch (Exception ex) { + // if anything goes wrong, do it the old way + cl = Class.forName(name); + } + if (cl != null) // XXX - always true? + return (DataContentHandler)cl.newInstance(); + } catch (IllegalAccessException e) { + if (LogSupport.isLoggable()) + LogSupport.log("Can't load DCH " + name, e); + } catch (ClassNotFoundException e) { + if (LogSupport.isLoggable()) + LogSupport.log("Can't load DCH " + name, e); + } catch (InstantiationException e) { + if (LogSupport.isLoggable()) + LogSupport.log("Can't load DCH " + name, e); + } + return null; + } + + /** + * Get all the MIME types known to this command map. + * + * @return array of MIME types as strings + * @since JAF 1.1 + */ + public synchronized String[] getMimeTypes() { + List mtList = new ArrayList(); + + for (int i = 0; i < DB.length; i++) { + if (DB[i] == null) + continue; + String[] ts = DB[i].getMimeTypes(); + if (ts != null) { + for (int j = 0; j < ts.length; j++) { + // eliminate duplicates + if (!mtList.contains(ts[j])) + mtList.add(ts[j]); + } + } + } + + String[] mts = new String[mtList.size()]; + mts = (String[])mtList.toArray(mts); + + return mts; + } + + /** + * Get the native commands for the given MIME type. + * Returns an array of strings where each string is + * an entire mailcap file entry. The application + * will need to parse the entry to extract the actual + * command as well as any attributes it needs. See + * RFC 1524 + * for details of the mailcap entry syntax. Only mailcap + * entries that specify a view command for the specified + * MIME type are returned. + * + * @return array of native command entries + * @since JAF 1.1 + */ + public synchronized String[] getNativeCommands(String mimeType) { + List cmdList = new ArrayList(); + if (mimeType != null) + mimeType = mimeType.toLowerCase(Locale.ENGLISH); + + for (int i = 0; i < DB.length; i++) { + if (DB[i] == null) + continue; + String[] cmds = DB[i].getNativeCommands(mimeType); + if (cmds != null) { + for (int j = 0; j < cmds.length; j++) { + // eliminate duplicates + if (!cmdList.contains(cmds[j])) + cmdList.add(cmds[j]); + } + } + } + + String[] cmds = new String[cmdList.size()]; + cmds = (String[])cmdList.toArray(cmds); + + return cmds; + } + + /** + * for debugging... + * + public static void main(String[] argv) throws Exception { + MailcapCommandMap map = new MailcapCommandMap(); + CommandInfo[] cmdInfo; + + cmdInfo = map.getPreferredCommands(argv[0]); + System.out.println("Preferred Commands:"); + for (int i = 0; i < cmdInfo.length; i++) + System.out.println("Command " + cmdInfo[i].getCommandName() + " [" + + cmdInfo[i].getCommandClass() + "]"); + cmdInfo = map.getAllCommands(argv[0]); + System.out.println(); + System.out.println("All Commands:"); + for (int i = 0; i < cmdInfo.length; i++) + System.out.println("Command " + cmdInfo[i].getCommandName() + " [" + + cmdInfo[i].getCommandClass() + "]"); + DataContentHandler dch = map.createDataContentHandler(argv[0]); + if (dch != null) + System.out.println("DataContentHandler " + + dch.getClass().toString()); + System.exit(0); + } + */ +} diff --git a/jaxws/src/share/jaf_classes/javax/activation/MimeType.java b/jaxws/src/share/jaf_classes/javax/activation/MimeType.java new file mode 100644 index 00000000000..279d79d64c7 --- /dev/null +++ b/jaxws/src/share/jaf_classes/javax/activation/MimeType.java @@ -0,0 +1,344 @@ +/* + * Copyright (c) 1997, 2005, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package javax.activation; + +import java.io.*; +import java.util.Locale; + +/** + * A Multipurpose Internet Mail Extension (MIME) type, as defined + * in RFC 2045 and 2046. + * + * @since 1.6 + */ +public class MimeType implements Externalizable { + + private String primaryType; + private String subType; + private MimeTypeParameterList parameters; + + /** + * A string that holds all the special chars. + */ + private static final String TSPECIALS = "()<>@,;:/[]?=\\\""; + + /** + * Default constructor. + */ + public MimeType() { + primaryType = "application"; + subType = "*"; + parameters = new MimeTypeParameterList(); + } + + /** + * Constructor that builds a MimeType from a String. + * + * @param rawdata the MIME type string + */ + public MimeType(String rawdata) throws MimeTypeParseException { + parse(rawdata); + } + + /** + * Constructor that builds a MimeType with the given primary and sub type + * but has an empty parameter list. + * + * @param primary the primary MIME type + * @param sub the MIME sub-type + * @exception MimeTypeParseException if the primary type or subtype + * is not a valid token + */ + public MimeType(String primary, String sub) throws MimeTypeParseException { + // check to see if primary is valid + if (isValidToken(primary)) { + primaryType = primary.toLowerCase(Locale.ENGLISH); + } else { + throw new MimeTypeParseException("Primary type is invalid."); + } + + // check to see if sub is valid + if (isValidToken(sub)) { + subType = sub.toLowerCase(Locale.ENGLISH); + } else { + throw new MimeTypeParseException("Sub type is invalid."); + } + + parameters = new MimeTypeParameterList(); + } + + /** + * A routine for parsing the MIME type out of a String. + */ + private void parse(String rawdata) throws MimeTypeParseException { + int slashIndex = rawdata.indexOf('/'); + int semIndex = rawdata.indexOf(';'); + if ((slashIndex < 0) && (semIndex < 0)) { + // neither character is present, so treat it + // as an error + throw new MimeTypeParseException("Unable to find a sub type."); + } else if ((slashIndex < 0) && (semIndex >= 0)) { + // we have a ';' (and therefore a parameter list), + // but no '/' indicating a sub type is present + throw new MimeTypeParseException("Unable to find a sub type."); + } else if ((slashIndex >= 0) && (semIndex < 0)) { + // we have a primary and sub type but no parameter list + primaryType = rawdata.substring(0, slashIndex).trim(). + toLowerCase(Locale.ENGLISH); + subType = rawdata.substring(slashIndex + 1).trim(). + toLowerCase(Locale.ENGLISH); + parameters = new MimeTypeParameterList(); + } else if (slashIndex < semIndex) { + // we have all three items in the proper sequence + primaryType = rawdata.substring(0, slashIndex).trim(). + toLowerCase(Locale.ENGLISH); + subType = rawdata.substring(slashIndex + 1, semIndex).trim(). + toLowerCase(Locale.ENGLISH); + parameters = new MimeTypeParameterList(rawdata.substring(semIndex)); + } else { + // we have a ';' lexically before a '/' which means we + // have a primary type and a parameter list but no sub type + throw new MimeTypeParseException("Unable to find a sub type."); + } + + // now validate the primary and sub types + + // check to see if primary is valid + if (!isValidToken(primaryType)) + throw new MimeTypeParseException("Primary type is invalid."); + + // check to see if sub is valid + if (!isValidToken(subType)) + throw new MimeTypeParseException("Sub type is invalid."); + } + + /** + * Retrieve the primary type of this object. + * + * @return the primary MIME type + */ + public String getPrimaryType() { + return primaryType; + } + + /** + * Set the primary type for this object to the given String. + * + * @param primary the primary MIME type + * @exception MimeTypeParseException if the primary type + * is not a valid token + */ + public void setPrimaryType(String primary) throws MimeTypeParseException { + // check to see if primary is valid + if (!isValidToken(primaryType)) + throw new MimeTypeParseException("Primary type is invalid."); + primaryType = primary.toLowerCase(Locale.ENGLISH); + } + + /** + * Retrieve the subtype of this object. + * + * @return the MIME subtype + */ + public String getSubType() { + return subType; + } + + /** + * Set the subtype for this object to the given String. + * + * @param sub the MIME subtype + * @exception MimeTypeParseException if the subtype + * is not a valid token + */ + public void setSubType(String sub) throws MimeTypeParseException { + // check to see if sub is valid + if (!isValidToken(subType)) + throw new MimeTypeParseException("Sub type is invalid."); + subType = sub.toLowerCase(Locale.ENGLISH); + } + + /** + * Retrieve this object's parameter list. + * + * @return a MimeTypeParameterList object representing the parameters + */ + public MimeTypeParameterList getParameters() { + return parameters; + } + + /** + * Retrieve the value associated with the given name, or null if there + * is no current association. + * + * @param name the parameter name + * @return the paramter's value + */ + public String getParameter(String name) { + return parameters.get(name); + } + + /** + * Set the value to be associated with the given name, replacing + * any previous association. + * + * @param name the parameter name + * @param value the paramter's value + */ + public void setParameter(String name, String value) { + parameters.set(name, value); + } + + /** + * Remove any value associated with the given name. + * + * @param name the parameter name + */ + public void removeParameter(String name) { + parameters.remove(name); + } + + /** + * Return the String representation of this object. + */ + public String toString() { + return getBaseType() + parameters.toString(); + } + + /** + * Return a String representation of this object + * without the parameter list. + * + * @return the MIME type and sub-type + */ + public String getBaseType() { + return primaryType + "/" + subType; + } + + /** + * Determine if the primary and sub type of this object is + * the same as what is in the given type. + * + * @param type the MimeType object to compare with + * @return true if they match + */ + public boolean match(MimeType type) { + return primaryType.equals(type.getPrimaryType()) + && (subType.equals("*") + || type.getSubType().equals("*") + || (subType.equals(type.getSubType()))); + } + + /** + * Determine if the primary and sub type of this object is + * the same as the content type described in rawdata. + * + * @param rawdata the MIME type string to compare with + * @return true if they match + */ + public boolean match(String rawdata) throws MimeTypeParseException { + return match(new MimeType(rawdata)); + } + + /** + * The object implements the writeExternal method to save its contents + * by calling the methods of DataOutput for its primitive values or + * calling the writeObject method of ObjectOutput for objects, strings + * and arrays. + * + * @param out the ObjectOutput object to write to + * @exception IOException Includes any I/O exceptions that may occur + */ + public void writeExternal(ObjectOutput out) throws IOException { + out.writeUTF(toString()); + out.flush(); + } + + /** + * The object implements the readExternal method to restore its + * contents by calling the methods of DataInput for primitive + * types and readObject for objects, strings and arrays. The + * readExternal method must read the values in the same sequence + * and with the same types as were written by writeExternal. + * + * @param in the ObjectInput object to read from + * @exception ClassNotFoundException If the class for an object being + * restored cannot be found. + */ + public void readExternal(ObjectInput in) + throws IOException, ClassNotFoundException { + try { + parse(in.readUTF()); + } catch (MimeTypeParseException e) { + throw new IOException(e.toString()); + } + } + + // below here be scary parsing related things + + /** + * Determine whether or not a given character belongs to a legal token. + */ + private static boolean isTokenChar(char c) { + return ((c > 040) && (c < 0177)) && (TSPECIALS.indexOf(c) < 0); + } + + /** + * Determine whether or not a given string is a legal token. + */ + private boolean isValidToken(String s) { + int len = s.length(); + if (len > 0) { + for (int i = 0; i < len; ++i) { + char c = s.charAt(i); + if (!isTokenChar(c)) { + return false; + } + } + return true; + } else { + return false; + } + } + + /** + * A simple parser test, + * for debugging... + * + public static void main(String[] args) + throws MimeTypeParseException, IOException { + for (int i = 0; i < args.length; ++i) { + System.out.println("Original: " + args[i]); + + MimeType type = new MimeType(args[i]); + + System.out.println("Short: " + type.getBaseType()); + System.out.println("Parsed: " + type.toString()); + System.out.println(); + } + } + */ +} diff --git a/jaxws/src/share/jaf_classes/javax/activation/MimeTypeParameterList.java b/jaxws/src/share/jaf_classes/javax/activation/MimeTypeParameterList.java new file mode 100644 index 00000000000..81be17a2022 --- /dev/null +++ b/jaxws/src/share/jaf_classes/javax/activation/MimeTypeParameterList.java @@ -0,0 +1,339 @@ +/* + * Copyright (c) 1997, 2005, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package javax.activation; + +import java.util.Hashtable; +import java.util.Enumeration; +import java.util.Locale; + +/** + * A parameter list of a MimeType + * as defined in RFC 2045 and 2046. The Primary type of the + * object must already be stripped off. + * + * @see javax.activation.MimeType + * + * @since 1.6 + */ +public class MimeTypeParameterList { + private Hashtable parameters; + + /** + * A string that holds all the special chars. + */ + private static final String TSPECIALS = "()<>@,;:/[]?=\\\""; + + + /** + * Default constructor. + */ + public MimeTypeParameterList() { + parameters = new Hashtable(); + } + + /** + * Constructs a new MimeTypeParameterList with the passed in data. + * + * @param parameterList an RFC 2045, 2046 compliant parameter list. + */ + public MimeTypeParameterList(String parameterList) + throws MimeTypeParseException { + parameters = new Hashtable(); + + // now parse rawdata + parse(parameterList); + } + + /** + * A routine for parsing the parameter list out of a String. + * + * @param parameterList an RFC 2045, 2046 compliant parameter list. + */ + protected void parse(String parameterList) throws MimeTypeParseException { + if (parameterList == null) + return; + + int length = parameterList.length(); + if (length <= 0) + return; + + int i; + char c; + for (i = skipWhiteSpace(parameterList, 0); + i < length && (c = parameterList.charAt(i)) == ';'; + i = skipWhiteSpace(parameterList, i)) { + int lastIndex; + String name; + String value; + + // eat the ';' + i++; + + // now parse the parameter name + + // skip whitespace + i = skipWhiteSpace(parameterList, i); + + // tolerate trailing semicolon, even though it violates the spec + if (i >= length) + return; + + // find the end of the token char run + lastIndex = i; + while ((i < length) && isTokenChar(parameterList.charAt(i))) + i++; + + name = parameterList.substring(lastIndex, i). + toLowerCase(Locale.ENGLISH); + + // now parse the '=' that separates the name from the value + i = skipWhiteSpace(parameterList, i); + + if (i >= length || parameterList.charAt(i) != '=') + throw new MimeTypeParseException( + "Couldn't find the '=' that separates a " + + "parameter name from its value."); + + // eat it and parse the parameter value + i++; + i = skipWhiteSpace(parameterList, i); + + if (i >= length) + throw new MimeTypeParseException( + "Couldn't find a value for parameter named " + name); + + // now find out whether or not we have a quoted value + c = parameterList.charAt(i); + if (c == '"') { + // yup it's quoted so eat it and capture the quoted string + i++; + if (i >= length) + throw new MimeTypeParseException( + "Encountered unterminated quoted parameter value."); + + lastIndex = i; + + // find the next unescaped quote + while (i < length) { + c = parameterList.charAt(i); + if (c == '"') + break; + if (c == '\\') { + // found an escape sequence + // so skip this and the + // next character + i++; + } + i++; + } + if (c != '"') + throw new MimeTypeParseException( + "Encountered unterminated quoted parameter value."); + + value = unquote(parameterList.substring(lastIndex, i)); + // eat the quote + i++; + } else if (isTokenChar(c)) { + // nope it's an ordinary token so it + // ends with a non-token char + lastIndex = i; + while (i < length && isTokenChar(parameterList.charAt(i))) + i++; + value = parameterList.substring(lastIndex, i); + } else { + // it ain't a value + throw new MimeTypeParseException( + "Unexpected character encountered at index " + i); + } + + // now put the data into the hashtable + parameters.put(name, value); + } + if (i < length) { + throw new MimeTypeParseException( + "More characters encountered in input than expected."); + } + } + + /** + * Return the number of name-value pairs in this list. + * + * @return the number of parameters + */ + public int size() { + return parameters.size(); + } + + /** + * Determine whether or not this list is empty. + * + * @return true if there are no parameters + */ + public boolean isEmpty() { + return parameters.isEmpty(); + } + + /** + * Retrieve the value associated with the given name, or null if there + * is no current association. + * + * @param name the parameter name + * @return the parameter's value + */ + public String get(String name) { + return (String)parameters.get(name.trim().toLowerCase(Locale.ENGLISH)); + } + + /** + * Set the value to be associated with the given name, replacing + * any previous association. + * + * @param name the parameter name + * @param value the parameter's value + */ + public void set(String name, String value) { + parameters.put(name.trim().toLowerCase(Locale.ENGLISH), value); + } + + /** + * Remove any value associated with the given name. + * + * @param name the parameter name + */ + public void remove(String name) { + parameters.remove(name.trim().toLowerCase(Locale.ENGLISH)); + } + + /** + * Retrieve an enumeration of all the names in this list. + * + * @return an enumeration of all parameter names + */ + public Enumeration getNames() { + return parameters.keys(); + } + + /** + * Return a string representation of this object. + */ + public String toString() { + StringBuffer buffer = new StringBuffer(); + buffer.ensureCapacity(parameters.size() * 16); + // heuristic: 8 characters per field + + Enumeration keys = parameters.keys(); + while (keys.hasMoreElements()) { + String key = (String)keys.nextElement(); + buffer.append("; "); + buffer.append(key); + buffer.append('='); + buffer.append(quote((String)parameters.get(key))); + } + + return buffer.toString(); + } + + // below here be scary parsing related things + + /** + * Determine whether or not a given character belongs to a legal token. + */ + private static boolean isTokenChar(char c) { + return ((c > 040) && (c < 0177)) && (TSPECIALS.indexOf(c) < 0); + } + + /** + * return the index of the first non white space character in + * rawdata at or after index i. + */ + private static int skipWhiteSpace(String rawdata, int i) { + int length = rawdata.length(); + while ((i < length) && Character.isWhitespace(rawdata.charAt(i))) + i++; + return i; + } + + /** + * A routine that knows how and when to quote and escape the given value. + */ + private static String quote(String value) { + boolean needsQuotes = false; + + // check to see if we actually have to quote this thing + int length = value.length(); + for (int i = 0; (i < length) && !needsQuotes; i++) { + needsQuotes = !isTokenChar(value.charAt(i)); + } + + if (needsQuotes) { + StringBuffer buffer = new StringBuffer(); + buffer.ensureCapacity((int)(length * 1.5)); + + // add the initial quote + buffer.append('"'); + + // add the properly escaped text + for (int i = 0; i < length; ++i) { + char c = value.charAt(i); + if ((c == '\\') || (c == '"')) + buffer.append('\\'); + buffer.append(c); + } + + // add the closing quote + buffer.append('"'); + + return buffer.toString(); + } else { + return value; + } + } + + /** + * A routine that knows how to strip the quotes and + * escape sequences from the given value. + */ + private static String unquote(String value) { + int valueLength = value.length(); + StringBuffer buffer = new StringBuffer(); + buffer.ensureCapacity(valueLength); + + boolean escaped = false; + for (int i = 0; i < valueLength; ++i) { + char currentChar = value.charAt(i); + if (!escaped && (currentChar != '\\')) { + buffer.append(currentChar); + } else if (escaped) { + buffer.append(currentChar); + escaped = false; + } else { + escaped = true; + } + } + + return buffer.toString(); + } +} diff --git a/jaxws/src/share/jaf_classes/javax/activation/MimeTypeParseException.java b/jaxws/src/share/jaf_classes/javax/activation/MimeTypeParseException.java new file mode 100644 index 00000000000..d9ce6b53920 --- /dev/null +++ b/jaxws/src/share/jaf_classes/javax/activation/MimeTypeParseException.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 1997, 2005, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package javax.activation; + +/** + * A class to encapsulate MimeType parsing related exceptions. + * + * @since 1.6 + */ +public class MimeTypeParseException extends Exception { + + /** + * Constructs a MimeTypeParseException with no specified detail message. + */ + public MimeTypeParseException() { + super(); + } + + /** + * Constructs a MimeTypeParseException with the specified detail message. + * + * @param s the detail message. + */ + public MimeTypeParseException(String s) { + super(s); + } +} diff --git a/jaxws/src/share/jaf_classes/javax/activation/MimetypesFileTypeMap.java b/jaxws/src/share/jaf_classes/javax/activation/MimetypesFileTypeMap.java new file mode 100644 index 00000000000..b87d2272c52 --- /dev/null +++ b/jaxws/src/share/jaf_classes/javax/activation/MimetypesFileTypeMap.java @@ -0,0 +1,336 @@ +/* + * Copyright (c) 1997, 2005, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package javax.activation; + +import java.io.*; +import java.net.*; +import java.util.*; +import com.sun.activation.registries.MimeTypeFile; +import com.sun.activation.registries.LogSupport; + +/** + * This class extends FileTypeMap and provides data typing of files + * via their file extension. It uses the .mime.types format.

+ * + * MIME types file search order:

+ * The MimetypesFileTypeMap looks in various places in the user's + * system for MIME types file entries. When requests are made + * to search for MIME types in the MimetypesFileTypeMap, it searches + * MIME types files in the following order: + *

+ *

    + *
  1. Programmatically added entries to the MimetypesFileTypeMap instance. + *
  2. The file .mime.types in the user's home directory. + *
  3. The file <java.home>/lib/mime.types. + *
  4. The file or resources named META-INF/mime.types. + *
  5. The file or resource named META-INF/mimetypes.default + * (usually found only in the activation.jar file). + *
+ *

+ * MIME types file format:

+ * + * + * # comments begin with a '#'
+ * # the format is <mime type> <space separated file extensions>
+ * # for example:
+ * text/plain txt text TXT
+ * # this would map file.txt, file.text, and file.TXT to
+ * # the mime type "text/plain"
+ *
+ * + * @author Bart Calder + * @author Bill Shannon + * + * @since 1.6 + */ +public class MimetypesFileTypeMap extends FileTypeMap { + /* + * We manage a collection of databases, searched in order. + * The default database is shared between all instances + * of this class. + * XXX - Can we safely share more databases between instances? + */ + private static MimeTypeFile defDB = null; + private MimeTypeFile[] DB; + private static final int PROG = 0; // programmatically added entries + + private static String defaultType = "application/octet-stream"; + + /** + * The default constructor. + */ + public MimetypesFileTypeMap() { + Vector dbv = new Vector(5); // usually 5 or less databases + MimeTypeFile mf = null; + dbv.addElement(null); // place holder for PROG entry + + LogSupport.log("MimetypesFileTypeMap: load HOME"); + try { + String user_home = System.getProperty("user.home"); + + if (user_home != null) { + String path = user_home + File.separator + ".mime.types"; + mf = loadFile(path); + if (mf != null) + dbv.addElement(mf); + } + } catch (SecurityException ex) {} + + LogSupport.log("MimetypesFileTypeMap: load SYS"); + try { + // check system's home + String system_mimetypes = System.getProperty("java.home") + + File.separator + "lib" + File.separator + "mime.types"; + mf = loadFile(system_mimetypes); + if (mf != null) + dbv.addElement(mf); + } catch (SecurityException ex) {} + + LogSupport.log("MimetypesFileTypeMap: load JAR"); + // load from the app's jar file + loadAllResources(dbv, "META-INF/mime.types"); + + LogSupport.log("MimetypesFileTypeMap: load DEF"); + synchronized (MimetypesFileTypeMap.class) { + // see if another instance has created this yet. + if (defDB == null) + defDB = loadResource("/META-INF/mimetypes.default"); + } + + if (defDB != null) + dbv.addElement(defDB); + + DB = new MimeTypeFile[dbv.size()]; + dbv.copyInto(DB); + } + + /** + * Load from the named resource. + */ + private MimeTypeFile loadResource(String name) { + InputStream clis = null; + try { + clis = SecuritySupport.getResourceAsStream(this.getClass(), name); + if (clis != null) { + MimeTypeFile mf = new MimeTypeFile(clis); + if (LogSupport.isLoggable()) + LogSupport.log("MimetypesFileTypeMap: successfully " + + "loaded mime types file: " + name); + return mf; + } else { + if (LogSupport.isLoggable()) + LogSupport.log("MimetypesFileTypeMap: not loading " + + "mime types file: " + name); + } + } catch (IOException e) { + if (LogSupport.isLoggable()) + LogSupport.log("MimetypesFileTypeMap: can't load " + name, e); + } catch (SecurityException sex) { + if (LogSupport.isLoggable()) + LogSupport.log("MimetypesFileTypeMap: can't load " + name, sex); + } finally { + try { + if (clis != null) + clis.close(); + } catch (IOException ex) { } // ignore it + } + return null; + } + + /** + * Load all of the named resource. + */ + private void loadAllResources(Vector v, String name) { + boolean anyLoaded = false; + try { + URL[] urls; + ClassLoader cld = null; + // First try the "application's" class loader. + cld = SecuritySupport.getContextClassLoader(); + if (cld == null) + cld = this.getClass().getClassLoader(); + if (cld != null) + urls = SecuritySupport.getResources(cld, name); + else + urls = SecuritySupport.getSystemResources(name); + if (urls != null) { + if (LogSupport.isLoggable()) + LogSupport.log("MimetypesFileTypeMap: getResources"); + for (int i = 0; i < urls.length; i++) { + URL url = urls[i]; + InputStream clis = null; + if (LogSupport.isLoggable()) + LogSupport.log("MimetypesFileTypeMap: URL " + url); + try { + clis = SecuritySupport.openStream(url); + if (clis != null) { + v.addElement(new MimeTypeFile(clis)); + anyLoaded = true; + if (LogSupport.isLoggable()) + LogSupport.log("MimetypesFileTypeMap: " + + "successfully loaded " + + "mime types from URL: " + url); + } else { + if (LogSupport.isLoggable()) + LogSupport.log("MimetypesFileTypeMap: " + + "not loading " + + "mime types from URL: " + url); + } + } catch (IOException ioex) { + if (LogSupport.isLoggable()) + LogSupport.log("MimetypesFileTypeMap: can't load " + + url, ioex); + } catch (SecurityException sex) { + if (LogSupport.isLoggable()) + LogSupport.log("MimetypesFileTypeMap: can't load " + + url, sex); + } finally { + try { + if (clis != null) + clis.close(); + } catch (IOException cex) { } + } + } + } + } catch (Exception ex) { + if (LogSupport.isLoggable()) + LogSupport.log("MimetypesFileTypeMap: can't load " + name, ex); + } + + // if failed to load anything, fall back to old technique, just in case + if (!anyLoaded) { + LogSupport.log("MimetypesFileTypeMap: !anyLoaded"); + MimeTypeFile mf = loadResource("/" + name); + if (mf != null) + v.addElement(mf); + } + } + + /** + * Load the named file. + */ + private MimeTypeFile loadFile(String name) { + MimeTypeFile mtf = null; + + try { + mtf = new MimeTypeFile(name); + } catch (IOException e) { + // e.printStackTrace(); + } + return mtf; + } + + /** + * Construct a MimetypesFileTypeMap with programmatic entries + * added from the named file. + * + * @param mimeTypeFileName the file name + */ + public MimetypesFileTypeMap(String mimeTypeFileName) throws IOException { + this(); + DB[PROG] = new MimeTypeFile(mimeTypeFileName); + } + + /** + * Construct a MimetypesFileTypeMap with programmatic entries + * added from the InputStream. + * + * @param is the input stream to read from + */ + public MimetypesFileTypeMap(InputStream is) { + this(); + try { + DB[PROG] = new MimeTypeFile(is); + } catch (IOException ex) { + // XXX - really should throw it + } + } + + /** + * Prepend the MIME type values to the registry. + * + * @param mime_types A .mime.types formatted string of entries. + */ + public synchronized void addMimeTypes(String mime_types) { + // check to see if we have created the registry + if (DB[PROG] == null) + DB[PROG] = new MimeTypeFile(); // make one + + DB[PROG].appendToRegistry(mime_types); + } + + /** + * Return the MIME type of the file object. + * The implementation in this class calls + * getContentType(f.getName()). + * + * @param f the file + * @return the file's MIME type + */ + public String getContentType(File f) { + return this.getContentType(f.getName()); + } + + /** + * Return the MIME type based on the specified file name. + * The MIME type entries are searched as described above under + * MIME types file search order. + * If no entry is found, the type "application/octet-stream" is returned. + * + * @param filename the file name + * @return the file's MIME type + */ + public synchronized String getContentType(String filename) { + int dot_pos = filename.lastIndexOf("."); // period index + + if (dot_pos < 0) + return defaultType; + + String file_ext = filename.substring(dot_pos + 1); + if (file_ext.length() == 0) + return defaultType; + + for (int i = 0; i < DB.length; i++) { + if (DB[i] == null) + continue; + String result = DB[i].getMIMETypeString(file_ext); + if (result != null) + return result; + } + return defaultType; + } + + /** + * for debugging... + * + public static void main(String[] argv) throws Exception { + MimetypesFileTypeMap map = new MimetypesFileTypeMap(); + System.out.println("File " + argv[0] + " has MIME type " + + map.getContentType(argv[0])); + System.exit(0); + } + */ +} diff --git a/jaxws/src/share/jaf_classes/javax/activation/SecuritySupport.java b/jaxws/src/share/jaf_classes/javax/activation/SecuritySupport.java new file mode 100644 index 00000000000..33139d6b209 --- /dev/null +++ b/jaxws/src/share/jaf_classes/javax/activation/SecuritySupport.java @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2002, 2005, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package javax.activation; + +import java.security.*; +import java.net.*; +import java.io.*; +import java.util.*; + +/** + * Security related methods that only work on J2SE 1.2 and newer. + * + * @since 1.6 + */ +class SecuritySupport { + + private SecuritySupport() { + // private constructor, can't create an instance + } + + public static ClassLoader getContextClassLoader() { + return (ClassLoader) + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + ClassLoader cl = null; + try { + cl = Thread.currentThread().getContextClassLoader(); + } catch (SecurityException ex) { } + return cl; + } + }); + } + + public static InputStream getResourceAsStream(final Class c, + final String name) throws IOException { + try { + return (InputStream) + AccessController.doPrivileged(new PrivilegedExceptionAction() { + public Object run() throws IOException { + return c.getResourceAsStream(name); + } + }); + } catch (PrivilegedActionException e) { + throw (IOException)e.getException(); + } + } + + public static URL[] getResources(final ClassLoader cl, final String name) { + return (URL[]) + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + URL[] ret = null; + try { + List v = new ArrayList(); + Enumeration e = cl.getResources(name); + while (e != null && e.hasMoreElements()) { + URL url = (URL)e.nextElement(); + if (url != null) + v.add(url); + } + if (v.size() > 0) { + ret = new URL[v.size()]; + ret = (URL[])v.toArray(ret); + } + } catch (IOException ioex) { + } catch (SecurityException ex) { } + return ret; + } + }); + } + + public static URL[] getSystemResources(final String name) { + return (URL[]) + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + URL[] ret = null; + try { + List v = new ArrayList(); + Enumeration e = ClassLoader.getSystemResources(name); + while (e != null && e.hasMoreElements()) { + URL url = (URL)e.nextElement(); + if (url != null) + v.add(url); + } + if (v.size() > 0) { + ret = new URL[v.size()]; + ret = (URL[])v.toArray(ret); + } + } catch (IOException ioex) { + } catch (SecurityException ex) { } + return ret; + } + }); + } + + public static InputStream openStream(final URL url) throws IOException { + try { + return (InputStream) + AccessController.doPrivileged(new PrivilegedExceptionAction() { + public Object run() throws IOException { + return url.openStream(); + } + }); + } catch (PrivilegedActionException e) { + throw (IOException)e.getException(); + } + } +} diff --git a/jaxws/src/share/jaf_classes/javax/activation/URLDataSource.java b/jaxws/src/share/jaf_classes/javax/activation/URLDataSource.java new file mode 100644 index 00000000000..f42df8c1923 --- /dev/null +++ b/jaxws/src/share/jaf_classes/javax/activation/URLDataSource.java @@ -0,0 +1,137 @@ +/* + * Copyright (c) 1997, 2005, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package javax.activation; + +import java.net.URL; +import java.net.URLConnection; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.IOException; + +/** + * The URLDataSource class provides an object that wraps a URL + * object in a DataSource interface. URLDataSource simplifies the handling + * of data described by URLs within the JavaBeans Activation Framework + * because this class can be used to create new DataHandlers. NOTE: The + * DataHandler object creates a URLDataSource internally, + * when it is constructed with a URL. + * + * @see javax.activation.DataSource + * @see javax.activation.DataHandler + * + * @since 1.6 + */ +public class URLDataSource implements DataSource { + private URL url = null; + private URLConnection url_conn = null; + + /** + * URLDataSource constructor. The URLDataSource class will + * not open a connection to the URL until a method requiring it + * to do so is called. + * + * @param url The URL to be encapsulated in this object. + */ + public URLDataSource(URL url) { + this.url = url; + } + + /** + * Returns the value of the URL content-type header field. + * It calls the URL's URLConnection.getContentType method + * after retrieving a URLConnection object. + * Note: this method attempts to call the openConnection + * method on the URL. If this method fails, or if a content type is not + * returned from the URLConnection, getContentType returns + * "application/octet-stream" as the content type. + * + * @return the content type. + */ + public String getContentType() { + String type = null; + + try { + if (url_conn == null) + url_conn = url.openConnection(); + } catch (IOException e) { } + + if (url_conn != null) + type = url_conn.getContentType(); + + if (type == null) + type = "application/octet-stream"; + + return type; + } + + /** + * Calls the getFile method on the URL used to + * instantiate the object. + * + * @return the result of calling the URL's getFile method. + */ + public String getName() { + return url.getFile(); + } + + /** + * The getInputStream method from the URL. Calls the + * openStream method on the URL. + * + * @return the InputStream. + */ + public InputStream getInputStream() throws IOException { + return url.openStream(); + } + + /** + * The getOutputStream method from the URL. First an attempt is + * made to get the URLConnection object for the URL. If that + * succeeds, the getOutputStream method on the URLConnection + * is returned. + * + * @return the OutputStream. + */ + public OutputStream getOutputStream() throws IOException { + // get the url connection if it is available + url_conn = url.openConnection(); + + if (url_conn != null) { + url_conn.setDoOutput(true); + return url_conn.getOutputStream(); + } else + return null; + } + + /** + * Return the URL used to create this DataSource. + * + * @return The URL. + */ + public URL getURL() { + return url; + } +} diff --git a/jaxws/src/share/jaf_classes/javax/activation/UnsupportedDataTypeException.java b/jaxws/src/share/jaf_classes/javax/activation/UnsupportedDataTypeException.java new file mode 100644 index 00000000000..bed052ccaa2 --- /dev/null +++ b/jaxws/src/share/jaf_classes/javax/activation/UnsupportedDataTypeException.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 1997, 2005, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package javax.activation; + +import java.io.IOException; + +/** + * Signals that the requested operation does not support the + * requested data type. + * + * @see javax.activation.DataHandler + * + * @since 1.6 + */ + +public class UnsupportedDataTypeException extends IOException { + /** + * Constructs an UnsupportedDataTypeException with no detail + * message. + */ + public UnsupportedDataTypeException() { + super(); + } + + /** + * Constructs an UnsupportedDataTypeException with the specified + * message. + * + * @param s The detail message. + */ + public UnsupportedDataTypeException(String s) { + super(s); + } +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/ClassType.java b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/ClassType.java new file mode 100644 index 00000000000..5196b4b31ca --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/ClassType.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.codemodel.internal; +/** + * This helps enable whether the JDefinedClass is a Class or Interface or + * AnnotationTypeDeclaration or Enum + * + * @author + * Bhakti Mehta (bhakti.mehta@sun.com) + */ +public final class ClassType { + + /** + * The keyword used to declare this type. + */ + final String declarationToken; + + private ClassType(String token) { + this.declarationToken = token; + } + + public static final ClassType CLASS = new ClassType("class"); + public static final ClassType INTERFACE = new ClassType("interface"); + public static final ClassType ANNOTATION_TYPE_DECL = new ClassType("@interface"); + public static final ClassType ENUM = new ClassType("enum"); +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/CodeWriter.java b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/CodeWriter.java new file mode 100644 index 00000000000..6149fb02688 --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/CodeWriter.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.codemodel.internal; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.Writer; +import java.nio.charset.CharsetEncoder; + +import com.sun.codemodel.internal.util.EncoderFactory; +import com.sun.codemodel.internal.util.UnicodeEscapeWriter; + +/** + * Receives generated code and writes to the appropriate storage. + * + * @author + * Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com) + */ +public abstract class CodeWriter { + + /** + * Encoding to be used by the writer. Null means platform specific encoding. + * + * @since 2.5 + */ + protected String encoding = null; + + /** + * Called by CodeModel to store the specified file. + * The callee must allocate a storage to store the specified file. + * + *

+ * The returned stream will be closed before the next file is + * stored. So the callee can assume that only one OutputStream + * is active at any given time. + * + * @param pkg + * The package of the file to be written. + * @param fileName + * File name without the path. Something like + * "Foo.java" or "Bar.properties" + */ + public abstract OutputStream openBinary( JPackage pkg, String fileName ) throws IOException; + + /** + * Called by CodeModel to store the specified file. + * The callee must allocate a storage to store the specified file. + * + *

+ * The returned stream will be closed before the next file is + * stored. So the callee can assume that only one OutputStream + * is active at any given time. + * + * @param pkg + * The package of the file to be written. + * @param fileName + * File name without the path. Something like + * "Foo.java" or "Bar.properties" + */ + public Writer openSource( JPackage pkg, String fileName ) throws IOException { + final OutputStreamWriter bw = encoding != null + ? new OutputStreamWriter(openBinary(pkg,fileName), encoding) + : new OutputStreamWriter(openBinary(pkg,fileName)); + + // create writer + try { + return new UnicodeEscapeWriter(bw) { + // can't change this signature to Encoder because + // we can't have Encoder in method signature + private final CharsetEncoder encoder = EncoderFactory.createEncoder(bw.getEncoding()); + @Override + protected boolean requireEscaping(int ch) { + // control characters + if( ch<0x20 && " \t\r\n".indexOf(ch)==-1 ) return true; + // check ASCII chars, for better performance + if( ch<0x80 ) return false; + + return !encoder.canEncode((char)ch); + } + }; + } catch( Throwable t ) { + return new UnicodeEscapeWriter(bw); + } + } + + /** + * Called by CodeModel at the end of the process. + */ + public abstract void close() throws IOException; +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JAnnotatable.java b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JAnnotatable.java new file mode 100644 index 00000000000..8be8028d2d4 --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JAnnotatable.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.codemodel.internal; + +import java.lang.annotation.Annotation; +import java.util.Collection; + +/** + * Annotatable program elements. + * + * @author Kohsuke Kawaguchi + */ +public interface JAnnotatable { + /** + * Adds an annotation to this program element. + * @param clazz + * The annotation class to annotate the program element with + */ + JAnnotationUse annotate(JClass clazz); + + /** + * Adds an annotation to this program element. + * + * @param clazz + * The annotation class to annotate the program element with + */ + JAnnotationUse annotate(Class clazz); + + /** + * Adds an annotation to this program element + * and returns a type-safe writer to fill in the values of such annotations. + */ + W annotate2(Class clazz); + + /** + * Read-only live view of all annotations on this {@link JAnnotatable} + * + * @return + * Can be empty but never null. + */ + Collection annotations(); +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JAnnotationArrayMember.java b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JAnnotationArrayMember.java new file mode 100644 index 00000000000..169c97e0d0a --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JAnnotationArrayMember.java @@ -0,0 +1,298 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.codemodel.internal; + + +import java.lang.annotation.Annotation; +import java.util.ArrayList; +import java.util.List; +import java.util.Collection; +import java.util.Collections; + +/** + * Represents an arrays as annotation members + * + *

+ * This class implements {@link JAnnotatable} to allow + * new annotations to be added as a member of the array. + * + * @author + * Bhakti Mehta (bhakti.mehta@sun.com) + */ +public final class JAnnotationArrayMember extends JAnnotationValue implements JAnnotatable { + private final List values = new ArrayList(); + private final JCodeModel owner; + + JAnnotationArrayMember(JCodeModel owner) { + this.owner = owner; + } + + /** + * Adds an array member to this annotation + * + * @param value Adds a string value to the array member + * @return The JAnnotationArrayMember. More elements can be added by calling + * the same method multiple times + */ + public JAnnotationArrayMember param(String value) { + JAnnotationValue annotationValue = new JAnnotationStringValue(JExpr.lit(value)); + values.add(annotationValue); + return this; + } + + /** + * Adds an array member to this annotation + * + * @param value Adds a boolean value to the array member + * @return The JAnnotationArrayMember. More elements can be added by calling + * the same method multiple times + */ + public JAnnotationArrayMember param(boolean value) { + JAnnotationValue annotationValue = new JAnnotationStringValue(JExpr.lit(value)); + values.add(annotationValue); + return this; + } + + /** + * Adds an array member to this annotation + * + * @param value Adds a byte value to the array member + * @return The JAnnotationArrayMember. More elements can be added by calling + * the same method multiple times + */ + public JAnnotationArrayMember param(byte value) { + JAnnotationValue annotationValue = new JAnnotationStringValue(JExpr.lit(value)); + values.add(annotationValue); + return this; + } + + /** + * Adds an array member to this annotation + * + * @param value Adds a char value to the array member + * @return The JAnnotationArrayMember. More elements can be added by calling + * the same method multiple times + */ + public JAnnotationArrayMember param(char value) { + JAnnotationValue annotationValue = new JAnnotationStringValue(JExpr.lit(value)); + values.add(annotationValue); + return this; + } + + /** + * Adds an array member to this annotation + * + * @param value Adds a double value to the array member + * @return The JAnnotationArrayMember. More elements can be added by calling + * the same method multiple times + */ + public JAnnotationArrayMember param(double value) { + JAnnotationValue annotationValue = new JAnnotationStringValue(JExpr.lit(value)); + values.add(annotationValue); + return this; + } + + /** + * Adds an array member to this annotation + * + * @param value Adds a long value to the array member + * @return The JAnnotationArrayMember. More elements can be added by calling + * the same method multiple times + */ + public JAnnotationArrayMember param(long value) { + JAnnotationValue annotationValue = new JAnnotationStringValue(JExpr.lit(value)); + values.add(annotationValue); + return this; + } + + /** + * Adds an array member to this annotation + * + * @param value Adds a short value to the array member + * @return The JAnnotationArrayMember. More elements can be added by calling + * the same method multiple times + */ + public JAnnotationArrayMember param(short value) { + JAnnotationValue annotationValue = new JAnnotationStringValue(JExpr.lit(value)); + values.add(annotationValue); + return this; + } + + /** + * Adds an array member to this annotation + * + * @param value Adds an int value to the array member + * @return The JAnnotationArrayMember. More elements can be added by calling + * the same method multiple times + */ + public JAnnotationArrayMember param(int value) { + JAnnotationValue annotationValue = new JAnnotationStringValue(JExpr.lit(value)); + values.add(annotationValue); + return this; + } + + /** + * Adds an array member to this annotation + * + * @param value Adds a float value to the array member + * @return The JAnnotationArrayMember. More elements can be added by calling + * the same method multiple times + */ + public JAnnotationArrayMember param(float value) { + JAnnotationValue annotationValue = new JAnnotationStringValue(JExpr.lit(value)); + values.add(annotationValue); + return this; + } + + /** + * Adds a enum array member to this annotation + * + * @param value Adds a enum value to the array member + * @return The JAnnotationArrayMember. More elements can be added by calling + * the same method multiple times + */ + public JAnnotationArrayMember param(final Enum value) { + JAnnotationValue annotationValue = new JAnnotationValue() { + public void generate(JFormatter f) { + f.t(owner.ref(value.getDeclaringClass())).p('.').p(value.name()); + } + }; + values.add(annotationValue); + return this; + } + + /** + * Adds a enum array member to this annotation + * + * @param value Adds a enum value to the array member + * @return The JAnnotationArrayMember. More elements can be added by calling + * the same method multiple times + */ + public JAnnotationArrayMember param(final JEnumConstant value) { + JAnnotationValue annotationValue = new JAnnotationStringValue(value); + values.add(annotationValue); + return this; + } + + /** + * Adds an expression array member to this annotation + * + * @param value Adds an expression value to the array member + * @return The JAnnotationArrayMember. More elements can be added by calling + * the same method multiple times + */ + public JAnnotationArrayMember param(final JExpression value) { + JAnnotationValue annotationValue = new JAnnotationStringValue(value); + values.add(annotationValue); + return this; + } + + /** + * Adds a class array member to this annotation + * + * @param value Adds a class value to the array member + * @return The JAnnotationArrayMember. More elements can be added by calling + * the same method multiple times + */ + public JAnnotationArrayMember param(final Class value){ + JAnnotationValue annotationValue = new JAnnotationStringValue( + new JExpressionImpl() { + public void generate(JFormatter f) { + f.p(value.getName().replace('$', '.')); + f.p(".class"); + } + }); + values.add(annotationValue); + return this; + } + + public JAnnotationArrayMember param(JType type){ + JClass clazz = type.boxify(); + JAnnotationValue annotationValue = new JAnnotationStringValue ( clazz.dotclass() ); + values.add(annotationValue); + return this; + } + + /** + * Adds a new annotation to the array. + */ + public JAnnotationUse annotate(Class clazz){ + return annotate(owner.ref(clazz)); + } + + /** + * Adds a new annotation to the array. + */ + public JAnnotationUse annotate(JClass clazz){ + JAnnotationUse a = new JAnnotationUse(clazz); + values.add(a); + return a; + } + + public W annotate2(Class clazz) { + return TypedAnnotationWriter.create(clazz,this); + } + + /** + * {@link JAnnotatable#annotations()} + */ + @SuppressWarnings("unchecked") + public Collection annotations() { + // this invocation is invalid if the caller isn't adding annotations into an array + // so this potentially type-unsafe conversion would be justified. + return Collections.unmodifiableList((List)values); + } + + /** + * Adds an annotation member to this annotation array + * This can be used for e.g @XmlCollection(values= @XmlCollectionItem(type=Foo.class)) + * @param value + * Adds a annotation to the array member + * @return + * The JAnnotationArrayMember. More elements can be added by calling + * the same method multiple times + * + * @deprecated + * use {@link #annotate} + */ + public JAnnotationArrayMember param (JAnnotationUse value ){ + values.add(value); + return this; + } + + public void generate(JFormatter f) { + f.p('{').nl().i(); + + boolean first = true; + for (JAnnotationValue aValue : values) { + if (!first) + f.p(',').nl(); + f.g(aValue); + first = false; + } + f.nl().o().p('}'); + } +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JAnnotationStringValue.java b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JAnnotationStringValue.java new file mode 100644 index 00000000000..5b541833e79 --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JAnnotationStringValue.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.codemodel.internal; + + + +/** + * Captures the value of the annotation. + * + * @author + * Bhakti Mehta (bhakti.mehta@sun.com) + */ +final class JAnnotationStringValue extends JAnnotationValue { + + /** + * The value of the Annotation member + */ + private final JExpression value; + + JAnnotationStringValue(JExpression value) { + this.value = value; + } + + public void generate(JFormatter f) { + f.g(value); + } +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JAnnotationUse.java b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JAnnotationUse.java new file mode 100644 index 00000000000..14fc2f91946 --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JAnnotationUse.java @@ -0,0 +1,426 @@ +/* + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.codemodel.internal; + + +import java.lang.annotation.Annotation; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * Represents an annotation on a program element. + * + * TODO + * How to add enums to the annotations + * @author + * Bhakti Mehta (bhakti.mehta@sun.com) + */ +public final class JAnnotationUse extends JAnnotationValue { + + /** + * The {@link Annotation} class + */ + private final JClass clazz; + + /** + * Map of member values. + */ + private Map memberValues; + + JAnnotationUse(JClass clazz){ + this.clazz = clazz; + } + + public JClass getAnnotationClass() { + return clazz; + } + + public Map getAnnotationMembers() { + return Collections.unmodifiableMap(memberValues); + } + + private JCodeModel owner() { + return clazz.owner(); + } + + private void addValue(String name, JAnnotationValue annotationValue) { + // Use ordered map to keep the code generation the same on any JVM. + // Lazily created. + if(memberValues==null) + memberValues = new LinkedHashMap(); + memberValues.put(name,annotationValue); + } + + /** + * Adds a member value pair to this annotation + * + * @param name + * The simple name for this annotation + * + * @param value + * The boolean value for this annotation + * @return + * The JAnnotationUse. More member value pairs can + * be added to it using the same or the overloaded methods. + * + */ + public JAnnotationUse param(String name, boolean value){ + addValue(name, new JAnnotationStringValue(JExpr.lit(value))); + return this; + } + + /** + * Adds a member value pair to this annotation + * @param name + * The simple name for this annotation + * + * @param value + * The byte member value for this annotation + * @return + * The JAnnotationUse. More member value pairs can + * be added to it using the same or the overloaded methods. + * + */ + public JAnnotationUse param(String name, byte value){ + addValue(name, new JAnnotationStringValue(JExpr.lit(value))); + return this; + } + + /** + * Adds a member value pair to this annotation + * @param name + * The simple name for this annotation + * + * @param value + * The char member value for this annotation + * @return + * The JAnnotationUse. More member value pairs can + * be added to it using the same or the overloaded methods. + * + */ + public JAnnotationUse param(String name, char value){ + addValue(name, new JAnnotationStringValue(JExpr.lit(value))); + return this; + } + + /** + * Adds a member value pair to this annotation + * @param name + * The simple name for this annotation + * + * @param value + * The double member value for this annotation + * @return + * The JAnnotationUse. More member value pairs can + * be added to it using the same or the overloaded methods. + * + */ + public JAnnotationUse param(String name, double value){ + addValue(name, new JAnnotationStringValue(JExpr.lit(value))); + return this; + } + + /** + * Adds a member value pair to this annotation + * @param name + * The simple name for this annotation + * + * @param value + * The float member value for this annotation + * @return + * The JAnnotationUse. More member value pairs can + * be added to it using the same or the overloaded methods. + * + */ + public JAnnotationUse param(String name, float value){ + addValue(name, new JAnnotationStringValue(JExpr.lit(value))); + return this; + } + + /** + * Adds a member value pair to this annotation + * @param name + * The simple name for this annotation + * + * @param value + * The long member value for this annotation + * @return + * The JAnnotationUse. More member value pairs can + * be added to it using the same or the overloaded methods. + * + */ + public JAnnotationUse param(String name, long value){ + addValue(name, new JAnnotationStringValue(JExpr.lit(value))); + return this; + } + + /** + * Adds a member value pair to this annotation + * @param name + * The simple name for this annotation + * + * @param value + * The short member value for this annotation + * @return + * The JAnnotationUse. More member value pairs can + * be added to it using the same or the overloaded methods. + * + */ + public JAnnotationUse param(String name, short value){ + addValue(name, new JAnnotationStringValue(JExpr.lit(value))); + return this; + } + + /** + * Adds a member value pair to this annotation + * @param name + * The simple name for this annotation + * + * @param value + * The int member value for this annotation + * @return + * The JAnnotationUse. More member value pairs can + * be added to it using the same or the overloaded methods. + * + */ + public JAnnotationUse param(String name, int value){ + addValue(name, new JAnnotationStringValue(JExpr.lit(value))); + return this; + } + + /** + * Adds a member value pair to this annotation + * @param name + * The simple name for this annotation + * + * @param value + * The String member value for this annotation + * @return + * The JAnnotationUse. More member value pairs can + * be added to it using the same or the overloaded methods. + * + */ + public JAnnotationUse param(String name, String value){ + //Escape string values with quotes so that they can + //be generated accordingly + addValue(name, new JAnnotationStringValue(JExpr.lit(value))); + return this; + } + + /** + * Adds a member value pair to this annotation + * For adding class values as param + * @see #param(String, Class) + * @param name + * The simple name for this annotation + * + * @param value + * The annotation class which is member value for this annotation + * @return + * The JAnnotationUse. More member value pairs can + * be added to it using the same or the overloaded methods. + * + */ + public JAnnotationUse annotationParam(String name, Class value) { + JAnnotationUse annotationUse = new JAnnotationUse(owner().ref(value)); + addValue(name, annotationUse); + return annotationUse; + } + + /** + * Adds a member value pair to this annotation + * @param name + * The simple name for this annotation + * + * @param value + * The enum class which is member value for this annotation + * @return + * The JAnnotationUse. More member value pairs can + * be added to it using the same or the overloaded methods. + * + */ + public JAnnotationUse param(String name, final Enum value) { + addValue(name, new JAnnotationValue() { + public void generate(JFormatter f) { + f.t(owner().ref(value.getDeclaringClass())).p('.').p(value.name()); + } + }); + return this; + } + + /** + * Adds a member value pair to this annotation + * @param name + * The simple name for this annotation + * + * @param value + * The JEnumConstant which is member value for this annotation + * @return + * The JAnnotationUse. More member value pairs can + * be added to it using the same or the overloaded methods. + * + */ + public JAnnotationUse param(String name, JEnumConstant value){ + addValue(name, new JAnnotationStringValue(value)); + return this; + } + + /** + * Adds a member value pair to this annotation + * This can be used for e.g to specify + *

+      *        @XmlCollectionItem(type=Integer.class);
+      * 
+      * For adding a value of Class
+      * @link
+      * #annotationParam(java.lang.String, java.lang.Class)
+      * @param name
+      *        The simple name for this annotation param
+      *
+      * @param value
+      *        The class type of the param
+      * @return
+      *         The JAnnotationUse. More member value pairs can
+      *         be added to it using the same or the overloaded methods.
+      *
+      *
+      *
+      */
+     public JAnnotationUse param(String name, final Class value){
+         addValue(name, new JAnnotationStringValue(
+                         new JExpressionImpl() {
+                                 public void generate(JFormatter f) {
+                                         f.p(value.getName().replace('$', '.'));
+                                         f.p(".class");
+                                }
+                         }));
+         return this;
+    }
+
+    /**
+     * Adds a member value pair to this annotation based on the
+     * type represented by the given JType
+     *
+     * @param name The simple name for this annotation param
+     * @param type the JType representing the actual type
+     * @return The JAnnotationUse. More member value pairs can
+     *         be added to it using the same or the overloaded methods.
+     */
+    public JAnnotationUse param(String name, JType type){
+        JClass c = type.boxify();
+        addValue(name, new JAnnotationStringValue ( c.dotclass() ));
+        return this;
+    }
+
+    /**
+     * Adds a member value pair to this annotation.
+     * @param name
+     *        The simple name for this annotation
+     *
+     * @param value
+     *        The JExpression which provides the contant value for this annotation
+     * @return
+     *         The JAnnotationUse. More member value pairs can
+     *         be added to it using the same or the overloaded methods.
+     *
+     */
+    public JAnnotationUse param(String name, JExpression value){
+        addValue(name, new JAnnotationStringValue(value));
+        return this;
+    }
+
+    /**
+     * Adds a member value pair which is of type array to this annotation
+     * @param name
+     *        The simple name for this annotation
+     *
+     * @return
+     *         The JAnnotationArrayMember. For adding array values
+     *         @see JAnnotationArrayMember
+     *
+     */
+    public JAnnotationArrayMember paramArray(String name){
+        JAnnotationArrayMember arrayMember = new JAnnotationArrayMember(owner());
+        addValue(name, arrayMember);
+        return arrayMember;
+    }
+
+
+//    /**
+//     * This can be used to add annotations inside annotations
+//     * for e.g  @XmlCollection(values= @XmlCollectionItem(type=Foo.class))
+//     * @param className
+//     *         The classname of the annotation to be included
+//     * @return
+//     *         The JAnnotationUse that can be used as a member within this JAnnotationUse
+//     * @deprecated
+//     *      use {@link JAnnotationArrayMember#annotate}
+//     */
+//    public JAnnotationUse annotate(String className) {
+//        JAnnotationUse annotationUse = new JAnnotationUse(owner().ref(className));
+//        return annotationUse;
+//    }
+
+    /**
+     * This can be used to add annotations inside annotations
+     * for e.g  @XmlCollection(values= @XmlCollectionItem(type=Foo.class))
+     * @param clazz
+     *         The annotation class to be included
+     * @return
+     *     The JAnnotationUse that can be used as a member within this JAnnotationUse
+     * @deprecated
+     *      use {@link JAnnotationArrayMember#annotate}
+     */
+    public JAnnotationUse annotate(Class  clazz) {
+         JAnnotationUse annotationUse = new JAnnotationUse(owner().ref(clazz));
+         return annotationUse;
+    }
+
+    public void generate(JFormatter f) {
+        f.p('@').g(clazz);
+        if(memberValues!=null) {
+            f.p('(');
+            boolean first = true;
+
+            if(isOptimizable()) {
+                // short form
+                f.g(memberValues.get("value"));
+            } else {
+                for (Map.Entry mapEntry : memberValues.entrySet()) {
+                    if (!first) f.p(',');
+                    f.p(mapEntry.getKey()).p('=').g(mapEntry.getValue());
+                    first = false;
+                }
+            }
+            f.p(')');
+        }
+    }
+
+    private boolean isOptimizable() {
+        return memberValues.size()==1 && memberValues.containsKey("value");
+    }
+}
diff --git a/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JAnnotationValue.java b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JAnnotationValue.java
new file mode 100644
index 00000000000..eb000aa4e80
--- /dev/null
+++ b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JAnnotationValue.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.codemodel.internal;
+
+/**
+ * Things that can be values of an annotation element.
+ *
+ * @author
+ *     Bhakti Mehta (bhakti.mehta@sun.com)
+ */
+public abstract class JAnnotationValue implements JGenerable {
+}
diff --git a/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JAnnotationWriter.java b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JAnnotationWriter.java
new file mode 100644
index 00000000000..51fb6edc0c4
--- /dev/null
+++ b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JAnnotationWriter.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.codemodel.internal;
+
+import java.lang.annotation.Annotation;
+
+/**
+ * Base interface for typed annotation writer.
+ *
+ * 

+ * Annotation compiler can generate a strongly typed annotation + * writer to assist applications to write uses of annotations. + * Such typed annotation writer interfaces all derive from + * this common interface. + * + *

+ * The type parameter 'A' represents the + * @author Kohsuke Kawaguchi + */ +public interface JAnnotationWriter { + /** + * Gets the underlying annotation use object to which we are writing. + */ + JAnnotationUse getAnnotationUse(); + + /** + * The type of the annotation that this writer is writing. + */ + Class getAnnotationType(); +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JAnonymousClass.java b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JAnonymousClass.java new file mode 100644 index 00000000000..82c19ffeaa1 --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JAnonymousClass.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.codemodel.internal; + +/** + * Anonymous class quick hack. + * + * @author + * Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com) + */ +class JAnonymousClass extends JDefinedClass { + + /** + * Base interface/class from which this anonymous class is built. + */ + private final JClass base; + + JAnonymousClass( JClass _base) { + super(_base.owner(), 0, null); + this.base = _base; + } + + @Override + public String fullName() { + return base.fullName(); + } + + @Override + public void generate(JFormatter f) { + f.t(base); + } + +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JArray.java b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JArray.java new file mode 100644 index 00000000000..08801c3937a --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JArray.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.codemodel.internal; + +import java.util.ArrayList; +import java.util.List; + + +/** + * array creation and initialization. + */ +public final class JArray extends JExpressionImpl { + + private final JType type; + private final JExpression size; + private List exprs = null; + + /** + * Add an element to the array initializer + */ + public JArray add(JExpression e) { + if (exprs == null) + exprs = new ArrayList(); + exprs.add(e); + return this; + } + + JArray(JType type, JExpression size) { + this.type = type; + this.size = size; + } + + public void generate(JFormatter f) { + + // generally we produce new T[x], but when T is an array type (T=T'[]) + // then new T'[][x] is wrong. It has to be new T'[x][]. + int arrayCount = 0; + JType t = type; + + while( t.isArray() ) { + t = t.elementType(); + arrayCount++; + } + + f.p("new").g(t).p('['); + if (size != null) + f.g(size); + f.p(']'); + + for( int i=0; i _implements() { + return Collections.emptyList().iterator(); + } + + public boolean isInterface() { + return false; + } + + public boolean isAbstract() { + return false; + } + + public JType elementType() { + return componentType; + } + + public boolean isArray() { + return true; + } + + + // + // Equality is based on value + // + + public boolean equals(Object obj) { + if(!(obj instanceof JArrayClass)) return false; + + if( componentType.equals( ((JArrayClass)obj).componentType ) ) + return true; + + return false; + } + + public int hashCode() { + return componentType.hashCode(); + } + + protected JClass substituteParams(JTypeVar[] variables, List bindings) { + if( componentType.isPrimitive() ) + return this; + + JClass c = ((JClass)componentType).substituteParams(variables,bindings); + if(c==componentType) + return this; + + return new JArrayClass(owner(),c); + } + +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JArrayCompRef.java b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JArrayCompRef.java new file mode 100644 index 00000000000..4cc6aa72960 --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JArrayCompRef.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.codemodel.internal; + +/** + * array component reference. + */ +final class JArrayCompRef extends JExpressionImpl implements JAssignmentTarget { + /** + * JArray expression upon which this component will be accessed. + */ + private final JExpression array; + + /** + * Integer expression representing index of the component + */ + private final JExpression index; + + /** + * JArray component reference constructor given an array expression + * and index. + * + * @param array + * JExpression for the array upon which + * the component will be accessed, + * + * @param index + * JExpression for index of component to access + */ + JArrayCompRef(JExpression array, JExpression index) { + if ((array == null) || (index == null)) { + throw new NullPointerException(); + } + this.array = array; + this.index = index; + } + + public void generate(JFormatter f) { + f.g(array).p('[').g(index).p(']'); + } + + public JExpression assign(JExpression rhs) { + return JExpr.assign(this,rhs); + } + public JExpression assignPlus(JExpression rhs) { + return JExpr.assignPlus(this,rhs); + } +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JAssignment.java b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JAssignment.java new file mode 100644 index 00000000000..9124b1e6a69 --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JAssignment.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.codemodel.internal; + + +/** + * Assignment statements, which are also expressions. + */ +public class JAssignment extends JExpressionImpl implements JStatement { + + JAssignmentTarget lhs; + JExpression rhs; + String op = ""; + + JAssignment(JAssignmentTarget lhs, JExpression rhs) { + this.lhs = lhs; + this.rhs = rhs; + } + + JAssignment(JAssignmentTarget lhs, JExpression rhs, String op) { + this.lhs = lhs; + this.rhs = rhs; + this.op = op; + } + + public void generate(JFormatter f) { + f.g(lhs).p(op + '=').g(rhs); + } + + public void state(JFormatter f) { + f.g(this).p(';').nl(); + } + +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JAssignmentTarget.java b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JAssignmentTarget.java new file mode 100644 index 00000000000..e0544273902 --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JAssignmentTarget.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.codemodel.internal; + + +/** + * Marker interface for code components that can be placed to + * the left of '=' in an assignment. + * + * A left hand value can always be a right hand value, so + * this interface derives from {@link JExpression}. + */ +public interface JAssignmentTarget extends JGenerable, JExpression { + JExpression assign(JExpression rhs); + JExpression assignPlus(JExpression rhs); +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JAtom.java b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JAtom.java new file mode 100644 index 00000000000..02c5c18aa16 --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JAtom.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.codemodel.internal; + + +/** + * JAtoms: Simple code components that merely generate themselves. + */ +final class JAtom extends JExpressionImpl { + + private final String what; + + JAtom(String what) { + this.what = what; + } + + public void generate(JFormatter f) { + f.p(what); + } +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JBlock.java b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JBlock.java new file mode 100644 index 00000000000..72e8608e8a4 --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JBlock.java @@ -0,0 +1,454 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.codemodel.internal; + +import java.util.ArrayList; +import java.util.List; +import java.util.Collections; + +/** + * A block of Java code, which may contain statements and local declarations. + * + *

+ * {@link JBlock} contains a large number of factory methods that creates new + * statements/declarations. Those newly created statements/declarations are + * inserted into the {@link #pos() "current position"}. The position advances + * one every time you add a new instruction. + */ +public final class JBlock implements JGenerable, JStatement { + + /** + * Declarations and statements contained in this block. + * Either {@link JStatement} or {@link JDeclaration}. + */ + private final List content = new ArrayList(); + + /** + * Whether or not this block must be braced and indented + */ + private boolean bracesRequired = true; + private boolean indentRequired = true; + + /** + * Current position. + */ + private int pos; + + public JBlock() { + this(true,true); + } + + public JBlock(boolean bracesRequired, boolean indentRequired) { + this.bracesRequired = bracesRequired; + this.indentRequired = indentRequired; + } + + /** + * Returns a read-only view of {@link JStatement}s and {@link JDeclaration} + * in this block. + */ + public List getContents() { + return Collections.unmodifiableList(content); + } + + private T insert( T statementOrDeclaration ) { + content.add(pos,statementOrDeclaration); + pos++; + return statementOrDeclaration; + } + + /** + * Gets the current position to which new statements will be inserted. + * + * For example if the value is 0, newly created instructions will be + * inserted at the very beginning of the block. + * + * @see #pos(int) + */ + public int pos() { + return pos; + } + + /** + * Sets the current position. + * + * @return + * the old value of the current position. + * @throws IllegalArgumentException + * if the new position value is illegal. + * + * @see #pos() + */ + public int pos(int newPos) { + int r = pos; + if(newPos>content.size() || newPos<0) + throw new IllegalArgumentException(); + pos = newPos; + + return r; + } + + /** + * Returns true if this block is empty and does not contain + * any statement. + */ + public boolean isEmpty() { + return content.isEmpty(); + } + + /** + * Adds a local variable declaration to this block + * + * @param type + * JType of the variable + * + * @param name + * Name of the variable + * + * @return Newly generated JVar + */ + public JVar decl(JType type, String name) { + return decl(JMod.NONE, type, name, null); + } + + /** + * Adds a local variable declaration to this block + * + * @param type + * JType of the variable + * + * @param name + * Name of the variable + * + * @param init + * Initialization expression for this variable. May be null. + * + * @return Newly generated JVar + */ + public JVar decl(JType type, String name, JExpression init) { + return decl(JMod.NONE, type, name, init); + } + + /** + * Adds a local variable declaration to this block + * + * @param mods + * Modifiers for the variable + * + * @param type + * JType of the variable + * + * @param name + * Name of the variable + * + * @param init + * Initialization expression for this variable. May be null. + * + * @return Newly generated JVar + */ + public JVar decl(int mods, JType type, String name, JExpression init) { + JVar v = new JVar(JMods.forVar(mods), type, name, init); + insert(v); + bracesRequired = true; + indentRequired = true; + return v; + } + + /** + * Creates an assignment statement and adds it to this block. + * + * @param lhs + * Assignable variable or field for left hand side of expression + * + * @param exp + * Right hand side expression + */ + public JBlock assign(JAssignmentTarget lhs, JExpression exp) { + insert(new JAssignment(lhs, exp)); + return this; + } + + public JBlock assignPlus(JAssignmentTarget lhs, JExpression exp) { + insert(new JAssignment(lhs, exp, "+")); + return this; + } + + /** + * Creates an invocation statement and adds it to this block. + * + * @param expr + * JExpression evaluating to the class or object upon which + * the named method will be invoked + * + * @param method + * Name of method to invoke + * + * @return Newly generated JInvocation + */ + public JInvocation invoke(JExpression expr, String method) { + JInvocation i = new JInvocation(expr, method); + insert(i); + return i; + } + + /** + * Creates an invocation statement and adds it to this block. + * + * @param expr + * JExpression evaluating to the class or object upon which + * the method will be invoked + * + * @param method + * JMethod to invoke + * + * @return Newly generated JInvocation + */ + public JInvocation invoke(JExpression expr, JMethod method) { + return insert(new JInvocation(expr, method)); + } + + /** + * Creates a static invocation statement. + */ + public JInvocation staticInvoke(JClass type, String method) { + return insert(new JInvocation(type, method)); + } + + /** + * Creates an invocation statement and adds it to this block. + * + * @param method + * Name of method to invoke + * + * @return Newly generated JInvocation + */ + public JInvocation invoke(String method) { + return insert(new JInvocation((JExpression)null, method)); + } + + /** + * Creates an invocation statement and adds it to this block. + * + * @param method + * JMethod to invoke + * + * @return Newly generated JInvocation + */ + public JInvocation invoke(JMethod method) { + return insert(new JInvocation((JExpression)null, method)); + } + + /** + * Adds a statement to this block + * + * @param s + * JStatement to be added + * + * @return This block + */ + public JBlock add(JStatement s) { // ## Needed? + insert(s); + return this; + } + + /** + * Create an If statement and add it to this block + * + * @param expr + * JExpression to be tested to determine branching + * + * @return Newly generated conditional statement + */ + public JConditional _if(JExpression expr) { + return insert(new JConditional(expr)); + } + + /** + * Create a For statement and add it to this block + * + * @return Newly generated For statement + */ + public JForLoop _for() { + return insert(new JForLoop()); + } + + /** + * Create a While statement and add it to this block + * + * @return Newly generated While statement + */ + public JWhileLoop _while(JExpression test) { + return insert(new JWhileLoop(test)); + } + + /** + * Create a switch/case statement and add it to this block + */ + public JSwitch _switch(JExpression test) { + return insert(new JSwitch(test)); + } + + /** + * Create a Do statement and add it to this block + * + * @return Newly generated Do statement + */ + public JDoLoop _do(JExpression test) { + return insert(new JDoLoop(test)); + } + + /** + * Create a Try statement and add it to this block + * + * @return Newly generated Try statement + */ + public JTryBlock _try() { + return insert(new JTryBlock()); + } + + /** + * Create a return statement and add it to this block + */ + public void _return() { + insert(new JReturn(null)); + } + + /** + * Create a return statement and add it to this block + */ + public void _return(JExpression exp) { + insert(new JReturn(exp)); + } + + /** + * Create a throw statement and add it to this block + */ + public void _throw(JExpression exp) { + insert(new JThrow(exp)); + } + + /** + * Create a break statement and add it to this block + */ + public void _break() { + _break(null); + } + + public void _break(JLabel label) { + insert(new JBreak(label)); + } + + /** + * Create a label, which can be referenced from + * continue and break statements. + */ + public JLabel label(String name) { + JLabel l = new JLabel(name); + insert(l); + return l; + } + + /** + * Create a continue statement and add it to this block + */ + public void _continue(JLabel label) { + insert(new JContinue(label)); + } + + public void _continue() { + _continue(null); + } + + /** + * Create a sub-block and add it to this block + */ + public JBlock block() { + JBlock b = new JBlock(); + b.bracesRequired = false; + b.indentRequired = false; + return insert(b); + } + + /** + * Creates a "literal" statement directly. + * + *

+ * Specified string is printed as-is. + * This is useful as a short-cut. + * + *

+ * For example, you can invoke this method as: + * directStatement("a=b+c;"). + */ + public JStatement directStatement(final String source) { + JStatement s = new JStatement() { + public void state(JFormatter f) { + f.p(source).nl(); + } + }; + add(s); + return s; + } + + public void generate(JFormatter f) { + if (bracesRequired) + f.p('{').nl(); + if (indentRequired) + f.i(); + generateBody(f); + if (indentRequired) + f.o(); + if (bracesRequired) + f.p('}'); + } + + void generateBody(JFormatter f) { + for (Object o : content) { + if (o instanceof JDeclaration) + f.d((JDeclaration) o); + else + f.s((JStatement) o); + } + } + + /** + * Creates an enhanced For statement based on j2se 1.5 JLS + * and add it to this block + * + * @return Newly generated enhanced For statement per j2se 1.5 + * specification + */ + public JForEach forEach(JType varType, String name, JExpression collection) { + return insert(new JForEach( varType, name, collection)); + + } + public void state(JFormatter f) { + f.g(this); + if (bracesRequired) + f.nl(); + } + +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JBreak.java b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JBreak.java new file mode 100644 index 00000000000..ec5a01d7a84 --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JBreak.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.codemodel.internal; + + +/** + * JBreak statement + */ +final class JBreak implements JStatement { + + private final JLabel label; + + /** + * JBreak constructor + * + * @param _label + * break label or null. + */ + JBreak( JLabel _label ) { + this.label = _label; + } + + public void state(JFormatter f) { + if( label==null ) + f.p("break;").nl(); + else + f.p("break").p(label.label).p(';').nl(); + } +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JCase.java b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JCase.java new file mode 100644 index 00000000000..2c7c5a7011d --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JCase.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.codemodel.internal; + +/** + * Case statement + */ +public final class JCase implements JStatement { + + /** + * label part of the case statement + */ + private JExpression label; + + /** + * JBlock of statements which makes up body of this While statement + */ + private JBlock body = null; + + /** + * is this a regular case statement or a default case statement? + */ + private boolean isDefaultCase = false; + + /** + * Construct a case statement + */ + JCase(JExpression label) { + this(label, false); + } + + /** + * Construct a case statement. If isDefaultCase is true, then + * label should be null since default cases don't have a label. + */ + JCase(JExpression label, boolean isDefaultCase) { + this.label = label; + this.isDefaultCase = isDefaultCase; + } + + public JExpression label() { + return label; + } + + public JBlock body() { + if (body == null) body=new JBlock( false, true ); + return body; + } + + public void state(JFormatter f) { + f.i(); + if( !isDefaultCase ) { + f.p("case ").g(label).p(':').nl(); + } else { + f.p("default:").nl(); + } + if (body != null) + f.s(body); + f.o(); + } +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JCast.java b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JCast.java new file mode 100644 index 00000000000..f705d492d59 --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JCast.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.codemodel.internal; + + + +/** + * A cast operation. + */ +final class JCast extends JExpressionImpl { + /** + * JType to which the expression is to be cast. + */ + private final JType type; + + /** + * JExpression to be cast. + */ + private final JExpression object; + + /** + * JCast constructor + * + * @param type + * JType to which the expression is cast + * + * @param object + * JExpression for the object upon which + * the cast is applied + */ + JCast(JType type, JExpression object) { + this.type = type; + this.object = object; + } + + public void generate(JFormatter f) { + f.p("((").g(type).p(')').g(object).p(')'); + } +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JCatchBlock.java b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JCatchBlock.java new file mode 100644 index 00000000000..04769197ed5 --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JCatchBlock.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.codemodel.internal; + + +/** + * Catch block for a try/catch/finally statement + */ + +public class JCatchBlock implements JGenerable { + + JClass exception; + private JVar var = null; + private JBlock body = new JBlock(); + + JCatchBlock(JClass exception) { + this.exception = exception; + } + + public JVar param(String name) { + if (var != null) throw new IllegalStateException(); + var = new JVar(JMods.forVar(JMod.NONE), exception, name, null); + return var; + } + + public JBlock body() { + return body; + } + + public void generate(JFormatter f) { + if (var == null) + var = new JVar(JMods.forVar(JMod.NONE), + exception, "_x", null); + f.p("catch (").b(var).p(')').g(body); + } + +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JClass.java b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JClass.java new file mode 100644 index 00000000000..cf033528e4b --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JClass.java @@ -0,0 +1,356 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.codemodel.internal; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +/** + * Represents a Java reference type, such as a class, an interface, + * an enum, an array type, a parameterized type. + * + *

+ * To be exact, this object represents an "use" of a reference type, + * not necessarily a declaration of it, which is modeled as {@link JDefinedClass}. + */ +public abstract class JClass extends JType +{ + protected JClass( JCodeModel _owner ) { + this._owner = _owner; + } + + /** + * Gets the name of this class. + * + * @return + * name of this class, without any qualification. + * For example, this method returns "String" for + * java.lang.String. + */ + abstract public String name(); + + /** + * Gets the package to which this class belongs. + * TODO: shall we move move this down? + */ + abstract public JPackage _package(); + + /** + * Returns the class in which this class is nested, or null if + * this is a top-level class. + */ + public JClass outer() { + return null; + } + + private final JCodeModel _owner; + /** Gets the JCodeModel object to which this object belongs. */ + public final JCodeModel owner() { return _owner; } + + /** + * Gets the super class of this class. + * + * @return + * Returns the JClass representing the superclass of the + * entity (class or interface) represented by this {@link JClass}. + * Even if no super class is given explicitly or this {@link JClass} + * is not a class, this method still returns + * {@link JClass} for {@link Object}. + * If this JClass represents {@link Object}, return null. + */ + abstract public JClass _extends(); + + /** + * Iterates all super interfaces directly implemented by + * this class/interface. + * + * @return + * A non-null valid iterator that iterates all + * {@link JClass} objects that represents those interfaces + * implemented by this object. + */ + abstract public Iterator _implements(); + + /** + * Iterates all the type parameters of this class/interface. + * + *

+ * For example, if this {@link JClass} represents + * Set<T>, this method returns an array + * that contains single {@link JTypeVar} for 'T'. + */ + public JTypeVar[] typeParams() { + return EMPTY_ARRAY; + } + + /** + * Sometimes useful reusable empty array. + */ + protected static final JTypeVar[] EMPTY_ARRAY = new JTypeVar[0]; + + /** + * Checks if this object represents an interface. + */ + abstract public boolean isInterface(); + + /** + * Checks if this class is an abstract class. + */ + abstract public boolean isAbstract(); + + /** + * If this class represents one of the wrapper classes + * defined in the java.lang package, return the corresponding + * primitive type. Otherwise null. + */ + public JPrimitiveType getPrimitiveType() { return null; } + + /** + * @deprecated calling this method from {@link JClass} + * would be meaningless, since it's always guaranteed to + * return this. + */ + public JClass boxify() { return this; } + + public JType unboxify() { + JPrimitiveType pt = getPrimitiveType(); + return pt==null ? (JType)this : pt; + } + + public JClass erasure() { + return this; + } + + /** + * Checks the relationship between two classes. + *

+ * This method works in the same way as {@link Class#isAssignableFrom(Class)} + * works. For example, baseClass.isAssignableFrom(derivedClass)==true. + */ + public final boolean isAssignableFrom( JClass derived ) { + // to avoid the confusion, always use "this" explicitly in this method. + + // null can be assigned to any type. + if( derived instanceof JNullType ) return true; + + if( this==derived ) return true; + + // the only class that is assignable from an interface is + // java.lang.Object + if( this==_package().owner().ref(Object.class) ) return true; + + JClass b = derived._extends(); + if( b!=null && this.isAssignableFrom(b) ) + return true; + + if( this.isInterface() ) { + Iterator itfs = derived._implements(); + while( itfs.hasNext() ) + if( this.isAssignableFrom(itfs.next()) ) + return true; + } + + return false; + } + + /** + * Gets the parameterization of the given base type. + * + *

+ * For example, given the following + *


+     * interface Foo<T> extends List<List<T>> {}
+     * interface Bar extends Foo<String> {}
+     * 
+ * This method works like this: + *

+     * getBaseClass( Bar, List ) = List<List<String>
+     * getBaseClass( Bar, Foo  ) = Foo<String>
+     * getBaseClass( Foo<? extends Number>, Collection ) = Collection<List<? extends Number>>
+     * getBaseClass( ArrayList<? extends BigInteger>, List ) = List<? extends BigInteger>
+     * 
+ * + * @param baseType + * The class whose parameterization we are interested in. + * @return + * The use of {@code baseType} in {@code this} type. + * or null if the type is not assignable to the base type. + */ + public final JClass getBaseClass( JClass baseType ) { + + if( this.erasure().equals(baseType) ) + return this; + + JClass b = _extends(); + if( b!=null ) { + JClass bc = b.getBaseClass(baseType); + if(bc!=null) + return bc; + } + + Iterator itfs = _implements(); + while( itfs.hasNext() ) { + JClass bc = itfs.next().getBaseClass(baseType); + if(bc!=null) + return bc; + } + + return null; + } + + public final JClass getBaseClass( Class baseType ) { + return getBaseClass(owner().ref(baseType)); + } + + + private JClass arrayClass; + public JClass array() { + if(arrayClass==null) + arrayClass = new JArrayClass(owner(),this); + return arrayClass; + } + + /** + * "Narrows" a generic class to a concrete class by specifying + * a type argument. + * + *

+ * .narrow(X) builds Set<X> from Set. + */ + public JClass narrow( Class clazz ) { + return narrow(owner().ref(clazz)); + } + + public JClass narrow( Class... clazz ) { + JClass[] r = new JClass[clazz.length]; + for( int i=0; i + * .narrow(X) builds Set<X> from Set. + */ + public JClass narrow( JClass clazz ) { + return new JNarrowedClass(this,clazz); + } + + public JClass narrow( JType type ) { + return narrow(type.boxify()); + } + + public JClass narrow( JClass... clazz ) { + return new JNarrowedClass(this,Arrays.asList(clazz.clone())); + } + + public JClass narrow( List clazz ) { + return new JNarrowedClass(this,new ArrayList(clazz)); + } + + /** + * If this class is parameterized, return the type parameter of the given index. + */ + public List getTypeParameters() { + return Collections.emptyList(); + } + + /** + * Returns true if this class is a parameterized class. + */ + public final boolean isParameterized() { + return erasure()!=this; + } + + /** + * Create "? extends T" from T. + * + * @return never null + */ + public final JClass wildcard() { + return new JTypeWildcard(this); + } + + /** + * Substitutes the type variables with their actual arguments. + * + *

+ * For example, when this class is Map<String,Map<V>>, + * (where V then doing + * substituteParams( V, Integer ) returns a {@link JClass} + * for Map<String,Map<Integer>>. + * + *

+ * This method needs to work recursively. + */ + protected abstract JClass substituteParams( JTypeVar[] variables, List bindings ); + + public String toString() { + return this.getClass().getName() + '(' + name() + ')'; + } + + + public final JExpression dotclass() { + return JExpr.dotclass(this); + } + + /** Generates a static method invocation. */ + public final JInvocation staticInvoke(JMethod method) { + return new JInvocation(this,method); + } + + /** Generates a static method invocation. */ + public final JInvocation staticInvoke(String method) { + return new JInvocation(this,method); + } + + /** Static field reference. */ + public final JFieldRef staticRef(String field) { + return new JFieldRef(this, field); + } + + /** Static field reference. */ + public final JFieldRef staticRef(JVar field) { + return new JFieldRef(this, field); + } + + public void generate(JFormatter f) { + f.t(this); + } + + /** + * Prints the class name in javadoc @link format. + */ + void printLink(JFormatter f) { + f.p("{@link ").g(this).p('}'); + } +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JClassAlreadyExistsException.java b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JClassAlreadyExistsException.java new file mode 100644 index 00000000000..cb1140fe1a6 --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JClassAlreadyExistsException.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.codemodel.internal; + +/** + * Indicates that the class is already created. + * + * @author + * Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com) + */ +public class JClassAlreadyExistsException extends Exception { + + private static final long serialVersionUID = 1L; + + private final JDefinedClass existing; + + public JClassAlreadyExistsException( JDefinedClass _existing ) { + this.existing = _existing; + } + + /** + * Gets a reference to the existing {@link JDefinedClass}. + * + * @return + * This method always return non-null valid object. + */ + public JDefinedClass getExistingClass() { + return existing; + } +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JClassContainer.java b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JClassContainer.java new file mode 100644 index 00000000000..8cdb30b5679 --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JClassContainer.java @@ -0,0 +1,165 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.codemodel.internal; + +import java.util.Iterator; + +/** + * The common aspect of a package and a class. + */ +public interface JClassContainer { + + /** + * Returns true if the container is a class. + */ + boolean isClass(); + /** + * Returns true if the container is a package. + */ + boolean isPackage(); + + /** + * Add a new class to this package/class. + * + * @param mods + * Modifiers for this class declaration + * + * @param name + * Name of class to be added to this package + * + * @return Newly generated class + * + * @exception JClassAlreadyExistsException + * When the specified class/interface was already created. + */ + JDefinedClass _class(int mods, String name) throws JClassAlreadyExistsException; + + /** + * Add a new public class to this class/package. + * + * @exception JClassAlreadyExistsException + * When the specified class/interface was already created. + */ + public JDefinedClass _class(String name) throws JClassAlreadyExistsException; + + /** + * Add an interface to this class/package. + * + * @param mods + * Modifiers for this interface declaration + * + * @param name + * Name of interface to be added to this package + * + * @return Newly generated interface + * + * @exception JClassAlreadyExistsException + * When the specified class/interface was already created. + */ + public JDefinedClass _interface(int mods, String name) throws JClassAlreadyExistsException; + + /** + * Adds a public interface to this package. + * + * @exception JClassAlreadyExistsException + * When the specified class/interface was already created. + */ + public JDefinedClass _interface(String name) throws JClassAlreadyExistsException; + + /** + * Create a new class or a new interface. + * + * @deprecated + * use {@link #_class(int, String, ClassType)} + */ + public JDefinedClass _class(int mods, String name, boolean isInterface ) + throws JClassAlreadyExistsException; + + /** + * Creates a new class/enum/interface/annotation. + */ + public JDefinedClass _class(int mods, String name, ClassType kind ) + throws JClassAlreadyExistsException; + + + /** + * Returns an iterator that walks the nested classes defined in this + * class. + */ + public Iterator classes(); + + /** + * Parent JClassContainer. + * + * If this is a package, this method returns a parent package, + * or null if this package is the root package. + * + * If this is an outer-most class, this method returns a package + * to which it belongs. + * + * If this is an inner class, this method returns the outer + * class. + */ + public JClassContainer parentContainer(); + + /** + * Gets the nearest package parent. + * + *

+ * If this.isPackage(), then return this. + */ + public JPackage getPackage(); + + /** + * Get the root code model object. + */ + public JCodeModel owner(); + + /** + * Add an annotationType Declaration to this package + * @param name + * Name of the annotation Type declaration to be added to this package + * @return + * newly created Annotation Type Declaration + * @exception JClassAlreadyExistsException + * When the specified class/interface was already created. + + */ + public JDefinedClass _annotationTypeDeclaration(String name) throws JClassAlreadyExistsException; + + /** + * Add a public enum to this package + * @param name + * Name of the enum to be added to this package + * @return + * newly created Enum + * @exception JClassAlreadyExistsException + * When the specified class/interface was already created. + + */ + public JDefinedClass _enum (String name) throws JClassAlreadyExistsException; + +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JCodeModel.java b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JCodeModel.java new file mode 100644 index 00000000000..c08016fe94f --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JCodeModel.java @@ -0,0 +1,667 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.codemodel.internal; + +import java.io.File; +import java.io.IOException; +import java.io.PrintStream; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import com.sun.codemodel.internal.writer.FileCodeWriter; +import com.sun.codemodel.internal.writer.ProgressCodeWriter; + + +/** + * Root of the code DOM. + * + *

+ * Here's your typical CodeModel application. + * + *

+ * JCodeModel cm = new JCodeModel();
+ *
+ * // generate source code by populating the 'cm' tree.
+ * cm._class(...);
+ * ...
+ *
+ * // write them out
+ * cm.build(new File("."));
+ * 
+ * + *

+ * Every CodeModel node is always owned by one {@link JCodeModel} object + * at any given time (which can be often accesesd by the owner() method.) + * + * As such, when you generate Java code, most of the operation works + * in a top-down fashion. For example, you create a class from {@link JCodeModel}, + * which gives you a {@link JDefinedClass}. Then you invoke a method on it + * to generate a new method, which gives you {@link JMethod}, and so on. + * + * There are a few exceptions to this, most notably building {@link JExpression}s, + * but generally you work with CodeModel in a top-down fashion. + * + * Because of this design, most of the CodeModel classes aren't directly instanciable. + * + * + *

Where to go from here?

+ *

+ * Most of the time you'd want to populate new type definitions in a {@link JCodeModel}. + * See {@link #_class(String, ClassType)}. + */ +public final class JCodeModel { + + /** The packages that this JCodeWriter contains. */ + private HashMap packages = new HashMap(); + + /** All JReferencedClasses are pooled here. */ + private final HashMap,JReferencedClass> refClasses = new HashMap,JReferencedClass>(); + + + /** Obtains a reference to the special "null" type. */ + public final JNullType NULL = new JNullType(this); + // primitive types + public final JPrimitiveType VOID = new JPrimitiveType(this,"void", Void.class); + public final JPrimitiveType BOOLEAN = new JPrimitiveType(this,"boolean",Boolean.class); + public final JPrimitiveType BYTE = new JPrimitiveType(this,"byte", Byte.class); + public final JPrimitiveType SHORT = new JPrimitiveType(this,"short", Short.class); + public final JPrimitiveType CHAR = new JPrimitiveType(this,"char", Character.class); + public final JPrimitiveType INT = new JPrimitiveType(this,"int", Integer.class); + public final JPrimitiveType FLOAT = new JPrimitiveType(this,"float", Float.class); + public final JPrimitiveType LONG = new JPrimitiveType(this,"long", Long.class); + public final JPrimitiveType DOUBLE = new JPrimitiveType(this,"double", Double.class); + + /** + * If the flag is true, we will consider two classes "Foo" and "foo" + * as a collision. + */ + protected static final boolean isCaseSensitiveFileSystem = getFileSystemCaseSensitivity(); + + private static boolean getFileSystemCaseSensitivity() { + try { + // let the system property override, in case the user really + // wants to override. + if( System.getProperty("com.sun.codemodel.internal.FileSystemCaseSensitive")!=null ) + return true; + } catch( Exception e ) {} + + // on Unix, it's case sensitive. + return (File.separatorChar == '/'); + } + + + public JCodeModel() {} + + /** + * Add a package to the list of packages to be generated + * + * @param name + * Name of the package. Use "" to indicate the root package. + * + * @return Newly generated package + */ + public JPackage _package(String name) { + JPackage p = packages.get(name); + if (p == null) { + p = new JPackage(name, this); + packages.put(name, p); + } + return p; + } + + public final JPackage rootPackage() { + return _package(""); + } + + /** + * Returns an iterator that walks the packages defined using this code + * writer. + */ + public Iterator packages() { + return packages.values().iterator(); + } + + /** + * Creates a new generated class. + * + * @exception JClassAlreadyExistsException + * When the specified class/interface was already created. + */ + public JDefinedClass _class(String fullyqualifiedName) throws JClassAlreadyExistsException { + return _class(fullyqualifiedName,ClassType.CLASS); + } + + /** + * Creates a dummy, unknown {@link JClass} that represents a given name. + * + *

+ * This method is useful when the code generation needs to include the user-specified + * class that may or may not exist, and only thing known about it is a class name. + */ + public JClass directClass(String name) { + return new JDirectClass(this,name); + } + + /** + * Creates a new generated class. + * + * @exception JClassAlreadyExistsException + * When the specified class/interface was already created. + */ + public JDefinedClass _class(int mods, String fullyqualifiedName,ClassType t) throws JClassAlreadyExistsException { + int idx = fullyqualifiedName.lastIndexOf('.'); + if( idx<0 ) return rootPackage()._class(fullyqualifiedName); + else + return _package(fullyqualifiedName.substring(0,idx)) + ._class(mods, fullyqualifiedName.substring(idx+1), t ); + } + + /** + * Creates a new generated class. + * + * @exception JClassAlreadyExistsException + * When the specified class/interface was already created. + */ + public JDefinedClass _class(String fullyqualifiedName,ClassType t) throws JClassAlreadyExistsException { + return _class( JMod.PUBLIC, fullyqualifiedName, t ); + } + + /** + * Gets a reference to the already created generated class. + * + * @return null + * If the class is not yet created. + * @see JPackage#_getClass(String) + */ + public JDefinedClass _getClass(String fullyQualifiedName) { + int idx = fullyQualifiedName.lastIndexOf('.'); + if( idx<0 ) return rootPackage()._getClass(fullyQualifiedName); + else + return _package(fullyQualifiedName.substring(0,idx)) + ._getClass( fullyQualifiedName.substring(idx+1) ); + } + + /** + * Creates a new anonymous class. + * + * @deprecated + * The naming convention doesn't match the rest of the CodeModel. + * Use {@link #anonymousClass(JClass)} instead. + */ + public JDefinedClass newAnonymousClass(JClass baseType) { + return new JAnonymousClass(baseType); + } + + /** + * Creates a new anonymous class. + */ + public JDefinedClass anonymousClass(JClass baseType) { + return new JAnonymousClass(baseType); + } + + public JDefinedClass anonymousClass(Class baseType) { + return anonymousClass(ref(baseType)); + } + + /** + * Generates Java source code. + * A convenience method for build(destDir,destDir,System.out). + * + * @param destDir + * source files are generated into this directory. + * @param status + * if non-null, progress indication will be sent to this stream. + */ + public void build( File destDir, PrintStream status ) throws IOException { + build(destDir,destDir,status); + } + + /** + * Generates Java source code. + * A convenience method that calls {@link #build(CodeWriter,CodeWriter)}. + * + * @param srcDir + * Java source files are generated into this directory. + * @param resourceDir + * Other resource files are generated into this directory. + * @param status + * if non-null, progress indication will be sent to this stream. + */ + public void build( File srcDir, File resourceDir, PrintStream status ) throws IOException { + CodeWriter src = new FileCodeWriter(srcDir); + CodeWriter res = new FileCodeWriter(resourceDir); + if(status!=null) { + src = new ProgressCodeWriter(src, status ); + res = new ProgressCodeWriter(res, status ); + } + build(src,res); + } + + /** + * A convenience method for build(destDir,System.out). + */ + public void build( File destDir ) throws IOException { + build(destDir,System.out); + } + + /** + * A convenience method for build(srcDir,resourceDir,System.out). + */ + public void build( File srcDir, File resourceDir ) throws IOException { + build(srcDir,resourceDir,System.out); + } + + /** + * A convenience method for build(out,out). + */ + public void build( CodeWriter out ) throws IOException { + build(out,out); + } + + /** + * Generates Java source code. + */ + public void build( CodeWriter source, CodeWriter resource ) throws IOException { + JPackage[] pkgs = packages.values().toArray(new JPackage[packages.size()]); + // avoid concurrent modification exception + for( JPackage pkg : pkgs ) + pkg.build(source,resource); + source.close(); + resource.close(); + } + + /** + * Returns the number of files to be generated if + * {@link #build} is invoked now. + */ + public int countArtifacts() { + int r = 0; + JPackage[] pkgs = packages.values().toArray(new JPackage[packages.size()]); + // avoid concurrent modification exception + for( JPackage pkg : pkgs ) + r += pkg.countArtifacts(); + return r; + } + + + /** + * Obtains a reference to an existing class from its Class object. + * + *

+ * The parameter may not be primitive. + * + * @see #_ref(Class) for the version that handles more cases. + */ + public JClass ref(Class clazz) { + JReferencedClass jrc = (JReferencedClass)refClasses.get(clazz); + if (jrc == null) { + if (clazz.isPrimitive()) + throw new IllegalArgumentException(clazz+" is a primitive"); + if (clazz.isArray()) { + return new JArrayClass(this, _ref(clazz.getComponentType())); + } else { + jrc = new JReferencedClass(clazz); + refClasses.put(clazz, jrc); + } + } + return jrc; + } + + public JType _ref(Class c) { + if(c.isPrimitive()) + return JType.parse(this,c.getName()); + else + return ref(c); + } + + /** + * Obtains a reference to an existing class from its fully-qualified + * class name. + * + *

+ * First, this method attempts to load the class of the given name. + * If that fails, we assume that the class is derived straight from + * {@link Object}, and return a {@link JClass}. + */ + public JClass ref(String fullyQualifiedClassName) { + try { + // try the context class loader first + return ref(SecureLoader.getContextClassLoader().loadClass(fullyQualifiedClassName)); + } catch (ClassNotFoundException e) { + // fall through + } + // then the default mechanism. + try { + return ref(Class.forName(fullyQualifiedClassName)); + } catch (ClassNotFoundException e1) { + // fall through + } + + // assume it's not visible to us. + return new JDirectClass(this,fullyQualifiedClassName); + } + + /** + * Cached for {@link #wildcard()}. + */ + private JClass wildcard; + + /** + * Gets a {@link JClass} representation for "?", + * which is equivalent to "? extends Object". + */ + public JClass wildcard() { + if(wildcard==null) + wildcard = ref(Object.class).wildcard(); + return wildcard; + } + + /** + * Obtains a type object from a type name. + * + *

+ * This method handles primitive types, arrays, and existing {@link Class}es. + * + * @exception ClassNotFoundException + * If the specified type is not found. + */ + public JType parseType(String name) throws ClassNotFoundException { + // array + if(name.endsWith("[]")) + return parseType(name.substring(0,name.length()-2)).array(); + + // try primitive type + try { + return JType.parse(this,name); + } catch (IllegalArgumentException e) { + ; + } + + // existing class + return new TypeNameParser(name).parseTypeName(); + } + + private final class TypeNameParser { + private final String s; + private int idx; + + public TypeNameParser(String s) { + this.s = s; + } + + /** + * Parses a type name token T (which can be potentially of the form Tr&ly;T1,T2,...>, + * or "? extends/super T".) + * + * @return the index of the character next to T. + */ + JClass parseTypeName() throws ClassNotFoundException { + int start = idx; + + if(s.charAt(idx)=='?') { + // wildcard + idx++; + ws(); + String head = s.substring(idx); + if(head.startsWith("extends")) { + idx+=7; + ws(); + return parseTypeName().wildcard(); + } else + if(head.startsWith("super")) { + throw new UnsupportedOperationException("? super T not implemented"); + } else { + // not supported + throw new IllegalArgumentException("only extends/super can follow ?, but found "+s.substring(idx)); + } + } + + while(idx' + * + * @return the index of the character next to '>' + */ + private JClass parseArguments(JClass rawType) throws ClassNotFoundException { + if(s.charAt(idx)!='<') + throw new IllegalArgumentException(); + idx++; + + List args = new ArrayList(); + + while(true) { + args.add(parseTypeName()); + if(idx==s.length()) + throw new IllegalArgumentException("Missing '>' in "+s); + char ch = s.charAt(idx); + if(ch=='>') + return rawType.narrow(args.toArray(new JClass[args.size()])); + + if(ch!=',') + throw new IllegalArgumentException(s); + idx++; + } + + } + } + + /** + * References to existing classes. + * + *

+ * JReferencedClass is kept in a pool so that they are shared. + * There is one pool for each JCodeModel object. + * + *

+ * It is impossible to cache JReferencedClass globally only because + * there is the _package() method, which obtains the owner JPackage + * object, which is scoped to JCodeModel. + */ + private class JReferencedClass extends JClass implements JDeclaration { + private final Class _class; + + JReferencedClass(Class _clazz) { + super(JCodeModel.this); + this._class = _clazz; + assert !_class.isArray(); + } + + public String name() { + return _class.getSimpleName().replace('$','.'); + } + + public String fullName() { + return _class.getName().replace('$','.'); + } + + public String binaryName() { + return _class.getName(); + } + + public JClass outer() { + Class p = _class.getDeclaringClass(); + if(p==null) return null; + return ref(p); + } + + public JPackage _package() { + String name = fullName(); + + // this type is array + if (name.indexOf('[') != -1) + return JCodeModel.this._package(""); + + // other normal case + int idx = name.lastIndexOf('.'); + if (idx < 0) + return JCodeModel.this._package(""); + else + return JCodeModel.this._package(name.substring(0, idx)); + } + + public JClass _extends() { + Class sp = _class.getSuperclass(); + if (sp == null) { + if(isInterface()) + return owner().ref(Object.class); + return null; + } else + return ref(sp); + } + + public Iterator _implements() { + final Class[] interfaces = _class.getInterfaces(); + return new Iterator() { + private int idx = 0; + public boolean hasNext() { + return idx < interfaces.length; + } + public JClass next() { + return JCodeModel.this.ref(interfaces[idx++]); + } + public void remove() { + throw new UnsupportedOperationException(); + } + }; + } + + public boolean isInterface() { + return _class.isInterface(); + } + + public boolean isAbstract() { + return Modifier.isAbstract(_class.getModifiers()); + } + + public JPrimitiveType getPrimitiveType() { + Class v = boxToPrimitive.get(_class); + if(v!=null) + return JType.parse(JCodeModel.this,v.getName()); + else + return null; + } + + public boolean isArray() { + return false; + } + + public void declare(JFormatter f) { + } + + public JTypeVar[] typeParams() { + // TODO: does JDK 1.5 reflection provides these information? + return super.typeParams(); + } + + protected JClass substituteParams(JTypeVar[] variables, List bindings) { + // TODO: does JDK 1.5 reflection provides these information? + return this; + } + } + + /** + * Conversion from primitive type {@link Class} (such as {@link Integer#TYPE} + * to its boxed type (such as Integer.class) + */ + public static final Map,Class> primitiveToBox; + /** + * The reverse look up for {@link #primitiveToBox} + */ + public static final Map,Class> boxToPrimitive; + + static { + Map,Class> m1 = new HashMap,Class>(); + Map,Class> m2 = new HashMap,Class>(); + + m1.put(Boolean.class,Boolean.TYPE); + m1.put(Byte.class,Byte.TYPE); + m1.put(Character.class,Character.TYPE); + m1.put(Double.class,Double.TYPE); + m1.put(Float.class,Float.TYPE); + m1.put(Integer.class,Integer.TYPE); + m1.put(Long.class,Long.TYPE); + m1.put(Short.class,Short.TYPE); + m1.put(Void.class,Void.TYPE); + + for (Map.Entry, Class> e : m1.entrySet()) + m2.put(e.getValue(),e.getKey()); + + boxToPrimitive = Collections.unmodifiableMap(m1); + primitiveToBox = Collections.unmodifiableMap(m2); + + } +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JCommentPart.java b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JCommentPart.java new file mode 100644 index 00000000000..7bb44ed46ec --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JCommentPart.java @@ -0,0 +1,137 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.codemodel.internal; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; + +/** + * A part is a part of a javadoc comment, and it is a list of values. + * + *

+ * A part can contain a free-form text. This text is modeled as a collection of 'values' + * in this class. A value can be a {@link JType} (which will be prinited with a @link tag), + * anything that can be turned into a {@link String} via the {@link Object#toString()} method, + * or a {@link Collection}/array of those objects. + * + *

+ * Values can be added through the various append methods one by one or in a bulk. + * + * @author Kohsuke Kawaguchi + */ +public class JCommentPart extends ArrayList { + + private static final long serialVersionUID = 1L; + + /** + * Appends a new value. + * + * If the value is {@link JType} it will be printed as a @link tag. + * Otherwise it will be converted to String via {@link Object#toString()}. + */ + public JCommentPart append(Object o) { + add(o); + return this; + } + + public boolean add(Object o) { + flattenAppend(o); + return true; + } + + private void flattenAppend(Object value) { + if(value==null) return; + if(value instanceof Object[]) { + for( Object o : (Object[])value) + flattenAppend(o); + } else + if(value instanceof Collection) { + for( Object o : (Collection)value) + flattenAppend(o); + } else + super.add(value); + } + + /** + * Writes this part into the formatter by using the specified indentation. + */ + protected void format( JFormatter f, String indent ) { + if(!f.isPrinting()) { + // quickly pass the types to JFormatter, as that's all we care. + // we don't need to worry about the exact formatting of text. + for( Object o : this ) + if(o instanceof JClass) + f.g((JClass)o); + return; + } + + if(!isEmpty()) + f.p(indent); + + Iterator itr = iterator(); + while(itr.hasNext()) { + Object o = itr.next(); + + if(o instanceof String) { + int idx; + String s = (String)o; + while( (idx=s.indexOf('\n'))!=-1 ) { + String line = s.substring(0,idx); + if(line.length()>0) + f.p(escape(line)); + s = s.substring(idx+1); + f.nl().p(indent); + } + if(s.length()!=0) + f.p(escape(s)); + } else + if(o instanceof JClass) { + // TODO: this doesn't print the parameterized type properly + ((JClass)o).printLink(f); + } else + if(o instanceof JType) { + f.g((JType)o); + } else + throw new IllegalStateException(); + } + + if(!isEmpty()) + f.nl(); + } + + /** + * Escapes the appearance of the comment terminator. + */ + private String escape(String s) { + while(true) { + int idx = s.indexOf("*/"); + if(idx <0) return s; + + s = s.substring(0,idx+1)+""+s.substring(idx+1); + } + } +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JConditional.java b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JConditional.java new file mode 100644 index 00000000000..a4f1b02896a --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JConditional.java @@ -0,0 +1,105 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.codemodel.internal; + +/** + * If statement, with optional else clause + */ + +public class JConditional implements JStatement { + + /** + * JExpression to test to determine branching + */ + private JExpression test = null; + + /** + * JBlock of statements for "then" clause + */ + private JBlock _then = new JBlock(); + + /** + * JBlock of statements for optional "else" clause + */ + private JBlock _else = null; + + /** + * Constructor + * + * @param test + * JExpression which will determine branching + */ + JConditional(JExpression test) { + this.test = test; + } + + /** + * Return the block to be excuted by the "then" branch + * + * @return Then block + */ + public JBlock _then() { + return _then; + } + + /** + * Create a block to be executed by "else" branch + * + * @return Newly generated else block + */ + public JBlock _else() { + if (_else == null) _else = new JBlock(); + return _else; + } + + /** + * Creates ... else if(...) ... code. + */ + public JConditional _elseif(JExpression boolExp) { + return _else()._if(boolExp); + } + + public void state(JFormatter f) { + if(test==JExpr.TRUE) { + _then.generateBody(f); + return; + } + if(test==JExpr.FALSE) { + _else.generateBody(f); + return; + } + + if (JOp.hasTopOp(test)) { + f.p("if ").g(test); + } else { + f.p("if (").g(test).p(')'); + } + f.g(_then); + if (_else != null) + f.p("else").g(_else); + f.nl(); + } +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JContinue.java b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JContinue.java new file mode 100644 index 00000000000..7d22e56d8b2 --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JContinue.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.codemodel.internal; + + +/** + * JContinue statement + */ +class JContinue implements JStatement { + + private final JLabel label; + + /** + * JContinue constructor. + * + * @param _label + * a valid label or null. + */ + JContinue(JLabel _label) { + this.label = _label; + } + + public void state(JFormatter f) { + if( label==null ) + f.p("continue;").nl(); + else + f.p("continue").p(label.label).p(';').nl(); + } + +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JDeclaration.java b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JDeclaration.java new file mode 100644 index 00000000000..c438442e705 --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JDeclaration.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.codemodel.internal; + + +/** + * Common interface for code components that can generate declarations + * of themselves. + */ + +public interface JDeclaration { + + public void declare(JFormatter f); + +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JDefinedClass.java b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JDefinedClass.java new file mode 100644 index 00000000000..cd89106293d --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JDefinedClass.java @@ -0,0 +1,898 @@ +/* + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.codemodel.internal; + +import java.lang.annotation.Annotation; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; +import java.util.TreeSet; + +/** + * A generated Java class/interface/enum/.... + * + *

+ * This class models a declaration, and since a declaration can be always + * used as a reference, it inherits {@link JClass}. + * + *

Where to go from here?

+ *

+ * You'd want to generate fields and methods on a class. + * See {@link #method(int, JType, String)} and {@link #field(int, JType, String)}. + */ +public class JDefinedClass + extends JClass + implements JDeclaration, JClassContainer, JGenerifiable, JAnnotatable, JDocCommentable { + + /** Name of this class. Null if anonymous. */ + private String name = null; + + /** Modifiers for the class declaration */ + private JMods mods; + + /** Name of the super class of this class. */ + private JClass superClass; + + /** List of interfaces that this class implements */ + private final Set interfaces = new TreeSet(); + + /** Fields keyed by their names. */ + /*package*/ final Map fields = new LinkedHashMap(); + + /** Static initializer, if this class has one */ + private JBlock init = null; + + /** class javadoc */ + private JDocComment jdoc = null; + + /** Set of constructors for this class, if any */ + private final List constructors = new ArrayList(); + + /** Set of methods that are members of this class */ + private final List methods = new ArrayList(); + + /** + * Nested classes as a map from name to JDefinedClass. + * The name is all capitalized in a case sensitive file system + * ({@link JCodeModel#isCaseSensitiveFileSystem}) to avoid conflicts. + * + * Lazily created to save footprint. + * + * @see #getClasses() + */ + private Map classes; + + + /** + * Flag that controls whether this class should be really generated or not. + * + * Sometimes it is useful to generate code that refers to class X, + * without actually generating the code of X. + * This flag is used to surpress X.java file in the output. + */ + private boolean hideFile = false; + + /** + * Client-app spcific metadata associated with this user-created class. + */ + public Object metadata; + + /** + * String that will be put directly inside the generated code. + * Can be null. + */ + private String directBlock; + + /** + * If this is a package-member class, this is {@link JPackage}. + * If this is a nested class, this is {@link JDefinedClass}. + * If this is an anonymous class, this constructor shouldn't be used. + */ + private JClassContainer outer = null; + + + /** Default value is class or interface + * or annotationTypeDeclaration + * or enum + * + */ + private final ClassType classType; + + /** List containing the enum value declarations + * + */ +// private List enumValues = new ArrayList(); + + /** + * Set of enum constants that are keyed by names. + * In Java, enum constant order is actually significant, + * because of order ID they get. So let's preserve the order. + */ + private final Map enumConstantsByName = new LinkedHashMap(); + + /** + * Annotations on this variable. Lazily created. + */ + private List annotations = null; + + + /** + * Helper class to implement {@link JGenerifiable}. + */ + private final JGenerifiableImpl generifiable = new JGenerifiableImpl() { + protected JCodeModel owner() { + return JDefinedClass.this.owner(); + } + }; + + JDefinedClass(JClassContainer parent, int mods, String name, ClassType classTypeval) { + this(mods, name, parent, parent.owner(), classTypeval); + } + + /** + * Constructor for creating anonymous inner class. + */ + JDefinedClass( + JCodeModel owner, + int mods, + String name) { + this(mods, name, null, owner); + } + + private JDefinedClass( + int mods, + String name, + JClassContainer parent, + JCodeModel owner) { + this (mods,name,parent,owner,ClassType.CLASS); + } + + /** + * JClass constructor + * + * @param mods + * Modifiers for this class declaration + * + * @param name + * Name of this class + */ + private JDefinedClass( + int mods, + String name, + JClassContainer parent, + JCodeModel owner, + ClassType classTypeVal) { + super(owner); + + if(name!=null) { + if (name.trim().length() == 0) + throw new IllegalArgumentException("JClass name empty"); + + if (!Character.isJavaIdentifierStart(name.charAt(0))) { + String msg = + "JClass name " + + name + + " contains illegal character" + + " for beginning of identifier: " + + name.charAt(0); + throw new IllegalArgumentException(msg); + } + for (int i = 1; i < name.length(); i++) { + if (!Character.isJavaIdentifierPart(name.charAt(i))) { + String msg = + "JClass name " + + name + + " contains illegal character " + + name.charAt(i); + throw new IllegalArgumentException(msg); + } + } + } + + this.classType = classTypeVal; + if (isInterface()) + this.mods = JMods.forInterface(mods); + else + this.mods = JMods.forClass(mods); + + this.name = name; + + this.outer = parent; + } + + /** + * Returns true if this is an anonymous class. + */ + public final boolean isAnonymous() { + return name == null; + } + + /** + * This class extends the specifed class. + * + * @param superClass + * Superclass for this class + * + * @return This class + */ + public JDefinedClass _extends(JClass superClass) { + if (this.classType==ClassType.INTERFACE) + if(superClass.isInterface()){ + return this._implements(superClass); + } else throw new IllegalArgumentException("unable to set the super class for an interface"); + if (superClass == null) + throw new NullPointerException(); + + for( JClass o=superClass.outer(); o!=null; o=o.outer() ){ + if(this==o){ + throw new IllegalArgumentException("Illegal class inheritance loop." + + " Outer class " + this.name + " may not subclass from inner class: " + o.name()); + } + } + + this.superClass = superClass; + return this; + } + + public JDefinedClass _extends(Class superClass) { + return _extends(owner().ref(superClass)); + } + + /** + * Returns the class extended by this class. + */ + public JClass _extends() { + if(superClass==null) + superClass = owner().ref(Object.class); + return superClass; + } + + /** + * This class implements the specifed interface. + * + * @param iface + * Interface that this class implements + * + * @return This class + */ + public JDefinedClass _implements(JClass iface) { + interfaces.add(iface); + return this; + } + + public JDefinedClass _implements(Class iface) { + return _implements(owner().ref(iface)); + } + + /** + * Returns an iterator that walks the nested classes defined in this + * class. + */ + public Iterator _implements() { + return interfaces.iterator(); + } + + /** + * JClass name accessor. + * + *

+ * For example, for java.util.List, this method + * returns "List"" + * + * @return Name of this class + */ + public String name() { + return name; + } + + /** + * If the named enum already exists, the reference to it is returned. + * Otherwise this method generates a new enum reference with the given + * name and returns it. + * + * @param name + * The name of the constant. + * @return + * The generated type-safe enum constant. + */ + public JEnumConstant enumConstant(String name){ + JEnumConstant ec = enumConstantsByName.get(name); + if (null == ec) { + ec = new JEnumConstant(this, name); + enumConstantsByName.put(name, ec); + } + return ec; + } + + /** + * Gets the fully qualified name of this class. + */ + public String fullName() { + if (outer instanceof JDefinedClass) + return ((JDefinedClass) outer).fullName() + '.' + name(); + + JPackage p = _package(); + if (p.isUnnamed()) + return name(); + else + return p.name() + '.' + name(); + } + + @Override + public String binaryName() { + if (outer instanceof JDefinedClass) + return ((JDefinedClass) outer).binaryName() + '$' + name(); + else + return fullName(); + } + + public boolean isInterface() { + return this.classType==ClassType.INTERFACE; + } + + public boolean isAbstract() { + return mods.isAbstract(); + } + + /** + * Adds a field to the list of field members of this JDefinedClass. + * + * @param mods + * Modifiers for this field + * + * @param type + * JType of this field + * + * @param name + * Name of this field + * + * @return Newly generated field + */ + public JFieldVar field(int mods, JType type, String name) { + return field(mods, type, name, null); + } + + public JFieldVar field(int mods, Class type, String name) { + return field(mods, owner()._ref(type), name); + } + + /** + * Adds a field to the list of field members of this JDefinedClass. + * + * @param mods + * Modifiers for this field. + * @param type + * JType of this field. + * @param name + * Name of this field. + * @param init + * Initial value of this field. + * + * @return Newly generated field + */ + public JFieldVar field( + int mods, + JType type, + String name, + JExpression init) { + JFieldVar f = new JFieldVar(this,JMods.forField(mods), type, name, init); + + if (fields.containsKey(name)) { + throw new IllegalArgumentException("trying to create the same field twice: "+name); + } + + fields.put(name, f); + return f; + } + + /** This method indicates if the interface + * is an annotationTypeDeclaration + * + */ + public boolean isAnnotationTypeDeclaration() { + return this.classType==ClassType.ANNOTATION_TYPE_DECL; + + + } + + /** + * Add an annotationType Declaration to this package + * @param name + * Name of the annotation Type declaration to be added to this package + * @return + * newly created Annotation Type Declaration + * @exception JClassAlreadyExistsException + * When the specified class/interface was already created. + + */ + public JDefinedClass _annotationTypeDeclaration(String name) throws JClassAlreadyExistsException { + return _class (JMod.PUBLIC,name,ClassType.ANNOTATION_TYPE_DECL); + } + + /** + * Add a public enum to this package + * @param name + * Name of the enum to be added to this package + * @return + * newly created Enum + * @exception JClassAlreadyExistsException + * When the specified class/interface was already created. + + */ + public JDefinedClass _enum (String name) throws JClassAlreadyExistsException { + return _class (JMod.PUBLIC,name,ClassType.ENUM); + } + + /** + * Add a public enum to this package + * @param name + * Name of the enum to be added to this package + * @param mods + * Modifiers for this enum declaration + * @return + * newly created Enum + * @exception JClassAlreadyExistsException + * When the specified class/interface was already created. + + */ + public JDefinedClass _enum (int mods,String name) throws JClassAlreadyExistsException { + return _class (mods,name,ClassType.ENUM); + } + + + + + + public ClassType getClassType(){ + return this.classType; + } + + public JFieldVar field( + int mods, + Class type, + String name, + JExpression init) { + return field(mods, owner()._ref(type), name, init); + } + + /** + * Returns all the fields declred in this class. + * The returned {@link Map} is a read-only live view. + * + * @return always non-null. + */ + public Map fields() { + return Collections.unmodifiableMap(fields); + } + + /** + * Removes a {@link JFieldVar} from this class. + * + * @throws IllegalArgumentException + * if the given field is not a field on this class. + */ + public void removeField(JFieldVar field) { + if(fields.remove(field.name())!=field) + throw new IllegalArgumentException(); + } + + /** + * Creates, if necessary, and returns the static initializer + * for this class. + * + * @return JBlock containing initialization statements for this class + */ + public JBlock init() { + if (init == null) + init = new JBlock(); + return init; + } + + /** + * Adds a constructor to this class. + * + * @param mods + * Modifiers for this constructor + */ + public JMethod constructor(int mods) { + JMethod c = new JMethod(mods, this); + constructors.add(c); + return c; + } + + /** + * Returns an iterator that walks the constructors defined in this class. + */ + public Iterator constructors() { + return constructors.iterator(); + } + + /** + * Looks for a method that has the specified method signature + * and return it. + * + * @return + * null if not found. + */ + public JMethod getConstructor(JType[] argTypes) { + for (JMethod m : constructors) { + if (m.hasSignature(argTypes)) + return m; + } + return null; + } + + /** + * Add a method to the list of method members of this JDefinedClass instance. + * + * @param mods + * Modifiers for this method + * + * @param type + * Return type for this method + * + * @param name + * Name of the method + * + * @return Newly generated JMethod + */ + public JMethod method(int mods, JType type, String name) { + // XXX problems caught in M constructor + JMethod m = new JMethod(this, mods, type, name); + methods.add(m); + return m; + } + + public JMethod method(int mods, Class type, String name) { + return method(mods, owner()._ref(type), name); + } + + /** + * Returns the set of methods defined in this class. + */ + public Collection methods() { + return methods; + } + + /** + * Looks for a method that has the specified method signature + * and return it. + * + * @return + * null if not found. + */ + public JMethod getMethod(String name, JType[] argTypes) { + for (JMethod m : methods) { + if (!m.name().equals(name)) + continue; + + if (m.hasSignature(argTypes)) + return m; + } + return null; + } + + public boolean isClass() { + return true; + } + public boolean isPackage() { + return false; + } + public JPackage getPackage() { return parentContainer().getPackage(); } + + /** + * Add a new nested class to this class. + * + * @param mods + * Modifiers for this class declaration + * + * @param name + * Name of class to be added to this package + * + * @return Newly generated class + */ + public JDefinedClass _class(int mods, String name) + throws JClassAlreadyExistsException { + return _class(mods, name, ClassType.CLASS); + } + + /** + * {@inheritDoc} + * + * @deprecated + */ + public JDefinedClass _class(int mods, String name, boolean isInterface) throws JClassAlreadyExistsException { + return _class(mods,name,isInterface?ClassType.INTERFACE:ClassType.CLASS); + } + + public JDefinedClass _class(int mods, String name, ClassType classTypeVal) + throws JClassAlreadyExistsException { + + String NAME; + if (JCodeModel.isCaseSensitiveFileSystem) + NAME = name.toUpperCase(); + else + NAME = name; + + if (getClasses().containsKey(NAME)) + throw new JClassAlreadyExistsException(getClasses().get(NAME)); + else { + // XXX problems caught in the NC constructor + JDefinedClass c = new JDefinedClass(this, mods, name, classTypeVal); + getClasses().put(NAME,c); + return c; + } + } + + /** + * Add a new public nested class to this class. + */ + public JDefinedClass _class(String name) + throws JClassAlreadyExistsException { + return _class(JMod.PUBLIC, name); + } + + /** + * Add an interface to this package. + * + * @param mods + * Modifiers for this interface declaration + * + * @param name + * Name of interface to be added to this package + * + * @return Newly generated interface + */ + public JDefinedClass _interface(int mods, String name) + throws JClassAlreadyExistsException { + return _class(mods, name, ClassType.INTERFACE); + } + + /** + * Adds a public interface to this package. + */ + public JDefinedClass _interface(String name) + throws JClassAlreadyExistsException { + return _interface(JMod.PUBLIC, name); + } + + /** + * Creates, if necessary, and returns the class javadoc for this + * JDefinedClass + * + * @return JDocComment containing javadocs for this class + */ + public JDocComment javadoc() { + if (jdoc == null) + jdoc = new JDocComment(owner()); + return jdoc; + } + + /** + * Mark this file as hidden, so that this file won't be + * generated. + * + *

+ * This feature could be used to generate code that refers + * to class X, without actually generating X.java. + */ + public void hide() { + hideFile = true; + } + + public boolean isHidden() { + return hideFile; + } + + /** + * Returns an iterator that walks the nested classes defined in this + * class. + */ + public final Iterator classes() { + if(classes==null) + return Collections.emptyList().iterator(); + else + return classes.values().iterator(); + } + + private Map getClasses() { + if(classes==null) + classes = new TreeMap(); + return classes; + } + + + /** + * Returns all the nested classes defined in this class. + */ + public final JClass[] listClasses() { + if(classes==null) + return new JClass[0]; + else + return classes.values().toArray(new JClass[classes.values().size()]); + } + + @Override + public JClass outer() { + if (outer.isClass()) + return (JClass) outer; + else + return null; + } + + public void declare(JFormatter f) { + if (jdoc != null) + f.nl().g(jdoc); + + if (annotations != null){ + for (JAnnotationUse annotation : annotations) + f.g(annotation).nl(); + } + + f.g(mods).p(classType.declarationToken).id(name).d(generifiable); + + if (superClass != null && superClass != owner().ref(Object.class)) + f.nl().i().p("extends").g(superClass).nl().o(); + + if (!interfaces.isEmpty()) { + if (superClass == null) + f.nl(); + f.i().p(classType==ClassType.INTERFACE ? "extends" : "implements"); + f.g(interfaces); + f.nl().o(); + } + declareBody(f); + } + + /** + * prints the body of a class. + */ + protected void declareBody(JFormatter f) { + f.p('{').nl().nl().i(); + boolean first = true; + + if (!enumConstantsByName.isEmpty()) { + for (JEnumConstant c : enumConstantsByName.values()) { + if (!first) f.p(',').nl(); + f.d(c); + first = false; + } + f.p(';').nl(); + } + + for( JFieldVar field : fields.values() ) + f.d(field); + if (init != null) + f.nl().p("static").s(init); + for (JMethod m : constructors) { + f.nl().d(m); + } + for (JMethod m : methods) { + f.nl().d(m); + } + if(classes!=null) + for (JDefinedClass dc : classes.values()) + f.nl().d(dc); + + + if (directBlock != null) + f.p(directBlock); + f.nl().o().p('}').nl(); + } + + /** + * Places the given string directly inside the generated class. + * + * This method can be used to add methods/fields that are not + * generated by CodeModel. + * This method should be used only as the last resort. + */ + public void direct(String string) { + if (directBlock == null) + directBlock = string; + else + directBlock += string; + } + + public final JPackage _package() { + JClassContainer p = outer; + while (!(p instanceof JPackage)) + p = p.parentContainer(); + return (JPackage) p; + } + + public final JClassContainer parentContainer() { + return outer; + } + + public JTypeVar generify(String name) { + return generifiable.generify(name); + } + public JTypeVar generify(String name, Class bound) { + return generifiable.generify(name, bound); + } + public JTypeVar generify(String name, JClass bound) { + return generifiable.generify(name, bound); + } + @Override + public JTypeVar[] typeParams() { + return generifiable.typeParams(); + } + + protected JClass substituteParams( + JTypeVar[] variables, + List bindings) { + return this; + } + + /** Adding ability to annotate a class + * @param clazz + * The annotation class to annotate the class with + */ + public JAnnotationUse annotate(Class clazz){ + return annotate(owner().ref(clazz)); + } + + /** Adding ability to annotate a class + * @param clazz + * The annotation class to annotate the class with + */ + public JAnnotationUse annotate(JClass clazz){ + if(annotations==null) + annotations = new ArrayList(); + JAnnotationUse a = new JAnnotationUse(clazz); + annotations.add(a); + return a; + } + + public W annotate2(Class clazz) { + return TypedAnnotationWriter.create(clazz,this); + } + + /** + * {@link JAnnotatable#annotations()} + */ + public Collection annotations() { + if (annotations == null) + annotations = new ArrayList(); + return Collections.unmodifiableCollection(annotations); + } + + /** + * @return + * the current modifiers of this class. + * Always return non-null valid object. + */ + public JMods mods() { + return mods; + } +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JDirectClass.java b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JDirectClass.java new file mode 100644 index 00000000000..25f03d0b387 --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JDirectClass.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.codemodel.internal; + +import java.util.Iterator; +import java.util.List; +import java.util.Collections; + +/** + * A special {@link JClass} that represents an unknown class (except its name.) + * + * @author Kohsuke Kawaguchi + * @see JCodeModel#directClass(String) + */ +final class JDirectClass extends JClass { + + private final String fullName; + + public JDirectClass(JCodeModel _owner,String fullName) { + super(_owner); + this.fullName = fullName; + } + + public String name() { + int i = fullName.lastIndexOf('.'); + if(i>=0) return fullName.substring(i+1); + return fullName; + } + + public String fullName() { + return fullName; + } + + public JPackage _package() { + int i = fullName.lastIndexOf('.'); + if(i>=0) return owner()._package(fullName.substring(0,i)); + else return owner().rootPackage(); + } + + public JClass _extends() { + return owner().ref(Object.class); + } + + public Iterator _implements() { + return Collections.emptyList().iterator(); + } + + public boolean isInterface() { + return false; + } + + public boolean isAbstract() { + return false; + } + + protected JClass substituteParams(JTypeVar[] variables, List bindings) { + return this; + } +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JDoLoop.java b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JDoLoop.java new file mode 100644 index 00000000000..3e674df3613 --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JDoLoop.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.codemodel.internal; + + +/** + * Do loops + */ + +public class JDoLoop implements JStatement { + + /** + * Test part of Do statement for determining exit state + */ + private JExpression test; + + /** + * JBlock of statements which makes up body of this Do statement + */ + private JBlock body = null; + + /** + * Construct a Do statment + */ + JDoLoop(JExpression test) { + this.test = test; + } + + public JBlock body() { + if (body == null) body = new JBlock(); + return body; + } + + public void state(JFormatter f) { + f.p("do"); + if (body != null) + f.g(body); + else + f.p("{ }"); + + if (JOp.hasTopOp(test)) { + f.p("while ").g(test); + } else { + f.p("while (").g(test).p(')'); + } + f.p(';').nl(); + } + +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JDocComment.java b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JDocComment.java new file mode 100644 index 00000000000..bfe8305a388 --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JDocComment.java @@ -0,0 +1,197 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.codemodel.internal; + +import java.util.HashMap; +import java.util.Map; + +/** + * JavaDoc comment. + * + *

+ * A javadoc comment consists of multiple parts. There's the main part (that comes the first in + * in the comment section), then the parameter parts (@param), the return part (@return), + * and the throws parts (@throws). + * + * TODO: it would be nice if we have JComment class and we can derive this class from there. + */ +public class JDocComment extends JCommentPart implements JGenerable { + + private static final long serialVersionUID = 1L; + + /** list of @param tags */ + private final Map atParams = new HashMap(); + + /** list of xdoclets */ + private final Map> atXdoclets = new HashMap>(); + + /** list of @throws tags */ + private final Map atThrows = new HashMap(); + + /** + * The @return tag part. + */ + private JCommentPart atReturn = null; + + /** The @deprecated tag */ + private JCommentPart atDeprecated = null; + + private final JCodeModel owner; + + + public JDocComment(JCodeModel owner) { + this.owner = owner; + } + + public JDocComment append(Object o) { + add(o); + return this; + } + + /** + * Append a text to a @param tag to the javadoc + */ + public JCommentPart addParam( String param ) { + JCommentPart p = atParams.get(param); + if(p==null) + atParams.put(param,p=new JCommentPart()); + return p; + } + + /** + * Append a text to an @param tag. + */ + public JCommentPart addParam( JVar param ) { + return addParam( param.name() ); + } + + + /** + * add an @throws tag to the javadoc + */ + public JCommentPart addThrows( Class exception ) { + return addThrows( owner.ref(exception) ); + } + + /** + * add an @throws tag to the javadoc + */ + public JCommentPart addThrows( JClass exception ) { + JCommentPart p = atThrows.get(exception); + if(p==null) + atThrows.put(exception,p=new JCommentPart()); + return p; + } + + /** + * Appends a text to @return tag. + */ + public JCommentPart addReturn() { + if(atReturn==null) + atReturn = new JCommentPart(); + return atReturn; + } + + /** + * add an @deprecated tag to the javadoc, with the associated message. + */ + public JCommentPart addDeprecated() { + if(atDeprecated==null) + atDeprecated = new JCommentPart(); + return atDeprecated; + } + + /** + * add an xdoclet. + */ + public Map addXdoclet(String name) { + Map p = atXdoclets.get(name); + if(p==null) + atXdoclets.put(name,p=new HashMap()); + return p; + } + + /** + * add an xdoclet. + */ + public Map addXdoclet(String name, Map attributes) { + Map p = atXdoclets.get(name); + if(p==null) + atXdoclets.put(name,p=new HashMap()); + p.putAll(attributes); + return p; + } + + /** + * add an xdoclet. + */ + public Map addXdoclet(String name, String attribute, String value) { + Map p = atXdoclets.get(name); + if(p==null) + atXdoclets.put(name,p=new HashMap()); + p.put(attribute, value); + return p; + } + + public void generate(JFormatter f) { + // I realized that we can't use StringTokenizer because + // this will recognize multiple \n as one token. + + f.p("/**").nl(); + + format(f," * "); + + f.p(" * ").nl(); + for (Map.Entry e : atParams.entrySet()) { + f.p(" * @param ").p(e.getKey()).nl(); + e.getValue().format(f,INDENT); + } + if( atReturn != null ) { + f.p(" * @return").nl(); + atReturn.format(f,INDENT); + } + for (Map.Entry e : atThrows.entrySet()) { + f.p(" * @throws ").t(e.getKey()).nl(); + e.getValue().format(f,INDENT); + } + if( atDeprecated != null ) { + f.p(" * @deprecated").nl(); + atDeprecated.format(f,INDENT); + } + for (Map.Entry> e : atXdoclets.entrySet()) { + f.p(" * @").p(e.getKey()); + if (e.getValue() != null) { + for (Map.Entry a : e.getValue().entrySet()) { + f.p(" ").p(a.getKey()).p("= \"").p(a.getValue()).p("\""); + } + } + f.nl(); + } + f.p(" */").nl(); + } + + private static final String INDENT = " * "; +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JDocCommentable.java b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JDocCommentable.java new file mode 100644 index 00000000000..b02d1c2533f --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JDocCommentable.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.codemodel.internal; + +/** + * Program elements that can have Javadoc + * + * @author Jonas von Malottki + */ +public interface JDocCommentable { + /** + * @return the JavaDoc of the Element + */ + JDocComment javadoc(); +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JEnumConstant.java b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JEnumConstant.java new file mode 100644 index 00000000000..11c0b515ae6 --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JEnumConstant.java @@ -0,0 +1,160 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.codemodel.internal; + +import java.util.ArrayList; +import java.util.List; +import java.util.Collection; +import java.util.Collections; +import java.lang.annotation.Annotation; + +/** + * Enum Constant. + * + * When used as an {@link JExpression}, this object represents a reference to the enum constant. + * + * @author + * Bhakti Mehta (Bhakti.Mehta@sun.com) + */ +public final class JEnumConstant extends JExpressionImpl implements JDeclaration, JAnnotatable, JDocCommentable { + + /** + * The constant. + */ + private final String name; + /** + * The enum class. + */ + private final JDefinedClass type; + /** + * javadoc comments, if any. + */ + private JDocComment jdoc = null; + + /** + * Annotations on this variable. Lazily created. + */ + private List annotations = null; + + + /** + * List of the constructor argument expressions. + * Lazily constructed. + */ + private List args = null; + + JEnumConstant(JDefinedClass type,String name) { + this.name = name; + this.type = type; + } + + /** + * Add an expression to this constructor's argument list + * + * @param arg + * Argument to add to argument list + */ + public JEnumConstant arg(JExpression arg) { + if(arg==null) throw new IllegalArgumentException(); + if(args==null) + args = new ArrayList(); + args.add(arg); + return this; + } + + /** + * Returns the name of this constant. + * + * @return never null. + */ + public String getName() { + return this.type.fullName().concat(".").concat(this.name); + } + + /** + * Creates, if necessary, and returns the enum constant javadoc. + * + * @return JDocComment containing javadocs for this constant. + */ + public JDocComment javadoc() { + if (jdoc == null) + jdoc = new JDocComment(type.owner()); + return jdoc; + } + + /** + * Adds an annotation to this variable. + * @param clazz + * The annotation class to annotate the field with + */ + public JAnnotationUse annotate(JClass clazz){ + if(annotations==null) + annotations = new ArrayList(); + JAnnotationUse a = new JAnnotationUse(clazz); + annotations.add(a); + return a; + } + + /** + * Adds an annotation to this variable. + * + * @param clazz + * The annotation class to annotate the field with + */ + public JAnnotationUse annotate(Class clazz){ + return annotate(type.owner().ref(clazz)); + } + + public W annotate2(Class clazz) { + return TypedAnnotationWriter.create(clazz,this); + } + + /** + * {@link JAnnotatable#annotations()} + */ + public Collection annotations() { + if (annotations == null) + annotations = new ArrayList(); + return Collections.unmodifiableList(annotations); + } + + public void declare(JFormatter f) { + if( jdoc != null ) + f.nl().g( jdoc ); + if (annotations != null) { + for( int i=0; itrue + */ + public static final JExpression TRUE = new JAtom("true"); + + /** + * Boolean constant that represents false + */ + public static final JExpression FALSE = new JAtom("false"); + + public static JExpression lit(boolean b) { + return b?TRUE:FALSE; + } + + public static JExpression lit(int n) { + return new JAtom(Integer.toString(n)); + } + + public static JExpression lit(long n) { + return new JAtom(Long.toString(n) + "L"); + } + + public static JExpression lit(float f) { + if (f == Float.NEGATIVE_INFINITY) + { + return new JAtom("java.lang.Float.NEGATIVE_INFINITY"); + } + else if (f == Float.POSITIVE_INFINITY) + { + return new JAtom("java.lang.Float.POSITIVE_INFINITY"); + } + else if (Float.isNaN(f)) + { + return new JAtom("java.lang.Float.NaN"); + } + else + { + return new JAtom(Float.toString(f) + "F"); + } + } + + public static JExpression lit(double d) { + if (d == Double.NEGATIVE_INFINITY) + { + return new JAtom("java.lang.Double.NEGATIVE_INFINITY"); + } + else if (d == Double.POSITIVE_INFINITY) + { + return new JAtom("java.lang.Double.POSITIVE_INFINITY"); + } + else if (Double.isNaN(d)) + { + return new JAtom("java.lang.Double.NaN"); + } + else + { + return new JAtom(Double.toString(d) + "D"); + } + } + + static final String charEscape = "\b\t\n\f\r\"\'\\"; + static final String charMacro = "btnfr\"'\\"; + + /** + * Escapes the given string, then surrounds it by the specified + * quotation mark. + */ + public static String quotify(char quote, String s) { + int n = s.length(); + StringBuilder sb = new StringBuilder(n + 2); + sb.append(quote); + for (int i = 0; i < n; i++) { + char c = s.charAt(i); + int j = charEscape.indexOf(c); + if(j>=0) { + if((quote=='"' && c=='\'') || (quote=='\'' && c=='"')) { + sb.append(c); + } else { + sb.append('\\'); + sb.append(charMacro.charAt(j)); + } + } else { + // technically Unicode escape shouldn't be done here, + // for it's a lexical level handling. + // + // However, various tools are so broken around this area, + // so just to be on the safe side, it's better to do + // the escaping here (regardless of the actual file encoding) + // + // see bug + if( c<0x20 || 0x7E + * This method can be used as a short-cut to create a JExpression. + * For example, instead of _a.gt(_b), you can write + * it as: JExpr.direct("a>b"). + * + *

+ * Be warned that there is a danger in using this method, + * as it obfuscates the object model. + */ + public static JExpression direct( final String source ) { + return new JExpressionImpl(){ + public void generate( JFormatter f ) { + f.p('(').p(source).p(')'); + } + }; + } +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JExpression.java b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JExpression.java new file mode 100644 index 00000000000..9311c3f70e4 --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JExpression.java @@ -0,0 +1,150 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.codemodel.internal; + + +/** + * A Java expression. + * + *

+ * Unlike most of CodeModel, JExpressions are built bottom-up ( + * meaning you start from leaves and then gradually build compliated expressions + * by combining them.) + * + *

+ * {@link JExpression} defines a series of composer methods, + * which returns a complicated expression (by often taking other {@link JExpression}s + * as parameters. + * For example, you can build "5+2" by + * JExpr.lit(5).add(JExpr.lit(2)) + */ +public interface JExpression extends JGenerable { + /** + * Returns "-[this]" from "[this]". + */ + JExpression minus(); + + /** + * Returns "![this]" from "[this]". + */ + JExpression not(); + /** + * Returns "~[this]" from "[this]". + */ + JExpression complement(); + + /** + * Returns "[this]++" from "[this]". + */ + JExpression incr(); + + /** + * Returns "[this]--" from "[this]". + */ + JExpression decr(); + + /** + * Returns "[this]+[right]" + */ + JExpression plus(JExpression right); + + /** + * Returns "[this]-[right]" + */ + JExpression minus(JExpression right); + + /** + * Returns "[this]*[right]" + */ + JExpression mul(JExpression right); + + /** + * Returns "[this]/[right]" + */ + JExpression div(JExpression right); + + /** + * Returns "[this]%[right]" + */ + JExpression mod(JExpression right); + + /** + * Returns "[this]<<[right]" + */ + JExpression shl(JExpression right); + + /** + * Returns "[this]>>[right]" + */ + JExpression shr(JExpression right); + + /** + * Returns "[this]>>>[right]" + */ + JExpression shrz(JExpression right); + + /** Bit-wise AND '&'. */ + JExpression band(JExpression right); + + /** Bit-wise OR '|'. */ + JExpression bor(JExpression right); + + /** Logical AND '&&'. */ + JExpression cand(JExpression right); + + /** Logical OR '||'. */ + JExpression cor(JExpression right); + + JExpression xor(JExpression right); + JExpression lt(JExpression right); + JExpression lte(JExpression right); + JExpression gt(JExpression right); + JExpression gte(JExpression right); + JExpression eq(JExpression right); + JExpression ne(JExpression right); + + /** + * Returns "[this] instanceof [right]" + */ + JExpression _instanceof(JType right); + + /** + * Returns "[this].[method]". + * + * Arguments shall be added to the returned {@link JInvocation} object. + */ + JInvocation invoke(JMethod method); + + /** + * Returns "[this].[method]". + * + * Arguments shall be added to the returned {@link JInvocation} object. + */ + JInvocation invoke(String method); + JFieldRef ref(JVar field); + JFieldRef ref(String field); + JArrayCompRef component(JExpression index); +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JExpressionImpl.java b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JExpressionImpl.java new file mode 100644 index 00000000000..6100d7b08a3 --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JExpressionImpl.java @@ -0,0 +1,165 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.codemodel.internal; + +/** + * Provides default implementations for {@link JExpression}. + */ +public abstract class JExpressionImpl implements JExpression +{ + // + // + // from JOp + // + // + public final JExpression minus() { + return JOp.minus(this); + } + + /** + * Logical not '!x'. + */ + public final JExpression not() { + return JOp.not(this); + } + + public final JExpression complement() { + return JOp.complement(this); + } + + public final JExpression incr() { + return JOp.incr(this); + } + + public final JExpression decr() { + return JOp.decr(this); + } + + public final JExpression plus(JExpression right) { + return JOp.plus(this, right); + } + + public final JExpression minus(JExpression right) { + return JOp.minus(this, right); + } + + public final JExpression mul(JExpression right) { + return JOp.mul(this, right); + } + + public final JExpression div(JExpression right) { + return JOp.div(this, right); + } + + public final JExpression mod(JExpression right) { + return JOp.mod(this, right); + } + + public final JExpression shl(JExpression right) { + return JOp.shl(this, right); + } + + public final JExpression shr(JExpression right) { + return JOp.shr(this, right); + } + + public final JExpression shrz(JExpression right) { + return JOp.shrz(this, right); + } + + public final JExpression band(JExpression right) { + return JOp.band(this, right); + } + + public final JExpression bor(JExpression right) { + return JOp.bor(this, right); + } + + public final JExpression cand(JExpression right) { + return JOp.cand(this, right); + } + + public final JExpression cor(JExpression right) { + return JOp.cor(this, right); + } + + public final JExpression xor(JExpression right) { + return JOp.xor(this, right); + } + + public final JExpression lt(JExpression right) { + return JOp.lt(this, right); + } + + public final JExpression lte(JExpression right) { + return JOp.lte(this, right); + } + + public final JExpression gt(JExpression right) { + return JOp.gt(this, right); + } + + public final JExpression gte(JExpression right) { + return JOp.gte(this, right); + } + + public final JExpression eq(JExpression right) { + return JOp.eq(this, right); + } + + public final JExpression ne(JExpression right) { + return JOp.ne(this, right); + } + + public final JExpression _instanceof(JType right) { + return JOp._instanceof(this, right); + } + + // + // + // from JExpr + // + // + public final JInvocation invoke(JMethod method) { + return JExpr.invoke(this, method); + } + + public final JInvocation invoke(String method) { + return JExpr.invoke(this, method); + } + + public final JFieldRef ref(JVar field) { + return JExpr.ref(this, field); + } + + public final JFieldRef ref(String field) { + return JExpr.ref(this, field); + } + + public final JArrayCompRef component(JExpression index) { + return JExpr.component(this, index); + } +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JFieldRef.java b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JFieldRef.java new file mode 100644 index 00000000000..589dc716366 --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JFieldRef.java @@ -0,0 +1,119 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.codemodel.internal; + + +/** + * Field Reference + */ + +public class JFieldRef extends JExpressionImpl implements JAssignmentTarget { + /** + * Object expression upon which this field will be accessed, or + * null for the implicit 'this'. + */ + private JGenerable object; + + /** + * Name of the field to be accessed. Either this or {@link #var} is set. + */ + private String name; + + /** + * Variable to be accessed. + */ + private JVar var; + + /** + * Indicates if an explicit this should be generated + */ + private boolean explicitThis; + + /** + * Field reference constructor given an object expression and field name + * + * @param object + * JExpression for the object upon which + * the named field will be accessed, + * + * @param name + * Name of field to access + */ + JFieldRef(JExpression object, String name) { + this(object, name, false); + } + + JFieldRef(JExpression object, JVar v) { + this(object, v, false); + } + + /** + * Static field reference. + */ + JFieldRef(JType type, String name) { + this(type, name, false); + } + + JFieldRef(JType type, JVar v) { + this(type, v, false); + } + + JFieldRef(JGenerable object, String name, boolean explicitThis) { + this.explicitThis = explicitThis; + this.object = object; + if (name.indexOf('.') >= 0) + throw new IllegalArgumentException("Field name contains '.': " + name); + this.name = name; + } + + JFieldRef(JGenerable object, JVar var, boolean explicitThis) { + this.explicitThis = explicitThis; + this.object = object; + this.var = var; + } + + public void generate(JFormatter f) { + String name = this.name; + if(name==null) name=var.name(); + + if (object != null) { + f.g(object).p('.').p(name); + } else { + if (explicitThis) { + f.p("this.").p(name); + } else { + f.id(name); + } + } + } + + public JExpression assign(JExpression rhs) { + return JExpr.assign(this, rhs); + } + public JExpression assignPlus(JExpression rhs) { + return JExpr.assignPlus(this, rhs); + } +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JFieldVar.java b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JFieldVar.java new file mode 100644 index 00000000000..59c4a8e3093 --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JFieldVar.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.codemodel.internal; + + + + +/** + * A field that can have a {@link JDocComment} associated with it + */ +public class JFieldVar extends JVar implements JDocCommentable { + + /** + * javadoc comments for this JFieldVar + */ + private JDocComment jdoc = null; + + private final JDefinedClass owner; + + + /** + * JFieldVar constructor + * + * @param type + * Datatype of this variable + * + * @param name + * Name of this variable + * + * @param init + * Value to initialize this variable to + */ + JFieldVar(JDefinedClass owner, JMods mods, JType type, String name, JExpression init) { + super( mods, type, name, init ); + this.owner = owner; + } + + @Override + public void name(String name) { + // make sure that the new name is available + if(owner.fields.containsKey(name)) + throw new IllegalArgumentException("name "+name+" is already in use"); + String oldName = name(); + super.name(name); + owner.fields.remove(oldName); + owner.fields.put(name,this); + } + + /** + * Creates, if necessary, and returns the class javadoc for this + * JDefinedClass + * + * @return JDocComment containing javadocs for this class + */ + public JDocComment javadoc() { + if( jdoc == null ) + jdoc = new JDocComment(owner.owner()); + return jdoc; + } + + public void declare(JFormatter f) { + if( jdoc != null ) + f.g( jdoc ); + super.declare( f ); + } + + +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JForEach.java b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JForEach.java new file mode 100644 index 00000000000..e926f16ed00 --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JForEach.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.codemodel.internal; + +/** + * ForEach Statement + * This will generate the code for statement based on the new + * j2se 1.5 j.l.s. + * + * @author Bhakti + */ +public final class JForEach implements JStatement { + + private final JType type; + private final String var; + private JBlock body = null; // lazily created + private final JExpression collection; + private final JVar loopVar; + + public JForEach(JType vartype, String variable, JExpression collection) { + + this.type = vartype; + this.var = variable; + this.collection = collection; + loopVar = new JVar(JMods.forVar(JMod.NONE), type, var, collection); + } + + + /** + * Returns a reference to the loop variable. + */ + public JVar var() { + return loopVar; + } + + public JBlock body() { + if (body == null) + body = new JBlock(); + return body; + } + + public void state(JFormatter f) { + f.p("for ("); + f.g(type).id(var).p(": ").g(collection); + f.p(')'); + if (body != null) + f.g(body).nl(); + else + f.p(';').nl(); + } + +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JForLoop.java b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JForLoop.java new file mode 100644 index 00000000000..f6b12301e25 --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JForLoop.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.codemodel.internal; + +import java.util.ArrayList; +import java.util.List; + + +/** + * For statement + */ + +public class JForLoop implements JStatement { + + private List inits = new ArrayList(); + private JExpression test = null; + private List updates = new ArrayList(); + private JBlock body = null; + + public JVar init(int mods, JType type, String var, JExpression e) { + JVar v = new JVar(JMods.forVar(mods), type, var, e); + inits.add(v); + return v; + } + + public JVar init(JType type, String var, JExpression e) { + return init(JMod.NONE, type, var, e); + } + + public void init(JVar v, JExpression e) { + inits.add(JExpr.assign(v, e)); + } + + public void test(JExpression e) { + this.test = e; + } + + public void update(JExpression e) { + updates.add(e); + } + + public JBlock body() { + if (body == null) body = new JBlock(); + return body; + } + + public void state(JFormatter f) { + f.p("for ("); + boolean first = true; + for (Object o : inits) { + if (!first) f.p(','); + if (o instanceof JVar) + f.b((JVar) o); + else + f.g((JExpression) o); + first = false; + } + f.p(';').g(test).p(';').g(updates).p(')'); + if (body != null) + f.g(body).nl(); + else + f.p(';').nl(); + } + +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JFormatter.java b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JFormatter.java new file mode 100644 index 00000000000..2d8d071bc5e --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JFormatter.java @@ -0,0 +1,555 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.codemodel.internal; + +import java.io.PrintWriter; +import java.io.Writer; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; + + +/** + * This is a utility class for managing indentation and other basic + * formatting for PrintWriter. + */ +public final class JFormatter { + /** all classes and ids encountered during the collection mode **/ + /** map from short type name to ReferenceList (list of JClass and ids sharing that name) **/ + private HashMap collectedReferences; + + /** set of imported types (including package java types, eventhough we won't generate imports for them) */ + private HashSet importedClasses; + + private static enum Mode { + /** + * Collect all the type names and identifiers. + * In this mode we don't actually generate anything. + */ + COLLECTING, + /** + * Print the actual source code. + */ + PRINTING + } + + /** + * The current running mode. + * Set to PRINTING so that a casual client can use a formatter just like before. + */ + private Mode mode = Mode.PRINTING; + + /** + * Current number of indentation strings to print + */ + private int indentLevel; + + /** + * String to be used for each indentation. + * Defaults to four spaces. + */ + private final String indentSpace; + + /** + * Stream associated with this JFormatter + */ + private final PrintWriter pw; + + /** + * Creates a JFormatter. + * + * @param s + * PrintWriter to JFormatter to use. + * + * @param space + * Incremental indentation string, similar to tab value. + */ + public JFormatter(PrintWriter s, String space) { + pw = s; + indentSpace = space; + collectedReferences = new HashMap(); + //ids = new HashSet(); + importedClasses = new HashSet(); + } + + /** + * Creates a formatter with default incremental indentations of + * four spaces. + */ + public JFormatter(PrintWriter s) { + this(s, " "); + } + + /** + * Creates a formatter with default incremental indentations of + * four spaces. + */ + public JFormatter(Writer w) { + this(new PrintWriter(w)); + } + + /** + * Closes this formatter. + */ + public void close() { + pw.close(); + } + + /** + * Returns true if we are in the printing mode, + * where we actually produce text. + * + * The other mode is the "collecting mode' + */ + public boolean isPrinting() { + return mode == Mode.PRINTING; + } + + /** + * Decrement the indentation level. + */ + public JFormatter o() { + indentLevel--; + return this; + } + + /** + * Increment the indentation level. + */ + public JFormatter i() { + indentLevel++; + return this; + } + + private boolean needSpace(char c1, char c2) { + if ((c1 == ']') && (c2 == '{')) return true; + if (c1 == ';') return true; + if (c1 == CLOSE_TYPE_ARGS) { + // e.g., "public Foo test;" + if(c2=='(') // but not "new Foo()" + return false; + return true; + } + if ((c1 == ')') && (c2 == '{')) return true; + if ((c1 == ',') || (c1 == '=')) return true; + if (c2 == '=') return true; + if (Character.isDigit(c1)) { + if ((c2 == '(') || (c2 == ')') || (c2 == ';') || (c2 == ',')) + return false; + return true; + } + if (Character.isJavaIdentifierPart(c1)) { + switch (c2) { + case '{': + case '}': + case '+': + case '>': + case '@': + return true; + default: + return Character.isJavaIdentifierStart(c2); + } + } + if (Character.isJavaIdentifierStart(c2)) { + switch (c1) { + case ']': + case ')': + case '}': + case '+': + return true; + default: + return false; + } + } + if (Character.isDigit(c2)) { + if (c1 == '(') return false; + return true; + } + return false; + } + + private char lastChar = 0; + private boolean atBeginningOfLine = true; + + private void spaceIfNeeded(char c) { + if (atBeginningOfLine) { + for (int i = 0; i < indentLevel; i++) + pw.print(indentSpace); + atBeginningOfLine = false; + } else if ((lastChar != 0) && needSpace(lastChar, c)) + pw.print(' '); + } + + /** + * Print a char into the stream + * + * @param c the char + */ + public JFormatter p(char c) { + if(mode==Mode.PRINTING) { + if(c==CLOSE_TYPE_ARGS) { + pw.print('>'); + } else { + spaceIfNeeded(c); + pw.print(c); + } + lastChar = c; + } + return this; + } + + /** + * Print a String into the stream + * + * @param s the String + */ + public JFormatter p(String s) { + if(mode==Mode.PRINTING) { + spaceIfNeeded(s.charAt(0)); + pw.print(s); + lastChar = s.charAt(s.length() - 1); + } + return this; + } + + public JFormatter t(JType type) { + if(type.isReference()) { + return t((JClass)type); + } else { + return g(type); + } + } + + /** + * Print a type name. + * + *

+ * In the collecting mode we use this information to + * decide what types to import and what not to. + */ + public JFormatter t(JClass type) { + switch(mode) { + case PRINTING: + // many of the JTypes in this list are either primitive or belong to package java + // so we don't need a FQCN + if(importedClasses.contains(type)) { + p(type.name()); // FQCN imported or not necessary, so generate short name + } else { + if(type.outer()!=null) + t(type.outer()).p('.').p(type.name()); + else + p(type.fullName()); // collision was detected, so generate FQCN + } + break; + case COLLECTING: + final String shortName = type.name(); + if(collectedReferences.containsKey(shortName)) { + collectedReferences.get(shortName).add(type); + } else { + ReferenceList tl = new ReferenceList(); + tl.add(type); + collectedReferences.put(shortName, tl); + } + break; + } + return this; + } + + /** + * Print an identifier + */ + public JFormatter id(String id) { + switch(mode) { + case PRINTING: + p(id); + break; + case COLLECTING: + // see if there is a type name that collides with this id + if(collectedReferences.containsKey(id)) { + if( !collectedReferences.get(id).getClasses().isEmpty() ) { + for( JClass type : collectedReferences.get(id).getClasses() ) { + if (type.outer()!=null) { + collectedReferences.get(id).setId(false); + return this; + } + } + } + collectedReferences.get(id).setId(true); + } else { + // not a type, but we need to create a place holder to + // see if there might be a collision with a type + ReferenceList tl = new ReferenceList(); + tl.setId(true); + collectedReferences.put(id, tl); + } + break; + } + return this; + } + + /** + * Print a new line into the stream + */ + public JFormatter nl() { + if(mode==Mode.PRINTING) { + pw.println(); + lastChar = 0; + atBeginningOfLine = true; + } + return this; + } + + /** + * Cause the JGenerable object to generate source for iteself + * + * @param g the JGenerable object + */ + public JFormatter g(JGenerable g) { + g.generate(this); + return this; + } + + /** + * Produces {@link JGenerable}s separated by ',' + */ + public JFormatter g(Collection list) { + boolean first = true; + if(!list.isEmpty()) { + for (JGenerable item : list) { + if (!first) + p(','); + g(item); + first = false; + } + } + return this; + } + + /** + * Cause the JDeclaration to generate source for itself + * + * @param d the JDeclaration object + */ + public JFormatter d(JDeclaration d) { + d.declare(this); + return this; + } + + /** + * Cause the JStatement to generate source for itself + * + * @param s the JStatement object + */ + public JFormatter s(JStatement s) { + s.state(this); + return this; + } + + /** + * Cause the JVar to generate source for itself + * + * @param v the JVar object + */ + public JFormatter b(JVar v) { + v.bind(this); + return this; + } + + /** + * Generates the whole source code out of the specified class. + */ + void write(JDefinedClass c) { + // first collect all the types and identifiers + mode = Mode.COLLECTING; + d(c); + + javaLang = c.owner()._package("java.lang"); + + // collate type names and identifiers to determine which types can be imported + for( ReferenceList tl : collectedReferences.values() ) { + if(!tl.collisions(c) && !tl.isId()) { + assert tl.getClasses().size() == 1; + + // add to list of collected types + importedClasses.add(tl.getClasses().get(0)); + } + } + + // the class itself that we will be generating is always accessible + importedClasses.add(c); + + // then print the declaration + mode = Mode.PRINTING; + + assert c.parentContainer().isPackage() : "this method is only for a pacakge-level class"; + JPackage pkg = (JPackage) c.parentContainer(); + if (!pkg.isUnnamed()) { + nl().d(pkg); + nl(); + } + + // generate import statements + JClass[] imports = importedClasses.toArray(new JClass[importedClasses.size()]); + Arrays.sort(imports); + for (JClass clazz : imports) { + // suppress import statements for primitive types, built-in types, + // types in the root package, and types in + // the same package as the current type + if(!supressImport(clazz, c)) { + if (clazz instanceof JNarrowedClass) { + clazz = clazz.erasure(); + } + + p("import").p(clazz.fullName()).p(';').nl(); + } + } + nl(); + + d(c); + } + + /** + * determine if an import statement should be supressed + * + * @param clazz JType that may or may not have an import + * @param c JType that is the current class being processed + * @return true if an import statement should be suppressed, false otherwise + */ + private boolean supressImport(JClass clazz, JClass c) { + if (clazz instanceof JNarrowedClass) { + clazz = clazz.erasure(); + } + if (clazz instanceof JAnonymousClass) { + clazz = clazz._extends(); + } + + if(clazz._package().isUnnamed()) + return true; + + final String packageName = clazz._package().name(); + if(packageName.equals("java.lang")) + return true; // no need to explicitly import java.lang classes + + if (clazz._package() == c._package()){ + // inner classes require an import stmt. + // All other pkg local classes do not need an + // import stmt for ref. + if(clazz.outer()==null) { + return true; // no need to explicitly import a class into itself + } + } + return false; + } + + private JPackage javaLang; + + + + /** + * Special character token we use to differenciate '>' as an operator and + * '>' as the end of the type arguments. The former uses '>' and it requires + * a preceding whitespace. The latter uses this, and it does not have a preceding + * whitespace. + */ + /*package*/ static final char CLOSE_TYPE_ARGS = '\uFFFF'; + + /** + * Used during the optimization of class imports. + * + * List of {@link JClass}es whose short name is the same. + * + * @author Ryan.Shoemaker@Sun.COM + */ + final class ReferenceList { + private final ArrayList classes = new ArrayList(); + + /** true if this name is used as an identifier (like a variable name.) **/ + private boolean id; + + /** + * Returns true if the symbol represented by the short name + * is "importable". + */ + public boolean collisions(JDefinedClass enclosingClass) { + // special case where a generated type collides with a type in package java + + // more than one type with the same name + if(classes.size() > 1) + return true; + + // an id and (at least one) type with the same name + if(id && classes.size() != 0) + return true; + + for(JClass c : classes) { + if (c instanceof JAnonymousClass) { + c = c._extends(); + } + if(c._package()==javaLang) { + // make sure that there's no other class with this name within the same package + Iterator itr = enclosingClass._package().classes(); + while(itr.hasNext()) { + // even if this is the only "String" class we use, + // if the class called "String" is in the same package, + // we still need to import it. + JDefinedClass n = itr.next(); + if(n.name().equals(c.name())) + return true; //collision + } + } + if(c.outer()!=null) + return true; // avoid importing inner class to work around 6431987. Also see jaxb issue 166 + } + + return false; + } + + public void add(JClass clazz) { + if(!classes.contains(clazz)) + classes.add(clazz); + } + + public List getClasses() { + return classes; + } + + public void setId(boolean value) { + id = value; + } + + /** + * Return true iff this is strictly an id, meaning that there + * are no collisions with type names. + */ + public boolean isId() { + return id && classes.size() == 0; + } + } +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JGenerable.java b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JGenerable.java new file mode 100644 index 00000000000..90cd19160f0 --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JGenerable.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.codemodel.internal; + + +/** + * Common interface for code components that can generate + * uses of themselves. + */ + +public interface JGenerable { + + public void generate(JFormatter f); + +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JGenerifiable.java b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JGenerifiable.java new file mode 100644 index 00000000000..73ce03cc3a8 --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JGenerifiable.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.codemodel.internal; + +/** + * Declarations that can have type variables. + * + * Something that can be made into a generic. + * + * @author + * Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com) + */ +public interface JGenerifiable { + /** + * Adds a new type variable to this declaration. + */ + JTypeVar generify( String name ); + + /** + * Adds a new type variable to this declaration with a bound. + */ + JTypeVar generify( String name, Class bound ); + + /** + * Adds a new type variable to this declaration with a bound. + */ + JTypeVar generify( String name, JClass bound ); + + /** + * Iterates all the type parameters of this class/interface. + */ + JTypeVar[] typeParams(); +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JGenerifiableImpl.java b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JGenerifiableImpl.java new file mode 100644 index 00000000000..a4e16e686fd --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JGenerifiableImpl.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.codemodel.internal; + +import java.util.ArrayList; +import java.util.List; + +/** + * Implementation of {@link JGenerifiable}. + * + * @author + * Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com) + */ +abstract class JGenerifiableImpl implements JGenerifiable, JDeclaration { + + /** Lazily created list of {@link JTypeVar}s. */ + private List typeVariables = null; + + protected abstract JCodeModel owner(); + + public void declare( JFormatter f ) { + if(typeVariables!=null) { + f.p('<'); + for (int i = 0; i < typeVariables.size(); i++) { + if(i!=0) f.p(','); + f.d(typeVariables.get(i)); + } + f.p('>'); + } + } + + + public JTypeVar generify(String name) { + JTypeVar v = new JTypeVar(owner(),name); + if(typeVariables==null) + typeVariables = new ArrayList(3); + typeVariables.add(v); + return v; + } + + public JTypeVar generify(String name, Class bound) { + return generify(name,owner().ref(bound)); + } + + public JTypeVar generify(String name, JClass bound) { + return generify(name).bound(bound); + } + + public JTypeVar[] typeParams() { + if(typeVariables==null) + return JTypeVar.EMPTY_ARRAY; + else + return typeVariables.toArray(new JTypeVar[typeVariables.size()]); + } + +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JInvocation.java b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JInvocation.java new file mode 100644 index 00000000000..1cab16ff259 --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JInvocation.java @@ -0,0 +1,186 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.codemodel.internal; + +import java.util.ArrayList; +import java.util.List; + + +/** + * JMethod invocation + */ +public final class JInvocation extends JExpressionImpl implements JStatement { + + /** + * Object expression upon which this method will be invoked, or null if + * this is a constructor invocation + */ + private JGenerable object; + + /** + * Name of the method to be invoked. + * Either this field is set, or {@link #method}, or {@link #type} (in which case it's a + * constructor invocation.) + * This allows {@link JMethod#name(String) the name of the method to be changed later}. + */ + private String name; + + private JMethod method; + + private boolean isConstructor = false; + + /** + * List of argument expressions for this method invocation + */ + private List args = new ArrayList(); + + /** + * If isConstructor==true, this field keeps the type to be created. + */ + private JType type = null; + + /** + * Invokes a method on an object. + * + * @param object + * JExpression for the object upon which + * the named method will be invoked, + * or null if none + * + * @param name + * Name of method to invoke + */ + JInvocation(JExpression object, String name) { + this( (JGenerable)object, name ); + } + + JInvocation(JExpression object, JMethod method) { + this( (JGenerable)object, method ); + } + + /** + * Invokes a static method on a class. + */ + JInvocation(JClass type, String name) { + this( (JGenerable)type, name ); + } + + JInvocation(JClass type, JMethod method) { + this( (JGenerable)type, method ); + } + + private JInvocation(JGenerable object, String name) { + this.object = object; + if (name.indexOf('.') >= 0) + throw new IllegalArgumentException("method name contains '.': " + name); + this.name = name; + } + + private JInvocation(JGenerable object, JMethod method) { + this.object = object; + this.method =method; + } + + /** + * Invokes a constructor of an object (i.e., creates + * a new object.) + * + * @param c + * Type of the object to be created. If this type is + * an array type, added arguments are treated as array + * initializer. Thus you can create an expression like + * new int[]{1,2,3,4,5}. + */ + JInvocation(JType c) { + this.isConstructor = true; + this.type = c; + } + + /** + * Add an expression to this invocation's argument list + * + * @param arg + * Argument to add to argument list + */ + public JInvocation arg(JExpression arg) { + if(arg==null) throw new IllegalArgumentException(); + args.add(arg); + return this; + } + + /** + * Adds a literal argument. + * + * Short for {@code arg(JExpr.lit(v))} + */ + public JInvocation arg(String v) { + return arg(JExpr.lit(v)); + } + + /** + * Returns all arguments of the invocation. + * @return + * If there's no arguments, an empty array will be returned. + */ + public JExpression[] listArgs() { + return args.toArray(new JExpression[args.size()]); + } + + public void generate(JFormatter f) { + if (isConstructor && type.isArray()) { + // [RESULT] new T[]{arg1,arg2,arg3,...}; + f.p("new").g(type).p('{'); + } else { + if (isConstructor) + f.p("new").g(type).p('('); + else { + String name = this.name; + if(name==null) name=this.method.name(); + + if (object != null) + f.g(object).p('.').p(name).p('('); + else + f.id(name).p('('); + } + } + + f.g(args); + + if (isConstructor && type.isArray()) + f.p('}'); + else + f.p(')'); + + if( type instanceof JDefinedClass && ((JDefinedClass)type).isAnonymous() ) { + ((JAnonymousClass)type).declareBody(f); + } + } + + public void state(JFormatter f) { + f.g(this).p(';').nl(); + } + +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JJavaName.java b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JJavaName.java new file mode 100644 index 00000000000..67e8fbc4068 --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JJavaName.java @@ -0,0 +1,252 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.codemodel.internal; + +import java.util.HashSet; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Utility methods that convert arbitrary strings into Java identifiers. + */ +public class JJavaName { + + + /** + * Checks if a given string is usable as a Java identifier. + */ + public static boolean isJavaIdentifier(String s) { + if(s.length()==0) return false; + if( reservedKeywords.contains(s) ) return false; + + if(!Character.isJavaIdentifierStart(s.charAt(0))) return false; + + for (int i = 1; i < s.length(); i++) + if (!Character.isJavaIdentifierPart(s.charAt(i))) + return false; + + return true; + } + + /** + * Checks if the given string is a valid fully qualified name. + */ + public static boolean isFullyQualifiedClassName(String s) { + return isJavaPackageName(s); + } + + /** + * Checks if the given string is a valid Java package name. + */ + public static boolean isJavaPackageName(String s) { + while(s.length()!=0) { + int idx = s.indexOf('.'); + if(idx==-1) idx=s.length(); + if( !isJavaIdentifier(s.substring(0,idx)) ) + return false; + + s = s.substring(idx); + if(s.length()!=0) s = s.substring(1); // remove '.' + } + return true; + } + + /** + * Experimental API: converts an English word into a plural form. + * + * @param word + * a word, such as "child", "apple". Must not be null. + * It accepts word concatanation forms + * that are common in programming languages, such as "my_child", "MyChild", + * "myChild", "MY-CHILD", "CODE003-child", etc, and mostly tries to do the right thing. + * ("my_children","MyChildren","myChildren", and "MY-CHILDREN", "CODE003-children" respectively) + *

+ * Although this method only works for English words, it handles non-English + * words gracefully (by just returning it as-is.) For example, 日本語 + * will be returned as-is without modified, not "日本語s" + *

+ * This method doesn't handle suffixes very well. For example, passing + * "person56" will return "person56s", not "people56". + * + * @return + * always non-null. + */ + public static String getPluralForm(String word) { + // remember the casing of the word + boolean allUpper = true; + + // check if the word looks like an English word. + // if we see non-ASCII characters, abort + for(int i=0; i=0x80) + return word; + + // note that this isn't the same as allUpper &= Character.isUpperCase(ch); + allUpper &= !Character.isLowerCase(ch); + } + + for (Entry e : TABLE) { + String r = e.apply(word); + if(r!=null) { + if(allUpper) r=r.toUpperCase(); + return r; + } + } + + // failed + return word; + } + + + /** All reserved keywords of Java. */ + private static HashSet reservedKeywords = new HashSet(); + + static { + // see http://java.sun.com/docs/books/tutorial/java/nutsandbolts/_keywords.html + String[] words = new String[]{ + "abstract", + "boolean", + "break", + "byte", + "case", + "catch", + "char", + "class", + "const", + "continue", + "default", + "do", + "double", + "else", + "extends", + "final", + "finally", + "float", + "for", + "goto", + "if", + "implements", + "import", + "instanceof", + "int", + "interface", + "long", + "native", + "new", + "package", + "private", + "protected", + "public", + "return", + "short", + "static", + "strictfp", + "super", + "switch", + "synchronized", + "this", + "throw", + "throws", + "transient", + "try", + "void", + "volatile", + "while", + + // technically these are not reserved words but they cannot be used as identifiers. + "true", + "false", + "null", + + // and I believe assert is also a new keyword + "assert", + + // and 5.0 keywords + "enum" + }; + for (String w : words) + reservedKeywords.add(w); + } + + + private static class Entry { + private final Pattern pattern; + private final String replacement; + + public Entry(String pattern, String replacement) { + this.pattern = Pattern.compile(pattern,Pattern.CASE_INSENSITIVE); + this.replacement = replacement; + } + + String apply(String word) { + Matcher m = pattern.matcher(word); + if(m.matches()) { + StringBuffer buf = new StringBuffer(); + m.appendReplacement(buf,replacement); + return buf.toString(); + } else { + return null; + } + } + } + + private static final Entry[] TABLE; + + static { + String[] source = { + "(.*)child","$1children", + "(.+)fe","$1ves", + "(.*)mouse","$1mise", + "(.+)f","$1ves", + "(.+)ch","$1ches", + "(.+)sh","$1shes", + "(.*)tooth","$1teeth", + "(.+)um","$1a", + "(.+)an","$1en", + "(.+)ato","$1atoes", + "(.*)basis","$1bases", + "(.*)axis","$1axes", + "(.+)is","$1ises", + "(.+)ss","$1sses", + "(.+)us","$1uses", + "(.+)s","$1s", + "(.*)foot","$1feet", + "(.+)ix","$1ixes", + "(.+)ex","$1ices", + "(.+)nx","$1nxes", + "(.+)x","$1xes", + "(.+)y","$1ies", + "(.+)","$1s", + }; + + TABLE = new Entry[source.length/2]; + + for( int i=0; i params = new ArrayList(); + + /** + * Set of exceptions that this method may throw. + * A set instance lazily created. + */ + private Set _throws; + + /** + * JBlock of statements that makes up the body this method + */ + private JBlock body = null; + + private JDefinedClass outer; + + /** + * javadoc comments for this JMethod + */ + private JDocComment jdoc = null; + + /** + * Variable parameter for this method's varargs declaration + * introduced in J2SE 1.5 + */ + private JVar varParam = null; + + /** + * Annotations on this variable. Lazily created. + */ + private List annotations = null; + + + private boolean isConstructor() { + return type == null; + } + + /** To set the default value for the + * annotation member + */ + private JExpression defaultValue = null; + + + /** + * JMethod constructor + * + * @param mods + * Modifiers for this method's declaration + * + * @param type + * Return type for the method + * + * @param name + * Name of this method + */ + JMethod(JDefinedClass outer, int mods, JType type, String name) { + this.mods = JMods.forMethod(mods); + this.type = type; + this.name = name; + this.outer = outer; + } + + /** + * Constructor constructor + * + * @param mods + * Modifiers for this constructor's declaration + * + * @param _class + * JClass containing this constructor + */ + JMethod(int mods, JDefinedClass _class) { + this.mods = JMods.forMethod(mods); + this.type = null; + this.name = _class.name(); + this.outer = _class; + } + + private Set getThrows() { + if(_throws==null) + _throws = new TreeSet(ClassNameComparator.theInstance); + return _throws; + } + + /** + * Add an exception to the list of exceptions that this + * method may throw. + * + * @param exception + * Name of an exception that this method may throw + */ + public JMethod _throws(JClass exception) { + getThrows().add(exception); + return this; + } + + public JMethod _throws(Class exception) { + return _throws(outer.owner().ref(exception)); + } + + /** + * Returns the list of variable of this method. + * + * @return List of parameters of this method. This list is not modifiable. + */ + public List params() { + return Collections.unmodifiableList(params); + } + + /** + * Add the specified variable to the list of parameters + * for this method signature. + * + * @param type + * JType of the parameter being added + * + * @param name + * Name of the parameter being added + * + * @return New parameter variable + */ + public JVar param(int mods, JType type, String name) { + JVar v = new JVar(JMods.forVar(mods), type, name, null); + params.add(v); + return v; + } + + public JVar param(JType type, String name) { + return param(JMod.NONE, type, name); + } + + public JVar param(int mods, Class type, String name) { + return param(mods, outer.owner()._ref(type), name); + } + + public JVar param(Class type, String name) { + return param(outer.owner()._ref(type), name); + } + + /** + * @see #varParam(JType, String) + */ + public JVar varParam(Class type, String name) { + return varParam(outer.owner()._ref(type),name); + } + + /** + * Add the specified variable argument to the list of parameters + * for this method signature. + * + * @param type + * Type of the parameter being added. + * + * @param name + * Name of the parameter being added + * + * @return the variable parameter + * + * @throws IllegalStateException + * If this method is called twice. + * varargs in J2SE 1.5 can appear only once in the + * method signature. + */ + public JVar varParam(JType type, String name) { + if (!hasVarArgs()) { + + varParam = + new JVar( + JMods.forVar(JMod.NONE), + type.array(), + name, + null); + return varParam; + } else { + throw new IllegalStateException( + "Cannot have two varargs in a method,\n" + + "Check if varParam method of JMethod is" + + " invoked more than once"); + + } + + } + + /** + * Adds an annotation to this variable. + * @param clazz + * The annotation class to annotate the field with + */ + public JAnnotationUse annotate(JClass clazz){ + if(annotations==null) + annotations = new ArrayList(); + JAnnotationUse a = new JAnnotationUse(clazz); + annotations.add(a); + return a; + } + + /** + * Adds an annotation to this variable. + * + * @param clazz + * The annotation class to annotate the field with + */ + public JAnnotationUse annotate(Class clazz){ + return annotate(owner().ref(clazz)); + } + + public W annotate2(Class clazz) { + return TypedAnnotationWriter.create(clazz,this); + } + + public Collection annotations() { + if (annotations == null) + annotations = new ArrayList(); + return Collections.unmodifiableList(annotations); + } + + /** + * Check if there are any varargs declared + * for this method signature. + */ + public boolean hasVarArgs() { + return this.varParam!=null; + } + + public String name() { + return name; + } + + /** + * Changes the name of the method. + */ + public void name(String n) { + this.name = n; + } + + /** + * Returns the return type. + */ + public JType type() { + return type; + } + + /** + * Overrides the return type. + */ + public void type(JType t) { + this.type = t; + } + + /** + * Returns all the parameter types in an array. + * @return + * If there's no parameter, an empty array will be returned. + */ + public JType[] listParamTypes() { + JType[] r = new JType[params.size()]; + for (int i = 0; i < r.length; i++) + r[i] = params.get(i).type(); + return r; + } + + /** + * Returns the varags parameter type. + * @return + * If there's no vararg parameter type, null will be returned. + */ + public JType listVarParamType() { + if (varParam != null) + return varParam.type(); + else + return null; + } + + /** + * Returns all the parameters in an array. + * @return + * If there's no parameter, an empty array will be returned. + */ + public JVar[] listParams() { + return params.toArray(new JVar[params.size()]); + } + + /** + * Returns the variable parameter + * @return + * If there's no parameter, null will be returned. + */ + public JVar listVarParam() { + return varParam; + } + + /** + * Returns true if the method has the specified signature. + */ + public boolean hasSignature(JType[] argTypes) { + JVar[] p = listParams(); + if (p.length != argTypes.length) + return false; + + for (int i = 0; i < p.length; i++) + if (!p[i].type().equals(argTypes[i])) + return false; + + return true; + } + + /** + * Get the block that makes up body of this method + * + * @return Body of method + */ + public JBlock body() { + if (body == null) + body = new JBlock(); + return body; + } + + /** + * Specify the default value for this annotation member + * @param value + * Default value for the annotation member + * + */ + public void declareDefaultValue(JExpression value){ + this.defaultValue = value; + } + + /** + * Creates, if necessary, and returns the class javadoc for this + * JDefinedClass + * + * @return JDocComment containing javadocs for this class + */ + public JDocComment javadoc() { + if (jdoc == null) + jdoc = new JDocComment(owner()); + return jdoc; + } + + public void declare(JFormatter f) { + if (jdoc != null) + f.g(jdoc); + + if (annotations != null){ + for (JAnnotationUse a : annotations) + f.g(a).nl(); + } + + f.g(mods); + + // declare the generics parameters + super.declare(f); + + if (!isConstructor()) + f.g(type); + f.id(name).p('(').i(); + // when parameters are printed in new lines, we want them to be indented. + // there's a good chance no newlines happen, too, but just in case it does. + boolean first = true; + for (JVar var : params) { + if (!first) + f.p(','); + if(var.isAnnotated()) + f.nl(); + f.b(var); + first = false; + } + if (hasVarArgs()) { + if (!first) + f.p(','); + f.g(varParam.type().elementType()); + f.p("... "); + f.id(varParam.name()); + } + + f.o().p(')'); + if (_throws!=null && !_throws.isEmpty()) { + f.nl().i().p("throws").g(_throws).nl().o(); + } + + if (defaultValue != null) { + f.p("default "); + f.g(defaultValue); + } + if (body != null) { + f.s(body); + } else if ( + !outer.isInterface() && !outer.isAnnotationTypeDeclaration() && !mods.isAbstract() && !mods.isNative()) { + // Print an empty body for non-native, non-abstract methods + f.s(new JBlock()); + } else { + f.p(';').nl(); + } + } + + /** + * @return + * the current modifiers of this method. + * Always return non-null valid object. + */ + public JMods mods() { + return mods; + } + + /** + * @deprecated use {@link #mods()} + */ + public JMods getMods() { + return mods; + } + + protected JCodeModel owner() { + return outer.owner(); + } +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JMod.java b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JMod.java new file mode 100644 index 00000000000..3a4b5881371 --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JMod.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.codemodel.internal; + + +/** + * Modifier constants. + */ +public final class JMod { + public final static int NONE = 0x000; + public final static int PUBLIC = 0x001; + public final static int PROTECTED = 0x002; + public final static int PRIVATE = 0x004; + public final static int FINAL = 0x008; + public final static int STATIC = 0x010; + public final static int ABSTRACT = 0x020; + public final static int NATIVE = 0x040; + public final static int SYNCHRONIZED = 0x080; + public final static int TRANSIENT = 0x100; + public final static int VOLATILE = 0x200; +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JMods.java b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JMods.java new file mode 100644 index 00000000000..85b2ddbd25e --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JMods.java @@ -0,0 +1,158 @@ +/* + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.codemodel.internal; + +import java.io.PrintWriter; +import java.io.StringWriter; + +/** + * Modifier groups. + */ +public class JMods implements JGenerable { + +// +// mask +// + private static int VAR = JMod.FINAL; + private static int FIELD = (JMod.PUBLIC | JMod.PRIVATE | JMod.PROTECTED + | JMod.STATIC | JMod.FINAL + | JMod.TRANSIENT | JMod.VOLATILE); + private static int METHOD = (JMod.PUBLIC | JMod.PRIVATE | JMod.PROTECTED | JMod.FINAL + | JMod.ABSTRACT | JMod.STATIC | JMod.NATIVE | JMod.SYNCHRONIZED); + private static int CLASS = (JMod.PUBLIC | JMod.PRIVATE | JMod.PROTECTED + | JMod.STATIC | JMod.FINAL | JMod.ABSTRACT); + private static int INTERFACE = JMod.PUBLIC; + /** bit-packed representation of modifiers. */ + private int mods; + + private JMods(int mods) { + this.mods = mods; + } + + /** + * Gets the bit-packed representaion of modifiers. + */ + public int getValue() { + return mods; + } + + private static void check(int mods, int legal, String what) { + if ((mods & ~legal) != 0) { + throw new IllegalArgumentException("Illegal modifiers for " + + what + ": " + + new JMods(mods).toString()); + } + /* ## check for illegal combinations too */ + } + + static JMods forVar(int mods) { + check(mods, VAR, "variable"); + return new JMods(mods); + } + + static JMods forField(int mods) { + check(mods, FIELD, "field"); + return new JMods(mods); + } + + static JMods forMethod(int mods) { + check(mods, METHOD, "method"); + return new JMods(mods); + } + + static JMods forClass(int mods) { + check(mods, CLASS, "class"); + return new JMods(mods); + } + + static JMods forInterface(int mods) { + check(mods, INTERFACE, "class"); + return new JMods(mods); + } + + public boolean isAbstract() { + return (mods & JMod.ABSTRACT) != 0; + } + + public boolean isNative() { + return (mods & JMod.NATIVE) != 0; + } + + public boolean isSynchronized() { + return (mods & JMod.SYNCHRONIZED) != 0; + } + + public void setSynchronized(boolean newValue) { + setFlag(JMod.SYNCHRONIZED, newValue); + } + + public void setPrivate() { + setFlag(JMod.PUBLIC, false); + setFlag(JMod.PROTECTED, false); + setFlag(JMod.PRIVATE, true); + } + + public void setProtected() { + setFlag(JMod.PUBLIC, false); + setFlag(JMod.PROTECTED, true); + setFlag(JMod.PRIVATE, false); + } + + public void setPublic() { + setFlag(JMod.PUBLIC, true); + setFlag(JMod.PROTECTED, false); + setFlag(JMod.PRIVATE, false); + } + + public void setFinal(boolean newValue) { + setFlag(JMod.FINAL, newValue); + } + + private void setFlag(int bit, boolean newValue) { + mods = (mods & ~bit) | (newValue ? bit : 0); + } + + public void generate(JFormatter f) { + if ((mods & JMod.PUBLIC) != 0) f.p("public"); + if ((mods & JMod.PROTECTED) != 0) f.p("protected"); + if ((mods & JMod.PRIVATE) != 0) f.p("private"); + if ((mods & JMod.FINAL) != 0) f.p("final"); + if ((mods & JMod.STATIC) != 0) f.p("static"); + if ((mods & JMod.ABSTRACT) != 0) f.p("abstract"); + if ((mods & JMod.NATIVE) != 0) f.p("native"); + if ((mods & JMod.SYNCHRONIZED) != 0) f.p("synchronized"); + if ((mods & JMod.TRANSIENT) != 0) f.p("transient"); + if ((mods & JMod.VOLATILE) != 0) f.p("volatile"); + } + + @Override + public String toString() { + StringWriter s = new StringWriter(); + JFormatter f = new JFormatter(new PrintWriter(s)); + this.generate(f); + return s.toString(); + } +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JNarrowedClass.java b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JNarrowedClass.java new file mode 100644 index 00000000000..532d38d25c6 --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JNarrowedClass.java @@ -0,0 +1,226 @@ +/* + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.codemodel.internal; + +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import java.util.Collections; +import java.util.ArrayList; + +/** + * Represents X<Y>. + * + * TODO: consider separating the decl and the use. + * + * @author + * Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com) + */ +class JNarrowedClass extends JClass { + /** + * A generic class with type parameters. + */ + final JClass basis; + /** + * Arguments to those parameters. + */ + private final List args; + + JNarrowedClass(JClass basis, JClass arg) { + this(basis,Collections.singletonList(arg)); + } + + JNarrowedClass(JClass basis, List args) { + super(basis.owner()); + this.basis = basis; + assert !(basis instanceof JNarrowedClass); + this.args = args; + } + + @Override + public JClass narrow( JClass clazz ) { + List newArgs = new ArrayList(args); + newArgs.add(clazz); + return new JNarrowedClass(basis,newArgs); + } + + @Override + public JClass narrow( JClass... clazz ) { + List newArgs = new ArrayList(args); + newArgs.addAll(Arrays.asList(clazz)); + return new JNarrowedClass(basis,newArgs); + } + + public String name() { + StringBuilder buf = new StringBuilder(); + buf.append(basis.name()); + buf.append('<'); + boolean first = true; + for (JClass c : args) { + if(first) + first = false; + else + buf.append(','); + buf.append(c.name()); + } + buf.append('>'); + return buf.toString(); + } + + public String fullName() { + StringBuilder buf = new StringBuilder(); + buf.append(basis.fullName()); + buf.append('<'); + boolean first = true; + for (JClass c : args) { + if(first) + first = false; + else + buf.append(','); + buf.append(c.fullName()); + } + buf.append('>'); + return buf.toString(); + } + + @Override + public String binaryName() { + StringBuilder buf = new StringBuilder(); + buf.append(basis.binaryName()); + buf.append('<'); + boolean first = true; + for (JClass c : args) { + if(first) + first = false; + else + buf.append(','); + buf.append(c.binaryName()); + } + buf.append('>'); + return buf.toString(); + } + + @Override + public void generate(JFormatter f) { + f.t(basis).p('<').g(args).p(JFormatter.CLOSE_TYPE_ARGS); + } + + @Override + void printLink(JFormatter f) { + basis.printLink(f); + f.p("{@code <}"); + boolean first = true; + for( JClass c : args ) { + if(first) + first = false; + else + f.p(','); + c.printLink(f); + } + f.p("{@code >}"); + } + + public JPackage _package() { + return basis._package(); + } + + public JClass _extends() { + JClass base = basis._extends(); + if(base==null) return base; + return base.substituteParams(basis.typeParams(),args); + } + + public Iterator _implements() { + return new Iterator() { + private final Iterator core = basis._implements(); + public void remove() { + core.remove(); + } + public JClass next() { + return core.next().substituteParams(basis.typeParams(),args); + } + public boolean hasNext() { + return core.hasNext(); + } + }; + } + + @Override + public JClass erasure() { + return basis; + } + + public boolean isInterface() { + return basis.isInterface(); + } + + public boolean isAbstract() { + return basis.isAbstract(); + } + + @Override + public boolean isArray() { + return false; + } + + + // + // Equality is based on value + // + + @Override + public boolean equals(Object obj) { + if(!(obj instanceof JNarrowedClass)) return false; + return fullName().equals(((JClass)obj).fullName()); + } + + @Override + public int hashCode() { + return fullName().hashCode(); + } + + protected JClass substituteParams(JTypeVar[] variables, List bindings) { + JClass b = basis.substituteParams(variables,bindings); + boolean different = b!=basis; + + List clazz = new ArrayList(args.size()); + for( int i=0; i getTypeParameters() { + return args; + } +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JNullType.java b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JNullType.java new file mode 100644 index 00000000000..836ba03ea74 --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JNullType.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.codemodel.internal; + +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +/** + * Special class object that represents the type of "null". + * + *

+ * Use this class with care. + * + * @author + * Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com) + */ +public final class JNullType extends JClass { + + JNullType(JCodeModel _owner) { + super(_owner); + } + + public String name() { return "null"; } + public String fullName() { return "null"; } + + public JPackage _package() { return owner()._package(""); } + + public JClass _extends() { return null; } + + public Iterator _implements() { + return Collections.emptyList().iterator(); + } + + public boolean isInterface() { return false; } + public boolean isAbstract() { return false; } + + protected JClass substituteParams(JTypeVar[] variables, List bindings) { + return this; + } +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JOp.java b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JOp.java new file mode 100644 index 00000000000..58c374ebfd4 --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JOp.java @@ -0,0 +1,254 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.codemodel.internal; + + +/** + * JClass for generating expressions containing operators + */ + +abstract public class JOp { + + private JOp() { + } + + + /** + * Determine whether the top level of an expression involves an + * operator. + */ + static boolean hasTopOp(JExpression e) { + return (e instanceof UnaryOp) || (e instanceof BinaryOp); + } + + /* -- Unary operators -- */ + + static private class UnaryOp extends JExpressionImpl { + + protected String op; + protected JExpression e; + protected boolean opFirst = true; + + UnaryOp(String op, JExpression e) { + this.op = op; + this.e = e; + } + + UnaryOp(JExpression e, String op) { + this.op = op; + this.e = e; + opFirst = false; + } + + public void generate(JFormatter f) { + if (opFirst) + f.p('(').p(op).g(e).p(')'); + else + f.p('(').g(e).p(op).p(')'); + } + + } + + public static JExpression minus(JExpression e) { + return new UnaryOp("-", e); + } + + /** + * Logical not '!x'. + */ + public static JExpression not(JExpression e) { + if (e == JExpr.TRUE) return JExpr.FALSE; + if (e == JExpr.FALSE) return JExpr.TRUE; + return new UnaryOp("!", e); + } + + public static JExpression complement(JExpression e) { + return new UnaryOp("~", e); + } + + static private class TightUnaryOp extends UnaryOp { + + TightUnaryOp(JExpression e, String op) { + super(e, op); + } + + public void generate(JFormatter f) { + if (opFirst) + f.p(op).g(e); + else + f.g(e).p(op); + } + + } + + public static JExpression incr(JExpression e) { + return new TightUnaryOp(e, "++"); + } + + public static JExpression decr(JExpression e) { + return new TightUnaryOp(e, "--"); + } + + + /* -- Binary operators -- */ + + static private class BinaryOp extends JExpressionImpl { + + String op; + JExpression left; + JGenerable right; + + BinaryOp(String op, JExpression left, JGenerable right) { + this.left = left; + this.op = op; + this.right = right; + } + + public void generate(JFormatter f) { + f.p('(').g(left).p(op).g(right).p(')'); + } + + } + + public static JExpression plus(JExpression left, JExpression right) { + return new BinaryOp("+", left, right); + } + + public static JExpression minus(JExpression left, JExpression right) { + return new BinaryOp("-", left, right); + } + + public static JExpression mul(JExpression left, JExpression right) { + return new BinaryOp("*", left, right); + } + + public static JExpression div(JExpression left, JExpression right) { + return new BinaryOp("/", left, right); + } + + public static JExpression mod(JExpression left, JExpression right) { + return new BinaryOp("%", left, right); + } + + public static JExpression shl(JExpression left, JExpression right) { + return new BinaryOp("<<", left, right); + } + + public static JExpression shr(JExpression left, JExpression right) { + return new BinaryOp(">>", left, right); + } + + public static JExpression shrz(JExpression left, JExpression right) { + return new BinaryOp(">>>", left, right); + } + + public static JExpression band(JExpression left, JExpression right) { + return new BinaryOp("&", left, right); + } + + public static JExpression bor(JExpression left, JExpression right) { + return new BinaryOp("|", left, right); + } + + public static JExpression cand(JExpression left, JExpression right) { + if (left == JExpr.TRUE) return right; + if (right == JExpr.TRUE) return left; + if (left == JExpr.FALSE) return left; // JExpr.FALSE + if (right == JExpr.FALSE) return right; // JExpr.FALSE + return new BinaryOp("&&", left, right); + } + + public static JExpression cor(JExpression left, JExpression right) { + if (left == JExpr.TRUE) return left; // JExpr.TRUE + if (right == JExpr.TRUE) return right; // JExpr.FALSE + if (left == JExpr.FALSE) return right; + if (right == JExpr.FALSE) return left; + return new BinaryOp("||", left, right); + } + + public static JExpression xor(JExpression left, JExpression right) { + return new BinaryOp("^", left, right); + } + + public static JExpression lt(JExpression left, JExpression right) { + return new BinaryOp("<", left, right); + } + + public static JExpression lte(JExpression left, JExpression right) { + return new BinaryOp("<=", left, right); + } + + public static JExpression gt(JExpression left, JExpression right) { + return new BinaryOp(">", left, right); + } + + public static JExpression gte(JExpression left, JExpression right) { + return new BinaryOp(">=", left, right); + } + + public static JExpression eq(JExpression left, JExpression right) { + return new BinaryOp("==", left, right); + } + + public static JExpression ne(JExpression left, JExpression right) { + return new BinaryOp("!=", left, right); + } + + public static JExpression _instanceof(JExpression left, JType right) { + return new BinaryOp("instanceof", left, right); + } + + /* -- Ternary operators -- */ + + static private class TernaryOp extends JExpressionImpl { + + String op1; + String op2; + JExpression e1; + JExpression e2; + JExpression e3; + + TernaryOp(String op1, String op2, + JExpression e1, JExpression e2, JExpression e3) { + this.e1 = e1; + this.op1 = op1; + this.e2 = e2; + this.op2 = op2; + this.e3 = e3; + } + + public void generate(JFormatter f) { + f.p('(').g(e1).p(op1).g(e2).p(op2).g(e3).p(')'); + } + + } + + public static JExpression cond(JExpression cond, + JExpression ifTrue, JExpression ifFalse) { + return new TernaryOp("?", ":", cond, ifTrue, ifFalse); + } + +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JPackage.java b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JPackage.java new file mode 100644 index 00000000000..488c8da1fbd --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JPackage.java @@ -0,0 +1,474 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.codemodel.internal; + +import java.io.BufferedOutputStream; +import java.io.BufferedWriter; +import java.io.File; +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.io.Writer; +import java.lang.annotation.Annotation; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; +import java.util.Collection; +import java.util.Collections; + + +/** + * A Java package. + */ +public final class JPackage implements JDeclaration, JGenerable, JClassContainer, JAnnotatable, Comparable, JDocCommentable { + + /** + * Name of the package. + * May be the empty string for the root package. + */ + private String name; + + private final JCodeModel owner; + + /** + * List of classes contained within this package keyed by their name. + */ + private final Map classes = new TreeMap(); + + /** + * List of resources files inside this package. + */ + private final Set resources = new HashSet(); + + /** + * All {@link JClass}s in this package keyed the upper case class name. + * + * This field is non-null only on Windows, to detect + * "Foo" and "foo" as a collision. + */ + private final Map upperCaseClassMap; + + /** + * Lazily created list of package annotations. + */ + private List annotations = null; + + /** + * package javadoc. + */ + private JDocComment jdoc = null; + + /** + * JPackage constructor + * + * @param name + * Name of package + * + * @param cw The code writer being used to create this package + * + * @throws IllegalArgumentException + * If each part of the package name is not a valid identifier + */ + JPackage(String name, JCodeModel cw) { + this.owner = cw; + if (name.equals(".")) { + String msg = "Package name . is not allowed"; + throw new IllegalArgumentException(msg); + } + + if(JCodeModel.isCaseSensitiveFileSystem) + upperCaseClassMap = null; + else + upperCaseClassMap = new HashMap(); + + this.name = name; + } + + + public JClassContainer parentContainer() { + return parent(); + } + + /** + * Gets the parent package, or null if this class is the root package. + */ + public JPackage parent() { + if(name.length()==0) return null; + + int idx = name.lastIndexOf('.'); + return owner._package(name.substring(0,idx)); + } + + public boolean isClass() { return false; } + public boolean isPackage() { return true; } + public JPackage getPackage() { return this; } + + /** + * Add a class to this package. + * + * @param mods + * Modifiers for this class declaration + * + * @param name + * Name of class to be added to this package + * + * @return Newly generated class + * + * @exception JClassAlreadyExistsException + * When the specified class/interface was already created. + */ + public JDefinedClass _class(int mods, String name) throws JClassAlreadyExistsException { + return _class(mods,name,ClassType.CLASS); + } + + /** + * {@inheritDoc} + * @deprecated + */ + public JDefinedClass _class( int mods, String name, boolean isInterface ) throws JClassAlreadyExistsException { + return _class(mods,name, isInterface?ClassType.INTERFACE:ClassType.CLASS ); + } + + public JDefinedClass _class( int mods, String name, ClassType classTypeVal ) throws JClassAlreadyExistsException { + if(classes.containsKey(name)) + throw new JClassAlreadyExistsException(classes.get(name)); + else { + // XXX problems caught in the NC constructor + JDefinedClass c = new JDefinedClass(this, mods, name, classTypeVal); + + if( upperCaseClassMap!=null ) { + JDefinedClass dc = upperCaseClassMap.get(name.toUpperCase()); + if(dc!=null) + throw new JClassAlreadyExistsException(dc); + upperCaseClassMap.put(name.toUpperCase(),c); + } + classes.put(name,c); + return c; + } + } + + /** + * Adds a public class to this package. + */ + public JDefinedClass _class(String name) throws JClassAlreadyExistsException { + return _class( JMod.PUBLIC, name ); + } + + /** + * Gets a reference to the already created {@link JDefinedClass}. + * + * @return null + * If the class is not yet created. + */ + public JDefinedClass _getClass(String name) { + if(classes.containsKey(name)) + return classes.get(name); + else + return null; + } + + /** + * Order is based on the lexicological order of the package name. + */ + public int compareTo(JPackage that) { + return this.name.compareTo(that.name); + } + + /** + * Add an interface to this package. + * + * @param mods + * Modifiers for this interface declaration + * + * @param name + * Name of interface to be added to this package + * + * @return Newly generated interface + */ + public JDefinedClass _interface(int mods, String name) throws JClassAlreadyExistsException { + return _class(mods,name,ClassType.INTERFACE); + } + + /** + * Adds a public interface to this package. + */ + public JDefinedClass _interface(String name) throws JClassAlreadyExistsException { + return _interface(JMod.PUBLIC, name); + } + + /** + * Add an annotationType Declaration to this package + * @param name + * Name of the annotation Type declaration to be added to this package + * @return + * newly created Annotation Type Declaration + * @exception JClassAlreadyExistsException + * When the specified class/interface was already created. + + */ + public JDefinedClass _annotationTypeDeclaration(String name) throws JClassAlreadyExistsException { + return _class (JMod.PUBLIC,name,ClassType.ANNOTATION_TYPE_DECL); + } + + /** + * Add a public enum to this package + * @param name + * Name of the enum to be added to this package + * @return + * newly created Enum + * @exception JClassAlreadyExistsException + * When the specified class/interface was already created. + + */ + public JDefinedClass _enum (String name) throws JClassAlreadyExistsException { + return _class (JMod.PUBLIC,name,ClassType.ENUM); + } + /** + * Adds a new resource file to this package. + */ + public JResourceFile addResourceFile(JResourceFile rsrc) { + resources.add(rsrc); + return rsrc; + } + + /** + * Checks if a resource of the given name exists. + */ + public boolean hasResourceFile(String name) { + for (JResourceFile r : resources) + if (r.name().equals(name)) + return true; + return false; + } + + /** + * Iterates all resource files in this package. + */ + public Iterator propertyFiles() { + return resources.iterator(); + } + + /** + * Creates, if necessary, and returns the package javadoc for this + * JDefinedClass. + * + * @return JDocComment containing javadocs for this class + */ + public JDocComment javadoc() { + if (jdoc == null) + jdoc = new JDocComment(owner()); + return jdoc; + } + + /** + * Removes a class from this package. + */ + public void remove(JClass c) { + if (c._package() != this) + throw new IllegalArgumentException( + "the specified class is not a member of this package," + " or it is a referenced class"); + + // note that c may not be a member of classes. + // this happens when someone is trying to remove a non generated class + classes.remove(c.name()); + if (upperCaseClassMap != null) + upperCaseClassMap.remove(c.name().toUpperCase()); + } + + /** + * Reference a class within this package. + */ + public JClass ref(String name) throws ClassNotFoundException { + if (name.indexOf('.') >= 0) + throw new IllegalArgumentException("JClass name contains '.': " + name); + + String n = ""; + if (!isUnnamed()) + n = this.name + '.'; + n += name; + + return owner.ref(Class.forName(n)); + } + + /** + * Gets a reference to a sub package of this package. + */ + public JPackage subPackage( String pkg ) { + if(isUnnamed()) return owner()._package(pkg); + else return owner()._package(name+'.'+pkg); + } + + /** + * Returns an iterator that walks the top-level classes defined in this + * package. + */ + public Iterator classes() { + return classes.values().iterator(); + } + + /** + * Checks if a given name is already defined as a class/interface + */ + public boolean isDefined(String classLocalName) { + Iterator itr = classes(); + while (itr.hasNext()) { + if ((itr.next()).name().equals(classLocalName)) + return true; + } + + return false; + } + + /** + * Checks if this package is the root, unnamed package. + */ + public final boolean isUnnamed() { return name.length() == 0; } + + /** + * Get the name of this package + * + * @return + * The name of this package, or the empty string if this is the + * null package. For example, this method returns strings like + * "java.lang" + */ + public String name() { + return name; + } + + /** + * Return the code model root object being used to create this package. + */ + public final JCodeModel owner() { return owner; } + + + public JAnnotationUse annotate(JClass clazz) { + if(isUnnamed()) + throw new IllegalArgumentException("the root package cannot be annotated"); + if(annotations==null) + annotations = new ArrayList(); + JAnnotationUse a = new JAnnotationUse(clazz); + annotations.add(a); + return a; + } + + public JAnnotationUse annotate(Class clazz) { + return annotate(owner.ref(clazz)); + } + + public W annotate2(Class clazz) { + return TypedAnnotationWriter.create(clazz,this); + } + + public Collection annotations() { + if (annotations == null) + annotations = new ArrayList(); + return Collections.unmodifiableList(annotations); + } + + /** + * Convert the package name to directory path equivalent + */ + File toPath(File dir) { + if (name == null) return dir; + return new File(dir, name.replace('.', File.separatorChar)); + } + + public void declare(JFormatter f ) { + if (name.length() != 0) + f.p("package").p(name).p(';').nl(); + } + + public void generate(JFormatter f) { + f.p(name); + } + + + void build( CodeWriter src, CodeWriter res ) throws IOException { + + // write classes + for (JDefinedClass c : classes.values()) { + if (c.isHidden()) + continue; // don't generate this file + + JFormatter f = createJavaSourceFileWriter(src, c.name()); + f.write(c); + f.close(); + } + + // write package annotations + if(annotations!=null || jdoc!=null) { + JFormatter f = createJavaSourceFileWriter(src,"package-info"); + + if (jdoc != null) + f.g(jdoc); + + // TODO: think about importing + if (annotations != null){ + for (JAnnotationUse a : annotations) + f.g(a).nl(); + } + f.d(this); + + f.close(); + } + + // write resources + for (JResourceFile rsrc : resources) { + CodeWriter cw = rsrc.isResource() ? res : src; + OutputStream os = new BufferedOutputStream(cw.openBinary(this, rsrc.name())); + rsrc.build(os); + os.close(); + } + } + + /*package*/ int countArtifacts() { + int r = 0; + for (JDefinedClass c : classes.values()) { + if (c.isHidden()) + continue; // don't generate this file + r++; + } + + if(annotations!=null || jdoc!=null) { + r++; + } + + r+= resources.size(); + + return r; + } + + private JFormatter createJavaSourceFileWriter(CodeWriter src, String className) throws IOException { + Writer bw = new BufferedWriter(src.openSource(this,className+".java")); + return new JFormatter(new PrintWriter(bw)); + } +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JPrimitiveType.java b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JPrimitiveType.java new file mode 100644 index 00000000000..cf2d0a82cdc --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JPrimitiveType.java @@ -0,0 +1,123 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.codemodel.internal; + + +/** + * Java built-in primitive types. + * + * Instances of this class can be obtained as constants of {@link JCodeModel}, + * such as {@link JCodeModel#BOOLEAN}. + */ +public final class JPrimitiveType extends JType { + + private final String typeName; + private final JCodeModel owner; + /** + * Corresponding wrapper class. + * For example, this would be "java.lang.Short" for short. + */ + private final JClass wrapperClass; + + JPrimitiveType(JCodeModel owner, String typeName, Class wrapper ) { + this.owner = owner; + this.typeName = typeName; + this.wrapperClass = owner.ref(wrapper); + } + + public JCodeModel owner() { return owner; } + + public String fullName() { + return typeName; + } + + public String name() { + return fullName(); + } + + public boolean isPrimitive() { + return true; + } + + private JClass arrayClass; + public JClass array() { + if(arrayClass==null) + arrayClass = new JArrayClass(owner,this); + return arrayClass; + } + + /** + * Obtains the wrapper class for this primitive type. + * For example, this method returns a reference to java.lang.Integer + * if this object represents int. + */ + public JClass boxify() { + return wrapperClass; + } + + /** + * @deprecated calling this method from {@link JPrimitiveType} + * would be meaningless, since it's always guaranteed to + * return this. + */ + public JType unboxify() { + return this; + } + + /** + * @deprecated + * Use {@link #boxify()}. + */ + public JClass getWrapperClass() { + return boxify(); + } + + /** + * Wraps an expression of this type to the corresponding wrapper class. + * For example, if this class represents "float", this method will return + * the expression new Float(x) for the paramter x. + * + * REVISIT: it's not clear how this method works for VOID. + */ + public JExpression wrap( JExpression exp ) { + return JExpr._new(boxify()).arg(exp); + } + + /** + * Do the opposite of the wrap method. + * + * REVISIT: it's not clear how this method works for VOID. + */ + public JExpression unwrap( JExpression exp ) { + // it just so happens that the unwrap method is always + // things like "intValue" or "booleanValue". + return exp.invoke(typeName+"Value"); + } + + public void generate(JFormatter f) { + f.p(typeName); + } +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JResourceFile.java b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JResourceFile.java new file mode 100644 index 00000000000..41720e745fe --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JResourceFile.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.codemodel.internal; + +import java.io.IOException; +import java.io.OutputStream; + +/** + * Represents a resource file in the application-specific file format. + */ +public abstract class JResourceFile { + + private final String name; + + protected JResourceFile( String name ) { + this.name = name; + } + + /** + * Gets the name of this property file + */ + public String name() { + return name; + } + + /** + * Returns true if this file should be generated into the directory + * that the resource files go into. + * + *

+ * Returns false if this file should be generated into the directory + * where other source files go. + */ + protected boolean isResource() { + return true; + } + + /** + * called by JPackage to produce the file image. + */ + protected abstract void build( OutputStream os ) throws IOException; +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JReturn.java b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JReturn.java new file mode 100644 index 00000000000..8b5c99b09cd --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JReturn.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.codemodel.internal; + + +/** + * A return statement + */ +class JReturn implements JStatement { + + /** + * JExpression to return; may be null. + */ + private JExpression expr; + + /** + * JReturn constructor + * + * @param expr + * JExpression which evaluates to return value + */ + JReturn(JExpression expr) { + this.expr = expr; + } + + public void state(JFormatter f) { + f.p("return "); + if (expr != null) f.g(expr); + f.p(';').nl(); + } + +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JStatement.java b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JStatement.java new file mode 100644 index 00000000000..d90182a77df --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JStatement.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.codemodel.internal; + + +/** + * Common interface for code components that can generate + * uses of themselves as statements. + */ + +public interface JStatement { + + public void state(JFormatter f); + +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JStringLiteral.java b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JStringLiteral.java new file mode 100644 index 00000000000..19321516508 --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JStringLiteral.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.codemodel.internal; + +/** + * String literal. + * + * @author + * Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com) + */ +public class JStringLiteral extends JExpressionImpl { + + public final String str; + + + JStringLiteral(String what) { + this.str = what; + + } + + + public void generate(JFormatter f) { + f.p(JExpr.quotify('"', str)); + } +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JSwitch.java b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JSwitch.java new file mode 100644 index 00000000000..3bd1065613b --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JSwitch.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.codemodel.internal; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +/** + * Switch statement + */ +public final class JSwitch implements JStatement { + + /** + * Test part of switch statement. + */ + private JExpression test; + + /** + * vector of JCases. + */ + private List cases = new ArrayList(); + + /** + * a single default case + */ + private JCase defaultCase = null; + + /** + * Construct a While statment + */ + JSwitch(JExpression test) { + this.test = test; + } + + public JExpression test() { return test; } + + public Iterator cases() { return cases.iterator(); } + + public JCase _case( JExpression label ) { + JCase c = new JCase( label ); + cases.add(c); + return c; + } + + public JCase _default() { + // what if (default != null) ??? + + // default cases statements don't have a label + defaultCase = new JCase(null, true); + return defaultCase; + } + + public void state(JFormatter f) { + if (JOp.hasTopOp(test)) { + f.p("switch ").g(test).p(" {").nl(); + } else { + f.p("switch (").g(test).p(')').p(" {").nl(); + } + for( JCase c : cases ) + f.s(c); + if( defaultCase != null ) + f.s( defaultCase ); + f.p('}').nl(); + } + +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JThrow.java b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JThrow.java new file mode 100644 index 00000000000..bce277b2a52 --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JThrow.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.codemodel.internal; + + +/** + * JThrow statement + */ + +class JThrow implements JStatement { + + /** + * JExpression to throw + */ + private JExpression expr; + + /** + * JThrow constructor + * + * @param expr + * JExpression which evaluates to JThrow value + */ + JThrow(JExpression expr) { + this.expr = expr; + } + + public void state(JFormatter f) { + f.p("throw"); + f.g(expr); + f.p(';').nl(); + } + +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JTryBlock.java b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JTryBlock.java new file mode 100644 index 00000000000..19ba4628082 --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JTryBlock.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.codemodel.internal; + +import java.util.ArrayList; +import java.util.List; + + +/** + * Try statement with Catch and/or Finally clause + */ + +public class JTryBlock implements JStatement { + + private JBlock body = new JBlock(); + private List catches = new ArrayList(); + private JBlock _finally = null; + + JTryBlock() { + } + + public JBlock body() { + return body; + } + + public JCatchBlock _catch(JClass exception) { + JCatchBlock cb = new JCatchBlock(exception); + catches.add(cb); + return cb; + } + + public JBlock _finally() { + if (_finally == null) _finally = new JBlock(); + return _finally; + } + + public void state(JFormatter f) { + f.p("try").g(body); + for (JCatchBlock cb : catches) + f.g(cb); + if (_finally != null) + f.p("finally").g(_finally); + f.nl(); + } + +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JType.java b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JType.java new file mode 100644 index 00000000000..cee832f97a2 --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JType.java @@ -0,0 +1,182 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.codemodel.internal; + + +/** + * A representation of a type in codeModel. + * + * A type is always either primitive ({@link JPrimitiveType}) or + * a reference type ({@link JClass}). + */ +public abstract class JType implements JGenerable, Comparable { + + /** + * Obtains a reference to the primitive type object from a type name. + */ + public static JPrimitiveType parse(JCodeModel codeModel, String typeName) { + if (typeName.equals("void")) + return codeModel.VOID; + else if (typeName.equals("boolean")) + return codeModel.BOOLEAN; + else if (typeName.equals("byte")) + return codeModel.BYTE; + else if (typeName.equals("short")) + return codeModel.SHORT; + else if (typeName.equals("char")) + return codeModel.CHAR; + else if (typeName.equals("int")) + return codeModel.INT; + else if (typeName.equals("float")) + return codeModel.FLOAT; + else if (typeName.equals("long")) + return codeModel.LONG; + else if (typeName.equals("double")) + return codeModel.DOUBLE; + else + throw new IllegalArgumentException("Not a primitive type: " + typeName); + } + + /** Gets the owner code model object. */ + public abstract JCodeModel owner(); + + /** + * Gets the full name of the type. + * + * See http://java.sun.com/docs/books/jls/second_edition/html/names.doc.html#25430 for the details. + * + * @return + * Strings like "int", "java.lang.String", + * "java.io.File[]". Never null. + */ + public abstract String fullName(); + + /** + * Gets the binary name of the type. + * + * See http://java.sun.com/docs/books/jls/third_edition/html/binaryComp.html#44909 + * + * @return + * Name like "Foo$Bar", "int", "java.lang.String", "java.io.File[]". Never null. + */ + public String binaryName() { + return fullName(); + } + + /** + * Gets the name of this type. + * + * @return + * Names like "int", "void", "BigInteger". + */ + public abstract String name(); + + /** + * Create an array type of this type. + * + * This method is undefined for primitive void type, which + * doesn't have any corresponding array representation. + * + * @return A {@link JClass} representing the array type + * whose element type is this type + */ + public abstract JClass array(); + + /** Tell whether or not this is an array type. */ + public boolean isArray() { + return false; + } + + /** Tell whether or not this is a built-in primitive type, such as int or void. */ + public boolean isPrimitive() { + return false; + } + + /** + * If this class is a primitive type, return the boxed class. Otherwise return this. + * + *

+ * For example, for "int", this method returns "java.lang.Integer". + */ + public abstract JClass boxify(); + + /** + * If this class is a wrapper type for a primitive, return the primitive type. + * Otherwise return this. + * + *

+ * For example, for "java.lang.Integer", this method returns "int". + */ + public abstract JType unboxify(); + + /** + * Returns the erasure of this type. + */ + public JType erasure() { + return this; + } + + /** + * Returns true if this is a referenced type. + */ + public final boolean isReference() { + return !isPrimitive(); + } + + /** + * If this is an array, returns the component type of the array. + * (T of T[]) + */ + public JType elementType() { + throw new IllegalArgumentException("Not an array type"); + } + + public String toString() { + return this.getClass().getName() + + '(' + fullName() + ')'; + } + + /** + * Compare two JTypes by FQCN, giving sorting precedence to types + * that belong to packages java and javax over all others. + * + * This method is used to sort generated import statments in a + * conventional way for readability. + */ + public int compareTo(JType o) { + final String rhs = o.fullName(); + boolean p = fullName().startsWith("java"); + boolean q = rhs.startsWith("java"); + + if( p && !q ) { + return -1; + } else if( !p && q ) { + return 1; + } else { + return fullName().compareTo(rhs); + } + } +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JTypeVar.java b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JTypeVar.java new file mode 100644 index 00000000000..bf420413675 --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JTypeVar.java @@ -0,0 +1,121 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.codemodel.internal; + +import java.util.Iterator; +import java.util.List; + +/** + * Type variable used to declare generics. + * + * @see JGenerifiable + * @author + * Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com) + */ +public final class JTypeVar extends JClass implements JDeclaration { + + private final String name; + + private JClass bound; + + JTypeVar(JCodeModel owner, String _name) { + super(owner); + this.name = _name; + } + + public String name() { + return name; + } + + public String fullName() { + return name; + } + + public JPackage _package() { + return null; + } + + /** + * Adds a bound to this variable. + * + * @return this + */ + public JTypeVar bound( JClass c ) { + if(bound!=null) + throw new IllegalArgumentException("type variable has an existing class bound "+bound); + bound = c; + return this; + } + + /** + * Returns the class bound of this variable. + * + *

+ * If no bound is given, this method returns {@link Object}. + */ + public JClass _extends() { + if(bound!=null) + return bound; + else + return owner().ref(Object.class); + } + + /** + * Returns the interface bounds of this variable. + */ + public Iterator _implements() { + return bound._implements(); + } + + public boolean isInterface() { + return false; + } + + public boolean isAbstract() { + return false; + } + + /** + * Prints out the declaration of the variable. + */ + public void declare(JFormatter f) { + f.id(name); + if(bound!=null) + f.p("extends").g(bound); + } + + + protected JClass substituteParams(JTypeVar[] variables, List bindings) { + for(int i=0;i + * Instances of this class can be obtained from {@link JClass#wildcard()} + * + * TODO: extend this to cover "? super Integer". + * + *

+ * Our modeling of types are starting to look really ugly. + * ideally it should have been done somewhat like APT, + * but it's too late now. + * + * @author Kohsuke Kawaguchi + */ +final class JTypeWildcard extends JClass { + + private final JClass bound; + + JTypeWildcard(JClass bound) { + super(bound.owner()); + this.bound = bound; + } + + public String name() { + return "? extends "+bound.name(); + } + + public String fullName() { + return "? extends "+bound.fullName(); + } + + public JPackage _package() { + return null; + } + + /** + * Returns the class bound of this variable. + * + *

+ * If no bound is given, this method returns {@link Object}. + */ + public JClass _extends() { + if(bound!=null) + return bound; + else + return owner().ref(Object.class); + } + + /** + * Returns the interface bounds of this variable. + */ + public Iterator _implements() { + return bound._implements(); + } + + public boolean isInterface() { + return false; + } + + public boolean isAbstract() { + return false; + } + + protected JClass substituteParams(JTypeVar[] variables, List bindings) { + JClass nb = bound.substituteParams(variables,bindings); + if(nb==bound) + return this; + else + return new JTypeWildcard(nb); + } + + public void generate(JFormatter f) { + if(bound._extends()==null) + f.p("?"); // instead of "? extends Object" + else + f.p("? extends").g(bound); + } +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JVar.java b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JVar.java new file mode 100644 index 00000000000..a4942b697bb --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/JVar.java @@ -0,0 +1,216 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.codemodel.internal; + +import java.lang.annotation.Annotation; +import java.util.ArrayList; +import java.util.List; +import java.util.Collection; +import java.util.Collections; + + +/** + * Variables and fields. + */ + +public class JVar extends JExpressionImpl implements JDeclaration, JAssignmentTarget, JAnnotatable { + + /** + * Modifiers. + */ + private JMods mods; + + /** + * JType of the variable + */ + private JType type; + + /** + * Name of the variable + */ + private String name; + + /** + * Initialization of the variable in its declaration + */ + private JExpression init; + + /** + * Annotations on this variable. Lazily created. + */ + private List annotations = null; + + + + /** + * JVar constructor + * + * @param type + * Datatype of this variable + * + * @param name + * Name of this variable + * + * @param init + * Value to initialize this variable to + */ + JVar(JMods mods, JType type, String name, JExpression init) { + this.mods = mods; + this.type = type; + this.name = name; + this.init = init; + } + + + /** + * Initialize this variable + * + * @param init + * JExpression to be used to initialize this field + */ + public JVar init(JExpression init) { + this.init = init; + return this; + } + + /** + * Get the name of this variable + * + * @return Name of the variable + */ + public String name() { + return name; + } + + /** + * Changes the name of this variable. + */ + public void name(String name) { + if(!JJavaName.isJavaIdentifier(name)) + throw new IllegalArgumentException(); + this.name = name; + } + + /** + * Return the type of this variable. + * @return + * always non-null. + */ + public JType type() { + return type; + } + + /** + * @return + * the current modifiers of this method. + * Always return non-null valid object. + */ + public JMods mods() { + return mods; + } + + /** + * Sets the type of this variable. + * + * @param newType + * must not be null. + * + * @return + * the old type value. always non-null. + */ + public JType type(JType newType) { + JType r = type; + if(newType==null) + throw new IllegalArgumentException(); + type = newType; + return r; + } + + + /** + * Adds an annotation to this variable. + * @param clazz + * The annotation class to annotate the field with + */ + public JAnnotationUse annotate(JClass clazz){ + if(annotations==null) + annotations = new ArrayList(); + JAnnotationUse a = new JAnnotationUse(clazz); + annotations.add(a); + return a; + } + + /** + * Adds an annotation to this variable. + * + * @param clazz + * The annotation class to annotate the field with + */ + public JAnnotationUse annotate(Class clazz){ + return annotate(type.owner().ref(clazz)); + } + + public W annotate2(Class clazz) { + return TypedAnnotationWriter.create(clazz,this); + } + + public Collection annotations() { + if (annotations == null) + annotations = new ArrayList(); + return Collections.unmodifiableList(annotations); + } + + protected boolean isAnnotated() { + return annotations!=null; + } + + public void bind(JFormatter f) { + if (annotations != null){ + for( int i=0; i> + implements InvocationHandler, JAnnotationWriter { + /** + * This is what we are writing to. + */ + private final JAnnotationUse use; + + /** + * The annotation that we are writing. + */ + private final Class annotation; + + /** + * The type of the writer. + */ + private final Class writerType; + + /** + * Keeps track of writers for array members. + * Lazily created. + */ + private Map arrays; + + public TypedAnnotationWriter(Class annotation, Class writer, JAnnotationUse use) { + this.annotation = annotation; + this.writerType = writer; + this.use = use; + } + + public JAnnotationUse getAnnotationUse() { + return use; + } + + public Class getAnnotationType() { + return annotation; + } + + @SuppressWarnings("unchecked") + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + + if(method.getDeclaringClass()==JAnnotationWriter.class) { + try { + return method.invoke(this,args); + } catch (InvocationTargetException e) { + throw e.getTargetException(); + } + } + + String name = method.getName(); + Object arg=null; + if(args!=null && args.length>0) + arg = args[0]; + + // check how it's defined on the annotation + Method m = annotation.getDeclaredMethod(name); + Class rt = m.getReturnType(); + + // array value + if(rt.isArray()) { + return addArrayValue(proxy,name,rt.getComponentType(),method.getReturnType(),arg); + } + + // sub annotation + if(Annotation.class.isAssignableFrom(rt)) { + Class r = (Class)rt; + return new TypedAnnotationWriter( + r,method.getReturnType(),use.annotationParam(name,r)).createProxy(); + } + + // scalar value + + if(arg instanceof JType) { + JType targ = (JType) arg; + checkType(Class.class,rt); + if(m.getDefaultValue()!=null) { + // check the default + if(targ.equals(targ.owner().ref((Class)m.getDefaultValue()))) + return proxy; // defaulted + } + use.param(name,targ); + return proxy; + } + + // other Java built-in types + checkType(arg.getClass(),rt); + if(m.getDefaultValue()!=null && m.getDefaultValue().equals(arg)) + // defaulted. no need to write out. + return proxy; + + if(arg instanceof String) { + use.param(name,(String)arg); + return proxy; + } + if(arg instanceof Boolean) { + use.param(name,(Boolean)arg); + return proxy; + } + if(arg instanceof Integer) { + use.param(name,(Integer)arg); + return proxy; + } + if(arg instanceof Class) { + use.param(name,(Class)arg); + return proxy; + } + if(arg instanceof Enum) { + use.param(name,(Enum)arg); + return proxy; + } + + throw new IllegalArgumentException("Unable to handle this method call "+method.toString()); + } + + @SuppressWarnings("unchecked") + private Object addArrayValue(Object proxy,String name, Class itemType, Class expectedReturnType, Object arg) { + if(arrays==null) + arrays = new HashMap(); + JAnnotationArrayMember m = arrays.get(name); + if(m==null) { + m = use.paramArray(name); + arrays.put(name,m); + } + + // sub annotation + if(Annotation.class.isAssignableFrom(itemType)) { + Class r = (Class)itemType; + if(!JAnnotationWriter.class.isAssignableFrom(expectedReturnType)) + throw new IllegalArgumentException("Unexpected return type "+expectedReturnType); + return new TypedAnnotationWriter(r,expectedReturnType,m.annotate(r)).createProxy(); + } + + // primitive + if(arg instanceof JType) { + checkType(Class.class,itemType); + m.param((JType)arg); + return proxy; + } + checkType(arg.getClass(),itemType); + if(arg instanceof String) { + m.param((String)arg); + return proxy; + } + if(arg instanceof Boolean) { + m.param((Boolean)arg); + return proxy; + } + if(arg instanceof Integer) { + m.param((Integer)arg); + return proxy; + } + if(arg instanceof Class) { + m.param((Class)arg); + return proxy; + } + // TODO: enum constant. how should we handle it? + + throw new IllegalArgumentException("Unable to handle this method call "); + } + + + /** + * Check if the type of the argument matches our expectation. + * If not, report an error. + */ + private void checkType(Class actual, Class expected) { + if(expected==actual || expected.isAssignableFrom(actual)) + return; // no problem + + if( expected==JCodeModel.boxToPrimitive.get(actual) ) + return; // no problem + + throw new IllegalArgumentException("Expected "+expected+" but found "+actual); + } + + /** + * Creates a proxy and returns it. + */ + @SuppressWarnings("unchecked") + private W createProxy() { + return (W)Proxy.newProxyInstance( + SecureLoader.getClassClassLoader(writerType),new Class[]{writerType},this); + } + + /** + * Creates a new typed annotation writer. + */ + @SuppressWarnings("unchecked") + static > W create(Class w, JAnnotatable annotatable) { + Class a = findAnnotationType(w); + return (W)new TypedAnnotationWriter(a,w,annotatable.annotate(a)).createProxy(); + } + + private static Class findAnnotationType(Class clazz) { + for( Type t : clazz.getGenericInterfaces()) { + if(t instanceof ParameterizedType) { + ParameterizedType p = (ParameterizedType) t; + if(p.getRawType()==JAnnotationWriter.class) + return (Class)p.getActualTypeArguments()[0]; + } + if(t instanceof Class) { + // recursive search + Class r = findAnnotationType((Class)t); + if(r!=null) return r; + } + } + return null; + } +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/fmt/JBinaryFile.java b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/fmt/JBinaryFile.java new file mode 100644 index 00000000000..24019654122 --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/fmt/JBinaryFile.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.codemodel.internal.fmt; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +import com.sun.codemodel.internal.JResourceFile; + +/** + * Allows the application to use OutputStream to define data + * that will be stored into a file. + * + * @author + * Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com) + */ +public final class JBinaryFile extends JResourceFile { + + private final ByteArrayOutputStream baos = new ByteArrayOutputStream(); + + public JBinaryFile( String name ) { + super(name); + } + + /** + * + * @return + * Data written to the returned output stream will be written + * to the file. + */ + public OutputStream getDataStore() { + return baos; + } + + public void build(OutputStream os) throws IOException { + os.write( baos.toByteArray() ); + } +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/fmt/JPropertyFile.java b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/fmt/JPropertyFile.java new file mode 100644 index 00000000000..5a8418d9730 --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/fmt/JPropertyFile.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.codemodel.internal.fmt; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.Properties; + +import com.sun.codemodel.internal.JResourceFile; + +/** + * A property file. + */ +public class JPropertyFile extends JResourceFile +{ + public JPropertyFile( String name ) { + super(name); + } + + private final Properties data = new Properties(); + + /** + * Adds key/value pair into the property file. + * If you call this method twice with the same key, + * the old one is overriden by the new one. + */ + public void add( String key, String value ) { + data.put(key,value); + } + + // TODO: method to iterate values in data? + // TODO: should we rather expose Properties object directly via + // public Properties body() { return data; } ? + + public void build( OutputStream out ) throws IOException { + data.store(out,null); + } +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/fmt/JSerializedObject.java b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/fmt/JSerializedObject.java new file mode 100644 index 00000000000..525f7766cb7 --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/fmt/JSerializedObject.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.codemodel.internal.fmt; + +import java.io.IOException; +import java.io.ObjectOutputStream; +import java.io.OutputStream; + +import com.sun.codemodel.internal.JResourceFile; + + +/** + * A simple class that takes an object and serializes it into a file + * in the parent package with the given name. + */ +public class JSerializedObject extends JResourceFile { + + private final Object obj; + + /** + * @exception IOException + * If the serialization fails, this exception is thrown + */ + public JSerializedObject( String name, Object obj ) throws IOException { + super(name); + this.obj = obj; + } + + /** + * called by JPackage to serialize the object + */ + protected void build( OutputStream os ) throws IOException { + // serialize the obj into a ByteArrayOutputStream + ObjectOutputStream oos = new ObjectOutputStream(os); + oos.writeObject(obj); + oos.close(); + } +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/fmt/JStaticFile.java b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/fmt/JStaticFile.java new file mode 100644 index 00000000000..f06527ca4e1 --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/fmt/JStaticFile.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.codemodel.internal.fmt; + +import java.io.DataInputStream; +import java.io.IOException; +import java.io.OutputStream; + +import com.sun.codemodel.internal.JResourceFile; + +/** + * Allows an application to copy a resource file to the output. + * + * @author + * Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com) + */ +public final class JStaticFile extends JResourceFile { + + private final ClassLoader classLoader; + private final String resourceName; + private final boolean isResource; + + public JStaticFile(String _resourceName) { + this(_resourceName,!_resourceName.endsWith(".java")); + } + + public JStaticFile(String _resourceName,boolean isResource) { + this( SecureLoader.getClassClassLoader(JStaticFile.class), _resourceName, isResource ); + } + + /** + * @param isResource + * false if this is a Java source file. True if this is other resource files. + */ + public JStaticFile(ClassLoader _classLoader, String _resourceName, boolean isResource) { + super(_resourceName.substring(_resourceName.lastIndexOf('/')+1)); + this.classLoader = _classLoader; + this.resourceName = _resourceName; + this.isResource = isResource; + } + + protected boolean isResource() { + return isResource; + } + + protected void build(OutputStream os) throws IOException { + DataInputStream dis = new DataInputStream(classLoader.getResourceAsStream(resourceName)); + + byte[] buf = new byte[256]; + int sz; + while( (sz=dis.read(buf))>0 ) + os.write(buf,0,sz); + + dis.close(); + } + +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/fmt/JStaticJavaFile.java b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/fmt/JStaticJavaFile.java new file mode 100644 index 00000000000..bdf83bac211 --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/fmt/JStaticJavaFile.java @@ -0,0 +1,239 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.codemodel.internal.fmt; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.net.URL; +import java.text.ParseException; +import java.util.Iterator; +import java.util.List; + +import com.sun.codemodel.internal.JClass; +import com.sun.codemodel.internal.JPackage; +import com.sun.codemodel.internal.JResourceFile; +import com.sun.codemodel.internal.JTypeVar; + +/** + * Statically generated Java soruce file. + * + *

+ * This {@link JResourceFile} implementation will generate a Java source + * file by copying the source code from a resource. + *

+ * While copying a resource, we look for a package declaration and + * replace it with the target package name. This allows the static Java + * source code to have an arbitrary package declaration. + *

+ * You can also use the getJClass method to obtain a {@link JClass} + * object that represents the static file. This allows the client code + * to refer to the class from other CodeModel generated code. + *

+ * Note that because we don't parse the static Java source code, + * the returned {@link JClass} object doesn't respond to methods like + * "isInterface" or "_extends", + * + * @author + * Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com) + */ +public final class JStaticJavaFile extends JResourceFile { + + private final JPackage pkg; + private final String className; + private final URL source; + private final JStaticClass clazz; + private final LineFilter filter; + + public JStaticJavaFile(JPackage _pkg, String className, String _resourceName) { + this( _pkg, className, + SecureLoader.getClassClassLoader(JStaticJavaFile.class).getResource(_resourceName), null ); + } + + public JStaticJavaFile(JPackage _pkg, String _className, URL _source, LineFilter _filter ) { + super(_className+".java"); + if(_source==null) throw new NullPointerException(); + this.pkg = _pkg; + this.clazz = new JStaticClass(); + this.className = _className; + this.source = _source; + this.filter = _filter; + } + + /** + * Returns a class object that represents a statically generated code. + */ + public final JClass getJClass() { + return clazz; + } + + protected boolean isResource() { + return false; + } + + protected void build(OutputStream os) throws IOException { + InputStream is = source.openStream(); + + BufferedReader r = new BufferedReader(new InputStreamReader(is)); + PrintWriter w = new PrintWriter(new BufferedWriter(new OutputStreamWriter(os))); + LineFilter filter = createLineFilter(); + int lineNumber=1; + + try { + String line; + while((line=r.readLine())!=null) { + line = filter.process(line); + if(line!=null) + w.println(line); + lineNumber++; + } + } catch( ParseException e ) { + throw new IOException("unable to process "+source+" line:"+lineNumber+"\n"+e.getMessage()); + } + + w.close(); + r.close(); + } + + /** + * Creates a {@link LineFilter}. + *

+ * A derived class can override this method to process + * the contents of the source file. + */ + private LineFilter createLineFilter() { + // this filter replaces the package declaration. + LineFilter f = new LineFilter() { + public String process(String line) { + if(!line.startsWith("package ")) return line; + + // replace package decl + if( pkg.isUnnamed() ) + return null; + else + return "package "+pkg.name()+";"; + } + }; + if( filter!=null ) + return new ChainFilter(filter,f); + else + return f; + } + + /** + * Filter that alters the Java source code. + *

+ * By implementing this interface, derived classes + * can modify the Java source file before it's written out. + */ + public interface LineFilter { + /** + * @param line + * a non-null valid String that corresponds to one line. + * No '\n' included. + * @return + * null to strip the line off. Otherwise the returned + * String will be written out. Do not add '\n' at the end + * of this string. + * + * @exception ParseException + * when for some reason there's an error in the line. + */ + String process(String line) throws ParseException; + } + + /** + * A {@link LineFilter} that combines two {@link LineFilter}s. + */ + public final static class ChainFilter implements LineFilter { + private final LineFilter first,second; + public ChainFilter( LineFilter first, LineFilter second ) { + this.first=first; + this.second=second; + } + public String process(String line) throws ParseException { + line = first.process(line); + if(line==null) return null; + return second.process(line); + } + } + + + private class JStaticClass extends JClass { + + private final JTypeVar[] typeParams; + + JStaticClass() { + super(pkg.owner()); + // TODO: allow those to be specified + typeParams = new JTypeVar[0]; + } + + public String name() { + return className; + } + + public String fullName() { + if(pkg.isUnnamed()) + return className; + else + return pkg.name()+'.'+className; + } + + public JPackage _package() { + return pkg; + } + + public JClass _extends() { + throw new UnsupportedOperationException(); + } + + public Iterator _implements() { + throw new UnsupportedOperationException(); + } + + public boolean isInterface() { + throw new UnsupportedOperationException(); + } + + public boolean isAbstract() { + throw new UnsupportedOperationException(); + } + + public JTypeVar[] typeParams() { + return typeParams; + } + + protected JClass substituteParams(JTypeVar[] variables, List bindings) { + return this; + } + }; +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/fmt/JTextFile.java b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/fmt/JTextFile.java new file mode 100644 index 00000000000..0be4048e8b5 --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/fmt/JTextFile.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.codemodel.internal.fmt; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.Writer; + +import com.sun.codemodel.internal.JResourceFile; + + +/** + * Simple text file. + * + * @author + * Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com) + */ +public class JTextFile extends JResourceFile +{ + public JTextFile( String name ) { + super(name); + } + + private String contents = null; + + public void setContents( String _contents ) { + this.contents = _contents; + } + + public void build( OutputStream out ) throws IOException { + Writer w = new OutputStreamWriter(out); + w.write(contents); + w.close(); + } +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/fmt/SecureLoader.java b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/fmt/SecureLoader.java new file mode 100644 index 00000000000..aaf18e71ba8 --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/fmt/SecureLoader.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.codemodel.internal.fmt; + +import com.sun.codemodel.internal.*; + +/** + * Class defined for safe calls of getClassLoader methods of any kind (context/system/class + * classloader. This MUST be package private and defined in every package which + * uses such invocations. + * @author snajper + */ +class SecureLoader { + + static ClassLoader getContextClassLoader() { + if (System.getSecurityManager() == null) { + return Thread.currentThread().getContextClassLoader(); + } else { + return (ClassLoader) java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction() { + public java.lang.Object run() { + return Thread.currentThread().getContextClassLoader(); + } + }); + } + } + + static ClassLoader getClassClassLoader(final Class c) { + if (System.getSecurityManager() == null) { + return c.getClassLoader(); + } else { + return (ClassLoader) java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction() { + public java.lang.Object run() { + return c.getClassLoader(); + } + }); + } + } + + static ClassLoader getSystemClassLoader() { + if (System.getSecurityManager() == null) { + return ClassLoader.getSystemClassLoader(); + } else { + return (ClassLoader) java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction() { + public java.lang.Object run() { + return ClassLoader.getSystemClassLoader(); + } + }); + } + } + + static void setContextClassLoader(final ClassLoader cl) { + if (System.getSecurityManager() == null) { + Thread.currentThread().setContextClassLoader(cl); + } else { + java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction() { + public java.lang.Object run() { + Thread.currentThread().setContextClassLoader(cl); + return null; + } + }); + } + } + +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/package-info.java b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/package-info.java new file mode 100644 index 00000000000..cb65b56655a --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/package-info.java @@ -0,0 +1,115 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + *

Library for generating Java source code

. + * + *

+ * CodeModel is a library that allows you to generate Java source + * code in a type-safe fashion. + * + *

+ * With CodeModel, you build the java source code by first building AST, + * then writing it out as text files that is Java source files. + * The AST looks like this: + * + * {@DotDiagram + digraph G { + cls1 [label="JDefinedClass"]; + cls2 [label="JDefinedClass"]; + JCodeModel -> cls1 [label="generated class"]; + JCodeModel -> cls2 [label="generated class"]; + + m1 [label="JMethod"]; + m2 [label="JMethod"]; + + cls1 -> m1; + cls1 -> m2; + cls1 -> JField; + + m1 -> JVar [label="method parameter"]; + m1 -> JBlock [label="code"]; + } + * } + * + *

+ * You bulid this tree mostly from top-down. So, you first create + * a new {@link JDefinedClass} from {@link JCodeModel}, then you + * create a {@link JMethod} from {@link JDefinedClass}, and so on. + * + *

+ * This design brings the following beneefits: + * + *

    + *
  • source code can be written in random order + *
  • generated source code nicely imports other classes + *
  • generated source code is lexically always correct + * (no unbalanced parenthesis, etc.) + *
  • code generation becomes relatively type-safe + *
+ * + * The price you pay for that is + * increased memory footprint and the generation speed. + * See
performance section for + * more discussions about the performance and possible improvements. + * + * + *

Using CodeModel

+ *

+ * {@link com.sun.codemodel.internal.JCodeModel} is the entry point to + * the library. See its javadoc for more details about how to use + * CodeModel. + * + * + * + *

Performance

+ *

+ * Generally speaking, CodeModel is expected to be used in + * an environment where the resource constraint is not severe. + * Therefore, we haven't spent much effort in trying to make + * this library lean and mean. + * + *

+ * That said, we did some benchmark and performance analysis. + * In case anyone is interested in making this library + * better performance wise, here's the findings. + * + *

+ * {@link List}s {@link Map}s, and other collections take up + * a lot of space. Allocating those things lazily is generally + * a good idea. + * + *

+ * Compared to template-based code generator, the writing operation + * is slow, as it needs to traverse each AST node. Consider + * pre-encoding tokens (like 'public') to the target encoding, + * and consider exploting the subtree equivalence. + * + * @ArchitectureDocument + */ +package com.sun.codemodel.internal; + +import java.util.List; +import java.util.Map; diff --git a/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/util/ClassNameComparator.java b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/util/ClassNameComparator.java new file mode 100644 index 00000000000..cf06eee3930 --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/util/ClassNameComparator.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.codemodel.internal.util; + +import java.util.Comparator; +import com.sun.codemodel.internal.JClass; + +/** + * Comparator object that sorts {@link JClass}es in the order + * of their names. + * + * @author + * Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com) + */ +public class ClassNameComparator implements Comparator { + private ClassNameComparator() {} + + public int compare(JClass l, JClass r) { + return l.fullName().compareTo(r.fullName()); + } + + public static final Comparator theInstance = new ClassNameComparator(); +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/util/EncoderFactory.java b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/util/EncoderFactory.java new file mode 100644 index 00000000000..d52adb2c552 --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/util/EncoderFactory.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @(#)$Id: EncoderFactory.java,v 1.3 2005/09/10 19:07:33 kohsuke Exp $ + */ +package com.sun.codemodel.internal.util; + +import java.lang.reflect.Constructor; +import java.nio.charset.Charset; +import java.nio.charset.CharsetEncoder; + +/** + * Creates {@link CharsetEncoder} from a charset name. + * + * Fixes a MS1252 handling bug in JDK1.4.2. + * + * @author + * Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com) + */ +public class EncoderFactory { + + public static CharsetEncoder createEncoder( String encodin ) { + Charset cs = Charset.forName(System.getProperty("file.encoding")); + CharsetEncoder encoder = cs.newEncoder(); + + if( cs.getClass().getName().equals("sun.nio.cs.MS1252") ) { + try { + // at least JDK1.4.2_01 has a bug in MS1252 encoder. + // specifically, it returns true for any character. + // return a correct encoder to workaround this problem + + // statically binding to MS1252Encoder will cause a Link error + // (at least in IBM JDK1.4.1) + @SuppressWarnings("unchecked") + Class ms1252encoder = (Class) Class.forName("com.sun.codemodel.internal.util.MS1252Encoder"); + Constructor c = ms1252encoder.getConstructor(new Class[]{ + Charset.class + }); + return c.newInstance(new Object[]{cs}); + } catch( Throwable t ) { + // if something funny happens, ignore it and fall back to + // a broken MS1252 encoder. It's probably still better + // than choking here. + return encoder; + } + } + + return encoder; + } +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/util/JavadocEscapeWriter.java b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/util/JavadocEscapeWriter.java new file mode 100644 index 00000000000..785d9ec6ea2 --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/util/JavadocEscapeWriter.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.codemodel.internal.util; + +import java.io.FilterWriter; +import java.io.IOException; +import java.io.Writer; + +/** + * {@link Writer} that escapes characters that are unsafe + * as Javadoc comments. + * + * Such characters include '<' and '&'. + * + *

+ * Note that this class doesn't escape other Unicode characters + * that are typically unsafe. For example, 愛 (A kanji + * that means "love") can be considered as unsafe because + * javac with English Windows cannot accept this character in the + * source code. + * + *

+ * If the application needs to escape such characters as well, then + * they are on their own. + * + * @author + * Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com) + */ +public class JavadocEscapeWriter extends FilterWriter { + + public JavadocEscapeWriter( Writer next ) { + super(next); + } + + public void write(int ch) throws IOException { + if(ch=='<') + out.write("<"); + else + if(ch=='&') + out.write("&"); + else + out.write(ch); + } + + public void write(char[] buf, int off, int len) throws IOException { + for( int i=0; i + * See + * http://www.microsoft.com/globaldev/reference/sbcs/1252.htm + * for the normative definition. + * + * This code depends on Sun internal package, so we have to make sure + * it won't be executed on other JDKs. + */ +public final class MS1252Encoder extends SingleByteEncoder { + + public MS1252Encoder(Charset cs) { + super(cs, index1, index2, 0xFF00, 0x00FF, 8); + } + + private final static String index2 = + "\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007" + + "\b\t\n\u000B\f\r\u000E\u000F" + + "\u0010\u0011\u0012\u0013\u0014\u0015\u0016\u0017" + + "\u0018\u0019\u001A\u001B\u001C\u001D\u001E\u001F" + + "\u0020\u0021\"\u0023\u0024\u0025\u0026\'" + + "\u0028\u0029\u002A\u002B\u002C\u002D\u002E\u002F" + + "\u0030\u0031\u0032\u0033\u0034\u0035\u0036\u0037" + + "\u0038\u0039\u003A\u003B\u003C\u003D\u003E\u003F" + + "\u0040\u0041\u0042\u0043\u0044\u0045\u0046\u0047" + + "\u0048\u0049\u004A\u004B\u004C\u004D\u004E\u004F" + + "\u0050\u0051\u0052\u0053\u0054\u0055\u0056\u0057" + + "\u0058\u0059\u005A\u005B\\\u005D\u005E\u005F" + + "\u0060\u0061\u0062\u0063\u0064\u0065\u0066\u0067" + + "\u0068\u0069\u006A\u006B\u006C\u006D\u006E\u006F" + + "\u0070\u0071\u0072\u0073\u0074\u0075\u0076\u0077" + + "\u0078\u0079\u007A\u007B\u007C\u007D\u007E\u007F" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u00A0\u00A1\u00A2\u00A3\u00A4\u00A5\u00A6\u00A7" + + "\u00A8\u00A9\u00AA\u00AB\u00AC\u00AD\u00AE\u00AF" + + "\u00B0\u00B1\u00B2\u00B3\u00B4\u00B5\u00B6\u00B7" + + "\u00B8\u00B9\u00BA\u00BB\u00BC\u00BD\u00BE\u00BF" + + "\u00C0\u00C1\u00C2\u00C3\u00C4\u00C5\u00C6\u00C7" + + "\u00C8\u00C9\u00CA\u00CB\u00CC\u00CD\u00CE\u00CF" + + "\u00D0\u00D1\u00D2\u00D3\u00D4\u00D5\u00D6\u00D7" + + "\u00D8\u00D9\u00DA\u00DB\u00DC\u00DD\u00DE\u00DF" + + "\u00E0\u00E1\u00E2\u00E3\u00E4\u00E5\u00E6\u00E7" + + "\u00E8\u00E9\u00EA\u00EB\u00EC\u00ED\u00EE\u00EF" + + "\u00F0\u00F1\u00F2\u00F3\u00F4\u00F5\u00F6\u00F7" + + "\u00F8\u00F9\u00FA\u00FB\u00FC\u00FD\u00FE\u00FF" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u008C\u009C\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u008A\u009A\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u009F\u0000\u0000\u0000\u0000\u008E\u009E\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0083\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0088\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0098\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0096\u0097\u0000" + + "\u0000\u0000\u0091\u0092\u0082\u0000\u0093\u0094" + + "\u0084\u0000\u0086\u0087\u0095\u0000\u0000\u0000" + + "\u0085\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0089\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u008B\u009B\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0080\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0099\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000"; + + private final static short index1[] = { + 0, 256, 461, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, + 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, + 698, 920, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, + 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, + 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, + 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, + 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, + 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, + 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, + 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, + 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, + 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, + 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, + 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, + 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, + 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, + }; + + public boolean canEncode(char c) { + char test = index2.charAt( index1[(c&0xFF00)>>8] + (c&0xFF) ); + return test!=0; + } + +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/util/SingleByteEncoder.java b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/util/SingleByteEncoder.java new file mode 100644 index 00000000000..b3a4ec56a4a --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/util/SingleByteEncoder.java @@ -0,0 +1,159 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @(#)SingleByteEncoder.java 1.14 03/01/23 + */ + +package com.sun.codemodel.internal.util; + +import java.nio.ByteBuffer; +import java.nio.CharBuffer; +import java.nio.charset.Charset; +import java.nio.charset.CharsetEncoder; +import java.nio.charset.CoderResult; + +import sun.nio.cs.Surrogate; + + +abstract class SingleByteEncoder + extends CharsetEncoder +{ + + private final short index1[]; + private final String index2; + private final int mask1; + private final int mask2; + private final int shift; + + private final Surrogate.Parser sgp = new Surrogate.Parser(); + + protected SingleByteEncoder(Charset cs, + short[] index1, String index2, + int mask1, int mask2, int shift) + { + super(cs, 1.0f, 1.0f); + this.index1 = index1; + this.index2 = index2; + this.mask1 = mask1; + this.mask2 = mask2; + this.shift = shift; + } + + public boolean canEncode(char c) { + char testEncode; + testEncode = index2.charAt(index1[(c & mask1) >> shift] + + (c & mask2)); + if (testEncode == '\u0000') + return false; + else + return true; + } + + private CoderResult encodeArrayLoop(CharBuffer src, ByteBuffer dst) { + char[] sa = src.array(); + int sp = src.arrayOffset() + src.position(); + int sl = src.arrayOffset() + src.limit(); + sp = (sp <= sl ? sp : sl); + byte[] da = dst.array(); + int dp = dst.arrayOffset() + dst.position(); + int dl = dst.arrayOffset() + dst.limit(); + dp = (dp <= dl ? dp : dl); + + try { + while (sp < sl) { + char c = sa[sp]; + if (Surrogate.is(c)) { + if (sgp.parse(c, sa, sp, sl) < 0) + return sgp.error(); + return sgp.unmappableResult(); + } + if (c >= '\uFFFE') + return CoderResult.unmappableForLength(1); + if (dl - dp < 1) + return CoderResult.OVERFLOW; + + char e = index2.charAt(index1[(c & mask1) >> shift] + + (c & mask2)); + + // If output byte is zero because input char is zero + // then character is mappable, o.w. fail + if (e == '\u0000' && c != '\u0000') + return CoderResult.unmappableForLength(1); + + sp++; + da[dp++] = (byte)e; + } + return CoderResult.UNDERFLOW; + } finally { + src.position(sp - src.arrayOffset()); + dst.position(dp - dst.arrayOffset()); + } + } + + private CoderResult encodeBufferLoop(CharBuffer src, ByteBuffer dst) { + int mark = src.position(); + try { + while (src.hasRemaining()) { + char c = src.get(); + if (Surrogate.is(c)) { + if (sgp.parse(c, src) < 0) + return sgp.error(); + return sgp.unmappableResult(); + } + if (c >= '\uFFFE') + return CoderResult.unmappableForLength(1); + if (!dst.hasRemaining()) + return CoderResult.OVERFLOW; + + char e = index2.charAt(index1[(c & mask1) >> shift] + + (c & mask2)); + + // If output byte is zero because input char is zero + // then character is mappable, o.w. fail + if (e == '\u0000' && c != '\u0000') + return CoderResult.unmappableForLength(1); + + mark++; + dst.put((byte)e); + } + return CoderResult.UNDERFLOW; + } finally { + src.position(mark); + } + } + + protected CoderResult encodeLoop(CharBuffer src, ByteBuffer dst) { + if (true && src.hasArray() && dst.hasArray()) + return encodeArrayLoop(src, dst); + else + return encodeBufferLoop(src, dst); + } + + public byte encode(char inputChar) { + return (byte)index2.charAt(index1[(inputChar & mask1) >> shift] + + (inputChar & mask2)); + } +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/util/Surrogate.java b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/util/Surrogate.java new file mode 100644 index 00000000000..955340b4a38 --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/util/Surrogate.java @@ -0,0 +1,355 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.codemodel.internal.util; + +import java.nio.CharBuffer; +import java.nio.charset.CoderResult; + + +/** + * Utility class for dealing with surrogates. + * + * @author Mark Reinhold + * @version 1.11, 03/01/23 + */ + +class Surrogate { + + private Surrogate() { } + + // UTF-16 surrogate-character ranges + // + public static final char MIN_HIGH = '\uD800'; + public static final char MAX_HIGH = '\uDBFF'; + public static final char MIN_LOW = '\uDC00'; + public static final char MAX_LOW = '\uDFFF'; + public static final char MIN = MIN_HIGH; + public static final char MAX = MAX_LOW; + + // Range of UCS-4 values that need surrogates in UTF-16 + // + public static final int UCS4_MIN = 0x10000; + public static final int UCS4_MAX = (1 << 20) + UCS4_MIN - 1; + + /** + * Tells whether or not the given UTF-16 value is a high surrogate. + */ + public static boolean isHigh(int c) { + return (MIN_HIGH <= c) && (c <= MAX_HIGH); + } + + /** + * Tells whether or not the given UTF-16 value is a low surrogate. + */ + public static boolean isLow(int c) { + return (MIN_LOW <= c) && (c <= MAX_LOW); + } + + /** + * Tells whether or not the given UTF-16 value is a surrogate character, + */ + public static boolean is(int c) { + return (MIN <= c) && (c <= MAX); + } + + /** + * Tells whether or not the given UCS-4 character must be represented as a + * surrogate pair in UTF-16. + */ + public static boolean neededFor(int uc) { + return (uc >= UCS4_MIN) && (uc <= UCS4_MAX); + } + + /** + * Returns the high UTF-16 surrogate for the given UCS-4 character. + */ + public static char high(int uc) { + return (char)(0xd800 | (((uc - UCS4_MIN) >> 10) & 0x3ff)); + } + + /** + * Returns the low UTF-16 surrogate for the given UCS-4 character. + */ + public static char low(int uc) { + return (char)(0xdc00 | ((uc - UCS4_MIN) & 0x3ff)); + } + + /** + * Converts the given surrogate pair into a 32-bit UCS-4 character. + */ + public static int toUCS4(char c, char d) { + return (((c & 0x3ff) << 10) | (d & 0x3ff)) + 0x10000; + } + + /** + * Surrogate parsing support. Charset implementations may use instances of + * this class to handle the details of parsing UTF-16 surrogate pairs. + */ + public static class Parser { + + public Parser() { } + + private int character; // UCS-4 + private CoderResult error = CoderResult.UNDERFLOW; + private boolean isPair; + + /** + * Returns the UCS-4 character previously parsed. + */ + public int character() { + return character; + } + + /** + * Tells whether or not the previously-parsed UCS-4 character was + * originally represented by a surrogate pair. + */ + public boolean isPair() { + return isPair; + } + + /** + * Returns the number of UTF-16 characters consumed by the previous + * parse. + */ + public int increment() { + return isPair ? 2 : 1; + } + + /** + * If the previous parse operation detected an error, return the object + * describing that error. + */ + public CoderResult error() { + return error; + } + + /** + * Returns an unmappable-input result object, with the appropriate + * input length, for the previously-parsed character. + */ + public CoderResult unmappableResult() { + return CoderResult.unmappableForLength(isPair ? 2 : 1); + } + + /** + * Parses a UCS-4 character from the given source buffer, handling + * surrogates. + * + * @param c The first character + * @param in The source buffer, from which one more character + * will be consumed if c is a high surrogate + * + * @return Either a parsed UCS-4 character, in which case the isPair() + * and increment() methods will return meaningful values, or + * -1, in which case error() will return a descriptive result + * object + */ + public int parse(char c, CharBuffer in) { + if (isHigh(c)) { + if (!in.hasRemaining()) { + error = CoderResult.UNDERFLOW; + return -1; + } + char d = in.get(); + if (isLow(d)) { + character = toUCS4(c, d); + isPair = true; + error = null; + return character; + } + error = CoderResult.malformedForLength(1); + return -1; + } + if (isLow(c)) { + error = CoderResult.malformedForLength(1); + return -1; + } + character = c; + isPair = false; + error = null; + return character; + } + + /** + * Parses a UCS-4 character from the given source buffer, handling + * surrogates. + * + * @param c The first character + * @param ia The input array, from which one more character + * will be consumed if c is a high surrogate + * @param ip The input index + * @param il The input limit + * + * @return Either a parsed UCS-4 character, in which case the isPair() + * and increment() methods will return meaningful values, or + * -1, in which case error() will return a descriptive result + * object + */ + public int parse(char c, char[] ia, int ip, int il) { + if (isHigh(c)) { + if (il - ip < 2) { + error = CoderResult.UNDERFLOW; + return -1; + } + char d = ia[ip + 1]; + if (isLow(d)) { + character = toUCS4(c, d); + isPair = true; + error = null; + return character; + } + error = CoderResult.malformedForLength(1); + return -1; + } + if (isLow(c)) { + error = CoderResult.malformedForLength(1); + return -1; + } + character = c; + isPair = false; + error = null; + return character; + } + + } + + /** + * Surrogate generation support. Charset implementations may use instances + * of this class to handle the details of generating UTF-16 surrogate + * pairs. + */ + public static class Generator { + + public Generator() { } + + private CoderResult error = CoderResult.OVERFLOW; + + /** + * If the previous generation operation detected an error, return the + * object describing that error. + */ + public CoderResult error() { + return error; + } + + /** + * Generates one or two UTF-16 characters to represent the given UCS-4 + * character. + * + * @param uc The UCS-4 character + * @param len The number of input bytes from which the UCS-4 value + * was constructed (used when creating result objects) + * @param dst The destination buffer, to which one or two UTF-16 + * characters will be written + * + * @return Either a positive count of the number of UTF-16 characters + * written to the destination buffer, or -1, in which case + * error() will return a descriptive result object + */ + public int generate(int uc, int len, CharBuffer dst) { + if (uc <= 0xffff) { + if (is(uc)) { + error = CoderResult.malformedForLength(len); + return -1; + } + if (dst.remaining() < 1) { + error = CoderResult.OVERFLOW; + return -1; + } + dst.put((char)uc); + error = null; + return 1; + } + if (uc < UCS4_MIN) { + error = CoderResult.malformedForLength(len); + return -1; + } + if (uc <= UCS4_MAX) { + if (dst.remaining() < 2) { + error = CoderResult.OVERFLOW; + return -1; + } + dst.put(high(uc)); + dst.put(low(uc)); + error = null; + return 2; + } + error = CoderResult.unmappableForLength(len); + return -1; + } + + /** + * Generates one or two UTF-16 characters to represent the given UCS-4 + * character. + * + * @param uc The UCS-4 character + * @param len The number of input bytes from which the UCS-4 value + * was constructed (used when creating result objects) + * @param da The destination array, to which one or two UTF-16 + * characters will be written + * @param dp The destination position + * @param dl The destination limit + * + * @return Either a positive count of the number of UTF-16 characters + * written to the destination buffer, or -1, in which case + * error() will return a descriptive result object + */ + public int generate(int uc, int len, char[] da, int dp, int dl) { + if (uc <= 0xffff) { + if (is(uc)) { + error = CoderResult.malformedForLength(len); + return -1; + } + if (dl - dp < 1) { + error = CoderResult.OVERFLOW; + return -1; + } + da[dp] = (char)uc; + error = null; + return 1; + } + if (uc < UCS4_MIN) { + error = CoderResult.malformedForLength(len); + return -1; + } + if (uc <= UCS4_MAX) { + if (dl - dp < 2) { + error = CoderResult.OVERFLOW; + return -1; + } + da[dp] = high(uc); + da[dp + 1] = low(uc); + error = null; + return 2; + } + error = CoderResult.unmappableForLength(len); + return -1; + } + + } + +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/util/UnicodeEscapeWriter.java b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/util/UnicodeEscapeWriter.java new file mode 100644 index 00000000000..e223476bd3e --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/util/UnicodeEscapeWriter.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.codemodel.internal.util; + +import java.io.FilterWriter; +import java.io.IOException; +import java.io.Writer; + +/** + * {@link Writer} that escapes non US-ASCII characters into + * Java Unicode escape \\uXXXX. + * + * This process is necessary if the method names or field names + * contain non US-ASCII characters. + * + * @author + * Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com) + */ +public class UnicodeEscapeWriter extends FilterWriter { + + public UnicodeEscapeWriter( Writer next ) { + super(next); + } + + public final void write(int ch) throws IOException { + if(!requireEscaping(ch)) out.write(ch); + else { + // need to escape + out.write("\\u"); + String s = Integer.toHexString(ch); + for( int i=s.length(); i<4; i++ ) + out.write('0'); + out.write(s); + } + } + + /** + * Can be overrided. Return true if the character + * needs to be escaped. + */ + protected boolean requireEscaping(int ch) { + if(ch>=128) return true; + + // control characters + if( ch<0x20 && " \t\r\n".indexOf(ch)==-1 ) return true; + + return false; + } + + public final void write(char[] buf, int off, int len) throws IOException { + for( int i=0; i readonlyFiles = new HashSet(); + + public FileCodeWriter( File target ) throws IOException { + this(target,false); + } + + public FileCodeWriter( File target, String encoding ) throws IOException { + this(target,false, encoding); + } + + public FileCodeWriter( File target, boolean readOnly ) throws IOException { + this(target, readOnly, null); + } + + public FileCodeWriter( File target, boolean readOnly, String encoding ) throws IOException { + this.target = target; + this.readOnly = readOnly; + this.encoding = encoding; + if(!target.exists() || !target.isDirectory()) + throw new IOException(target + ": non-existent directory"); + } + + public OutputStream openBinary(JPackage pkg, String fileName) throws IOException { + return new FileOutputStream(getFile(pkg,fileName)); + } + + protected File getFile(JPackage pkg, String fileName ) throws IOException { + File dir; + if(pkg.isUnnamed()) + dir = target; + else + dir = new File(target, toDirName(pkg)); + + if(!dir.exists()) dir.mkdirs(); + + File fn = new File(dir,fileName); + + if (fn.exists()) { + if (!fn.delete()) + throw new IOException(fn + ": Can't delete previous version"); + } + + + if(readOnly) readonlyFiles.add(fn); + return fn; + } + + public void close() throws IOException { + // mark files as read-onnly if necessary + for (File f : readonlyFiles) + f.setReadOnly(); + } + + /** Converts a package name to the directory name. */ + private static String toDirName( JPackage pkg ) { + return pkg.name().replace('.',File.separatorChar); + } + +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/writer/FilterCodeWriter.java b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/writer/FilterCodeWriter.java new file mode 100644 index 00000000000..20c57581392 --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/writer/FilterCodeWriter.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.codemodel.internal.writer; + +import java.io.OutputStream; +import java.io.IOException; +import java.io.Writer; + +import com.sun.codemodel.internal.CodeWriter; +import com.sun.codemodel.internal.JPackage; + +/** + * {@link CodeWriter} that delegates to another {@link CodeWriter}. + * + * @author Kohsuke Kawaguchi + */ +public class FilterCodeWriter extends CodeWriter { + protected CodeWriter core; + + public FilterCodeWriter(CodeWriter core) { + this.core = core; + } + + public OutputStream openBinary( JPackage pkg, String fileName ) throws IOException { + return core.openBinary(pkg, fileName); + } + + public Writer openSource( JPackage pkg, String fileName ) throws IOException { + return core.openSource(pkg, fileName); + } + + public void close() throws IOException { + core.close(); + } +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/writer/ProgressCodeWriter.java b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/writer/ProgressCodeWriter.java new file mode 100644 index 00000000000..abb40de0a66 --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/writer/ProgressCodeWriter.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.codemodel.internal.writer; + +import java.io.File; +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintStream; +import java.io.Writer; + +import com.sun.codemodel.internal.CodeWriter; +import com.sun.codemodel.internal.JPackage; + +/** + * Filter CodeWriter that writes a progress message to the specified + * PrintStream. + * + * @author + * Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com) + */ +public class ProgressCodeWriter extends FilterCodeWriter { + public ProgressCodeWriter( CodeWriter output, PrintStream progress ) { + super(output); + this.progress = progress; + if(progress==null) + throw new IllegalArgumentException(); + } + + private final PrintStream progress; + + public OutputStream openBinary(JPackage pkg, String fileName) throws IOException { + report(pkg, fileName); + return super.openBinary(pkg,fileName); + } + + public Writer openSource(JPackage pkg, String fileName) throws IOException { + report(pkg, fileName); + return super.openSource(pkg,fileName); + } + + private void report(JPackage pkg, String fileName) { + if(pkg.isUnnamed()) progress.println(fileName); + else + progress.println( + pkg.name().replace('.',File.separatorChar) + +File.separatorChar+fileName); + } + +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/writer/PrologCodeWriter.java b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/writer/PrologCodeWriter.java new file mode 100644 index 00000000000..9ea213728c0 --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/writer/PrologCodeWriter.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.codemodel.internal.writer; + +import java.io.IOException; +import java.io.PrintWriter; +import java.io.Writer; + +import com.sun.codemodel.internal.CodeWriter; +import com.sun.codemodel.internal.JPackage; + +/** + * Writes all the source files under the specified file folder and + * inserts a file prolog comment in each java source file. + * + * @author + * Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com) + */ +public class PrologCodeWriter extends FilterCodeWriter { + + /** prolog comment */ + private final String prolog; + + /** + * @param core + * This CodeWriter will be used to actually create a storage for files. + * PrologCodeWriter simply decorates this underlying CodeWriter by + * adding prolog comments. + * @param prolog + * Strings that will be added as comments. + * This string may contain newlines to produce multi-line comments. + * '//' will be inserted at the beginning of each line to make it + * a valid Java comment, so the caller can just pass strings like + * "abc\ndef" + */ + public PrologCodeWriter( CodeWriter core, String prolog ) { + super(core); + this.prolog = prolog; + } + + + public Writer openSource(JPackage pkg, String fileName) throws IOException { + Writer w = super.openSource(pkg,fileName); + + PrintWriter out = new PrintWriter(w); + + // write prolog if this is a java source file + if( prolog != null ) { + out.println( "//" ); + + String s = prolog; + int idx; + while( (idx=s.indexOf('\n'))!=-1 ) { + out.println("// "+ s.substring(0,idx) ); + s = s.substring(idx+1); + } + out.println("//"); + out.println(); + } + out.flush(); // we can't close the stream for that would close the undelying stream. + + return w; + } +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/writer/SingleStreamCodeWriter.java b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/writer/SingleStreamCodeWriter.java new file mode 100644 index 00000000000..7901a376df4 --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/writer/SingleStreamCodeWriter.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.codemodel.internal.writer; + +import java.io.FilterOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintStream; + +import com.sun.codemodel.internal.CodeWriter; +import com.sun.codemodel.internal.JPackage; + +/** + * Output all source files into a single stream with a little + * formatting header in front of each file. + * + * This is primarily for human consumption of the generated source + * code, such as to debug/test CodeModel or to quickly inspect the result. + * + * @author + * Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com) + */ +public class SingleStreamCodeWriter extends CodeWriter { + + private final PrintStream out; + + /** + * @param os + * This stream will be closed at the end of the code generation. + */ + public SingleStreamCodeWriter( OutputStream os ) { + out = new PrintStream(os); + } + + public OutputStream openBinary(JPackage pkg, String fileName) throws IOException { + String pkgName = pkg.name(); + if(pkgName.length()!=0) pkgName += '.'; + + out.println( + "-----------------------------------" + pkgName+fileName + + "-----------------------------------"); + + return new FilterOutputStream(out) { + public void close() { + // don't let this stream close + } + }; + } + + public void close() throws IOException { + out.close(); + } + +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/writer/ZipCodeWriter.java b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/writer/ZipCodeWriter.java new file mode 100644 index 00000000000..13cc1adfcfb --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/codemodel/internal/writer/ZipCodeWriter.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.codemodel.internal.writer; + +import java.io.FilterOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; + +import com.sun.codemodel.internal.CodeWriter; +import com.sun.codemodel.internal.JPackage; + +/** + * Writes all the files into a zip file. + * + * @author + * Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com) + */ +public class ZipCodeWriter extends CodeWriter { + /** + * @param target + * Zip file will be written to this stream. + */ + public ZipCodeWriter( OutputStream target ) { + zip = new ZipOutputStream(target); + // nullify the close method. + filter = new FilterOutputStream(zip){ + public void close() {} + }; + } + + private final ZipOutputStream zip; + + private final OutputStream filter; + + public OutputStream openBinary(JPackage pkg, String fileName) throws IOException { + String name = fileName; + if(!pkg.isUnnamed()) name = toDirName(pkg)+name; + + zip.putNextEntry(new ZipEntry(name)); + return filter; + } + + /** Converts a package name to the directory name. */ + private static String toDirName( JPackage pkg ) { + return pkg.name().replace('.','/')+'/'; + } + + public void close() throws IOException { + zip.close(); + } + +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/istack/internal/Builder.java b/jaxws/src/share/jaxws_classes/com/sun/istack/internal/Builder.java new file mode 100644 index 00000000000..d62413afed0 --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/istack/internal/Builder.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.istack.internal; + +/** + * + * @author Martin Grebac + */ +public interface Builder { + T build(); +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/istack/internal/ByteArrayDataSource.java b/jaxws/src/share/jaxws_classes/com/sun/istack/internal/ByteArrayDataSource.java new file mode 100644 index 00000000000..c4f1e21c8da --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/istack/internal/ByteArrayDataSource.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.istack.internal; + +import javax.activation.DataSource; +import java.io.InputStream; +import java.io.ByteArrayInputStream; +import java.io.OutputStream; + +/** + * {@link DataSource} backed by a byte buffer. + * + * @author Kohsuke Kawaguchi + */ +public final class ByteArrayDataSource implements DataSource { + + private final String contentType; + private final byte[] buf; + private final int len; + + public ByteArrayDataSource(byte[] buf, String contentType) { + this(buf,buf.length,contentType); + } + public ByteArrayDataSource(byte[] buf, int length, String contentType) { + this.buf = buf; + this.len = length; + this.contentType = contentType; + } + + public String getContentType() { + if(contentType==null) + return "application/octet-stream"; + return contentType; + } + + public InputStream getInputStream() { + return new ByteArrayInputStream(buf,0,len); + } + + public String getName() { + return null; + } + + public OutputStream getOutputStream() { + throw new UnsupportedOperationException(); + } +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/istack/internal/FinalArrayList.java b/jaxws/src/share/jaxws_classes/com/sun/istack/internal/FinalArrayList.java new file mode 100644 index 00000000000..b101731dec5 --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/istack/internal/FinalArrayList.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.istack.internal; + +import java.util.ArrayList; +import java.util.Collection; + +/** + * {@link ArrayList} with the final keyword. + * + *

+ * This gives HotSpot a better hint that all methods can be inlined. + * + * @author Kohsuke Kawaguchi + */ +public final class FinalArrayList extends ArrayList { + public FinalArrayList(int initialCapacity) { + super(initialCapacity); + } + + public FinalArrayList() { + } + + public FinalArrayList(Collection ts) { + super(ts); + } +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/istack/internal/FragmentContentHandler.java b/jaxws/src/share/jaxws_classes/com/sun/istack/internal/FragmentContentHandler.java new file mode 100644 index 00000000000..50bc344ec73 --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/istack/internal/FragmentContentHandler.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.istack.internal; + +import org.xml.sax.helpers.XMLFilterImpl; +import org.xml.sax.SAXException; +import org.xml.sax.XMLReader; +import org.xml.sax.ContentHandler; + +/** + * {@link XMLFilterImpl} that masks start/end document SAX events. + * @author Kohsuke Kawaguchi + */ +public class FragmentContentHandler extends XMLFilterImpl { + public FragmentContentHandler() { + } + + public FragmentContentHandler(XMLReader parent) { + super(parent); + } + + public FragmentContentHandler(ContentHandler handler) { + super(); + setContentHandler(handler); + } + + public void startDocument() throws SAXException { + // noop + } + + public void endDocument() throws SAXException { + // noop + } +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/istack/internal/Interned.java b/jaxws/src/share/jaxws_classes/com/sun/istack/internal/Interned.java new file mode 100644 index 00000000000..a02edbab4bf --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/istack/internal/Interned.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.istack.internal; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.lang.annotation.ElementType; + +/** + * Designates that a field, return value, argument, or a variable is supposed + * to be an {@link String#intern() interned} string. + * + *

+ * In many places in the istack, we assume Strings to be interned for + * the performance reason. Similarly, In many other places, we don't + * make such an assumption for the performance reason (because intern + * isn't free.) + * + *

+ * Therefore, distinguishing which part is supposed to be interned and + * which part is supposed to be not is important. This annotation + * allows us to capture that in the code. + * + * @author Kohsuke Kawaguchi + */ +@Documented +@Retention(RetentionPolicy.CLASS) +@Target({ElementType.FIELD,ElementType.METHOD,ElementType.PARAMETER,ElementType.LOCAL_VARIABLE}) +public @interface Interned { +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/istack/internal/NotNull.java b/jaxws/src/share/jaxws_classes/com/sun/istack/internal/NotNull.java new file mode 100644 index 00000000000..77c46d435cf --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/istack/internal/NotNull.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.istack.internal; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.lang.annotation.ElementType; + +/** + * Designates that a field, return value, argument, or a variable is guaranteed to be non-null. + * + * @author Kohsuke Kawaguchi + */ +@Documented +@Retention(RetentionPolicy.CLASS) +@Target({ElementType.FIELD,ElementType.METHOD,ElementType.PARAMETER,ElementType.LOCAL_VARIABLE}) +public @interface NotNull { +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/istack/internal/Nullable.java b/jaxws/src/share/jaxws_classes/com/sun/istack/internal/Nullable.java new file mode 100644 index 00000000000..a482f405e89 --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/istack/internal/Nullable.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.istack.internal; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.lang.annotation.ElementType; + +/** + * Designates that a field, return value, argument, or a variable may be null. + * + * @author Kohsuke Kawaguchi + */ +@Documented +@Retention(RetentionPolicy.CLASS) +@Target({ElementType.FIELD,ElementType.METHOD,ElementType.PARAMETER,ElementType.LOCAL_VARIABLE}) +public @interface Nullable { +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/istack/internal/Pool.java b/jaxws/src/share/jaxws_classes/com/sun/istack/internal/Pool.java new file mode 100644 index 00000000000..c8e825b415e --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/istack/internal/Pool.java @@ -0,0 +1,116 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.istack.internal; + +import java.util.concurrent.ConcurrentLinkedQueue; +import java.lang.ref.WeakReference; + +/** + * Pool of reusable objects that are indistinguishable from each other, + * such as JAXB marshallers. + * + * @author Kohsuke Kawaguchi + */ +public interface Pool { + + /** + * Gets a new object from the pool. + * + *

+ * If no object is available in the pool, this method creates a new one. + */ + @NotNull T take(); + + /** + * Returns an object back to the pool. + */ + void recycle(@NotNull T t); + + /** + * Default implementation that uses {@link ConcurrentLinkedQueue} + * as the data store. + * + *

Note for Implementors

+ *

+ * Don't rely on the fact that this class extends from {@link ConcurrentLinkedQueue}. + */ + public abstract class Impl implements Pool { + + private volatile WeakReference> queue; + + /** + * Gets a new object from the pool. + * + *

+ * If no object is available in the pool, this method creates a new one. + * + * @return + * always non-null. + */ + public final @NotNull T take() { + T t = getQueue().poll(); + if(t==null) { + return create(); + } + return t; + } + + /** + * Returns an object back to the pool. + */ + public final void recycle(T t) { + getQueue().offer(t); + } + + private ConcurrentLinkedQueue getQueue() { + WeakReference> q = queue; + if (q != null) { + ConcurrentLinkedQueue d = q.get(); + if (d != null) { + return d; + } + } + // overwrite the queue + ConcurrentLinkedQueue d = new ConcurrentLinkedQueue(); + queue = new WeakReference>(d); + + return d; + } + + /** + * Creates a new instance of object. + * + *

+ * This method is used when someone wants to + * {@link #take() take} an object from an empty pool. + * + *

+ * Also note that multiple threads may call this method + * concurrently. + */ + protected abstract @NotNull T create(); + } +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/istack/internal/SAXException2.java b/jaxws/src/share/jaxws_classes/com/sun/istack/internal/SAXException2.java new file mode 100644 index 00000000000..025e2530e00 --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/istack/internal/SAXException2.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.istack.internal; + +import org.xml.sax.SAXException; + +/** + * {@link SAXException} that handles exception chaining correctly. + * + * @author Kohsuke Kawaguchi + * @since 2.0 FCS + */ +public class SAXException2 extends SAXException { + public SAXException2(String message) { + super(message); + } + + public SAXException2(Exception e) { + super(e); + } + + public SAXException2(String message, Exception e) { + super(message, e); + } + + public Throwable getCause() { + return getException(); + } +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/istack/internal/SAXParseException2.java b/jaxws/src/share/jaxws_classes/com/sun/istack/internal/SAXParseException2.java new file mode 100644 index 00000000000..d51daf9dcc9 --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/istack/internal/SAXParseException2.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.istack.internal; + +import org.xml.sax.SAXParseException; +import org.xml.sax.Locator; + +/** + * {@link SAXParseException} that handles exception chaining correctly. + * + * @author Kohsuke Kawaguchi + * @since 2.0 FCS + */ +public class SAXParseException2 extends SAXParseException { + public SAXParseException2(String message, Locator locator) { + super(message, locator); + } + + public SAXParseException2(String message, Locator locator, Exception e) { + super(message, locator, e); + } + + public SAXParseException2(String message, String publicId, String systemId, int lineNumber, int columnNumber) { + super(message, publicId, systemId, lineNumber, columnNumber); + } + + public SAXParseException2(String message, String publicId, String systemId, int lineNumber, int columnNumber, Exception e) { + super(message, publicId, systemId, lineNumber, columnNumber, e); + } + + public Throwable getCause() { + return getException(); + } +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/istack/internal/XMLStreamException2.java b/jaxws/src/share/jaxws_classes/com/sun/istack/internal/XMLStreamException2.java new file mode 100644 index 00000000000..ace5d2a5e13 --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/istack/internal/XMLStreamException2.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.istack.internal; + +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.Location; + +/** + * {@link XMLStreamException} that properly handles exception chaining. + * + * @author Kohsuke Kawaguchi + */ +public class XMLStreamException2 extends XMLStreamException { + public XMLStreamException2(String msg) { + super(msg); + } + + public XMLStreamException2(Throwable th) { + super(th); + } + + public XMLStreamException2(String msg, Throwable th) { + super(msg, th); + } + + public XMLStreamException2(String msg, Location location) { + super(msg, location); + } + + public XMLStreamException2(String msg, Location location, Throwable th) { + super(msg, location, th); + } + + /** + * {@link XMLStreamException} doesn't return the correct cause. + */ + public Throwable getCause() { + return getNestedException(); + } +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/istack/internal/XMLStreamReaderToContentHandler.java b/jaxws/src/share/jaxws_classes/com/sun/istack/internal/XMLStreamReaderToContentHandler.java new file mode 100644 index 00000000000..ad2ad91ca03 --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/istack/internal/XMLStreamReaderToContentHandler.java @@ -0,0 +1,388 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.istack.internal; + +import org.xml.sax.ContentHandler; +import org.xml.sax.SAXException; +import org.xml.sax.Locator; +import org.xml.sax.Attributes; +import org.xml.sax.helpers.AttributesImpl; + +import javax.xml.stream.XMLStreamReader; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamConstants; +import javax.xml.namespace.QName; + +/** + * This is a simple utility class that adapts StAX events from an + * {@link XMLStreamReader} to SAX events on a + * {@link ContentHandler}, bridging between the two + * parser technologies. + * + * @author Ryan.Shoemaker@Sun.COM + * @version 1.0 + */ +public class XMLStreamReaderToContentHandler { + + // StAX event source + private final XMLStreamReader staxStreamReader; + + // SAX event sink + private final ContentHandler saxHandler; + + // if true, when the conversion is completed, leave the cursor to the last + // event that was fired (such as end element) + private final boolean eagerQuit; + + /** + * If true, not start/endDocument event. + */ + private final boolean fragment; + + // array of the even length of the form { prefix0, uri0, prefix1, uri1, ... } + private final String[] inscopeNamespaces; + + /** + * @see #XMLStreamReaderToContentHandler(XMLStreamReader, ContentHandler, boolean, boolean, String[]) + */ + public XMLStreamReaderToContentHandler(XMLStreamReader staxCore, ContentHandler saxCore, boolean eagerQuit, boolean fragment) { + this(staxCore, saxCore, eagerQuit, fragment, new String[0]); + } + + /** + * Construct a new StAX to SAX adapter that will convert a StAX event + * stream into a SAX event stream. + * + * @param staxCore + * StAX event source + * @param saxCore + * SAXevent sink + * @param eagerQuit + * @param fragment + * @param inscopeNamespaces + * array of the even length of the form { prefix0, uri0, prefix1, uri1, ... } + */ + public XMLStreamReaderToContentHandler(XMLStreamReader staxCore, ContentHandler saxCore, + boolean eagerQuit, boolean fragment, String[] inscopeNamespaces) { + this.staxStreamReader = staxCore; + this.saxHandler = saxCore; + this.eagerQuit = eagerQuit; + this.fragment = fragment; + this.inscopeNamespaces = inscopeNamespaces; + assert inscopeNamespaces.length%2 == 0; + } + + + /* + * @see StAXReaderToContentHandler#bridge() + */ + public void bridge() throws XMLStreamException { + + try { + // remembers the nest level of elements to know when we are done. + int depth=0; + + // if the parser is at the start tag, proceed to the first element + int event = staxStreamReader.getEventType(); + if(event == XMLStreamConstants.START_DOCUMENT) { + // nextTag doesn't correctly handle DTDs + while( !staxStreamReader.isStartElement() ) + event = staxStreamReader.next(); + } + + + if( event!=XMLStreamConstants.START_ELEMENT) + throw new IllegalStateException("The current event is not START_ELEMENT\n but " + event); + + handleStartDocument(); + + for(int i=0; i < inscopeNamespaces.length; i+=2) { + saxHandler.startPrefixMapping(inscopeNamespaces[i], inscopeNamespaces[i+1]); + } + + OUTER: + do { + // These are all of the events listed in the javadoc for + // XMLEvent. + // The spec only really describes 11 of them. + switch (event) { + case XMLStreamConstants.START_ELEMENT : + depth++; + handleStartElement(); + break; + case XMLStreamConstants.END_ELEMENT : + handleEndElement(); + depth--; + if(depth==0 && eagerQuit) + break OUTER; + break; + case XMLStreamConstants.CHARACTERS : + handleCharacters(); + break; + case XMLStreamConstants.ENTITY_REFERENCE : + handleEntityReference(); + break; + case XMLStreamConstants.PROCESSING_INSTRUCTION : + handlePI(); + break; + case XMLStreamConstants.COMMENT : + handleComment(); + break; + case XMLStreamConstants.DTD : + handleDTD(); + break; + case XMLStreamConstants.ATTRIBUTE : + handleAttribute(); + break; + case XMLStreamConstants.NAMESPACE : + handleNamespace(); + break; + case XMLStreamConstants.CDATA : + handleCDATA(); + break; + case XMLStreamConstants.ENTITY_DECLARATION : + handleEntityDecl(); + break; + case XMLStreamConstants.NOTATION_DECLARATION : + handleNotationDecl(); + break; + case XMLStreamConstants.SPACE : + handleSpace(); + break; + default : + throw new InternalError("processing event: " + event); + } + + event=staxStreamReader.next(); + } while (depth!=0); + + for(int i=0; i < inscopeNamespaces.length; i+=2) { + saxHandler.endPrefixMapping(inscopeNamespaces[i]); + } + + handleEndDocument(); + } catch (SAXException e) { + throw new XMLStreamException2(e); + } + } + + private void handleEndDocument() throws SAXException { + if(fragment) + return; + + saxHandler.endDocument(); + } + + private void handleStartDocument() throws SAXException { + if(fragment) + return; + + saxHandler.setDocumentLocator(new Locator() { + public int getColumnNumber() { + return staxStreamReader.getLocation().getColumnNumber(); + } + public int getLineNumber() { + return staxStreamReader.getLocation().getLineNumber(); + } + public String getPublicId() { + return staxStreamReader.getLocation().getPublicId(); + } + public String getSystemId() { + return staxStreamReader.getLocation().getSystemId(); + } + }); + saxHandler.startDocument(); + } + + private void handlePI() throws XMLStreamException { + try { + saxHandler.processingInstruction( + staxStreamReader.getPITarget(), + staxStreamReader.getPIData()); + } catch (SAXException e) { + throw new XMLStreamException2(e); + } + } + + private void handleCharacters() throws XMLStreamException { + try { + saxHandler.characters( + staxStreamReader.getTextCharacters(), + staxStreamReader.getTextStart(), + staxStreamReader.getTextLength() ); + } catch (SAXException e) { + throw new XMLStreamException2(e); + } + } + + private void handleEndElement() throws XMLStreamException { + QName qName = staxStreamReader.getName(); + + try { + String pfix = qName.getPrefix(); + String rawname = (pfix == null || pfix.length() == 0) + ? qName.getLocalPart() + : pfix + ':' + qName.getLocalPart(); + // fire endElement + saxHandler.endElement( + qName.getNamespaceURI(), + qName.getLocalPart(), + rawname); + + // end namespace bindings + int nsCount = staxStreamReader.getNamespaceCount(); + for (int i = nsCount - 1; i >= 0; i--) { + String prefix = staxStreamReader.getNamespacePrefix(i); + if (prefix == null) { // true for default namespace + prefix = ""; + } + saxHandler.endPrefixMapping(prefix); + } + } catch (SAXException e) { + throw new XMLStreamException2(e); + } + } + + private void handleStartElement() throws XMLStreamException { + + try { + // start namespace bindings + int nsCount = staxStreamReader.getNamespaceCount(); + for (int i = 0; i < nsCount; i++) { + saxHandler.startPrefixMapping( + fixNull(staxStreamReader.getNamespacePrefix(i)), + fixNull(staxStreamReader.getNamespaceURI(i))); + } + + // fire startElement + QName qName = staxStreamReader.getName(); + String prefix = qName.getPrefix(); + String rawname; + if(prefix==null || prefix.length()==0) + rawname = qName.getLocalPart(); + else + rawname = prefix + ':' + qName.getLocalPart(); + Attributes attrs = getAttributes(); + saxHandler.startElement( + qName.getNamespaceURI(), + qName.getLocalPart(), + rawname, + attrs); + } catch (SAXException e) { + throw new XMLStreamException2(e); + } + } + + private static String fixNull(String s) { + if(s==null) return ""; + else return s; + } + + /** + * Get the attributes associated with the given START_ELEMENT or ATTRIBUTE + * StAXevent. + * + * @return the StAX attributes converted to an org.xml.sax.Attributes + */ + private Attributes getAttributes() { + AttributesImpl attrs = new AttributesImpl(); + + int eventType = staxStreamReader.getEventType(); + if (eventType != XMLStreamConstants.ATTRIBUTE + && eventType != XMLStreamConstants.START_ELEMENT) { + throw new InternalError( + "getAttributes() attempting to process: " + eventType); + } + + // in SAX, namespace declarations are not part of attributes by default. + // (there's a property to control that, but as far as we are concerned + // we don't use it.) So don't add xmlns:* to attributes. + + // gather non-namespace attrs + for (int i = 0; i < staxStreamReader.getAttributeCount(); i++) { + String uri = staxStreamReader.getAttributeNamespace(i); + if(uri==null) uri=""; + String localName = staxStreamReader.getAttributeLocalName(i); + String prefix = staxStreamReader.getAttributePrefix(i); + String qName; + if(prefix==null || prefix.length()==0) + qName = localName; + else + qName = prefix + ':' + localName; + String type = staxStreamReader.getAttributeType(i); + String value = staxStreamReader.getAttributeValue(i); + + attrs.addAttribute(uri, localName, qName, type, value); + } + + return attrs; + } + + private void handleNamespace() { + // no-op ??? + // namespace events don't normally occur outside of a startElement + // or endElement + } + + private void handleAttribute() { + // no-op ??? + // attribute events don't normally occur outside of a startElement + // or endElement + } + + private void handleDTD() { + // no-op ??? + // it seems like we need to pass this info along, but how? + } + + private void handleComment() { + // no-op ??? + } + + private void handleEntityReference() { + // no-op ??? + } + + private void handleSpace() { + // no-op ??? + // this event is listed in the javadoc, but not in the spec. + } + + private void handleNotationDecl() { + // no-op ??? + // this event is listed in the javadoc, but not in the spec. + } + + private void handleEntityDecl() { + // no-op ??? + // this event is listed in the javadoc, but not in the spec. + } + + private void handleCDATA() { + // no-op ??? + // this event is listed in the javadoc, but not in the spec. + } +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/istack/internal/localization/Localizable.java b/jaxws/src/share/jaxws_classes/com/sun/istack/internal/localization/Localizable.java new file mode 100644 index 00000000000..79eeba20cc6 --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/istack/internal/localization/Localizable.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.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. + * + *

+ * Use of "new" is to create an unique instance. + */ + public static final String NOT_LOCALIZABLE = new String("\u0000"); +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/istack/internal/localization/LocalizableMessage.java b/jaxws/src/share/jaxws_classes/com/sun/istack/internal/localization/LocalizableMessage.java new file mode 100644 index 00000000000..95a6f6ca6d4 --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/istack/internal/localization/LocalizableMessage.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.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; + } +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/istack/internal/localization/LocalizableMessageFactory.java b/jaxws/src/share/jaxws_classes/com/sun/istack/internal/localization/LocalizableMessageFactory.java new file mode 100644 index 00000000000..7cc7b5f236a --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/istack/internal/localization/LocalizableMessageFactory.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.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); + } + +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/istack/internal/localization/Localizer.java b/jaxws/src/share/jaxws_classes/com/sun/istack/internal/localization/Localizer.java new file mode 100644 index 00000000000..c3c932143ec --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/istack/internal/localization/Localizer.java @@ -0,0 +1,149 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.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(); + } + +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/istack/internal/logging/Logger.java b/jaxws/src/share/jaxws_classes/com/sun/istack/internal/logging/Logger.java new file mode 100644 index 00000000000..2c00143e611 --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/istack/internal/logging/Logger.java @@ -0,0 +1,459 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.istack.internal.logging; + +import com.sun.istack.internal.NotNull; + +import java.util.StringTokenizer; +import java.util.logging.Level; + +/** + * This is a helper class that provides some conveniece methods wrapped around the + * standard {@link java.util.logging.Logger} interface. + * + * The class also makes sure that logger names of each Metro subsystem are consistent + * with each other. + * + * @author Marek Potociar + * @author Fabian Ritzmann + */ +public class Logger { + + private static final String WS_LOGGING_SUBSYSTEM_NAME_ROOT = "com.sun.metro"; + private static final String ROOT_WS_PACKAGE = "com.sun.xml.internal.ws."; + // + private static final Level METHOD_CALL_LEVEL_VALUE = Level.FINEST; + // + private final String componentClassName; + private final java.util.logging.Logger logger; + + /** + * Prevents creation of a new instance of this Logger unless used by a subclass. + */ + protected Logger(final String systemLoggerName, final String componentName) { + this.componentClassName = "[" + componentName + "] "; + this.logger = java.util.logging.Logger.getLogger(systemLoggerName); + } + + /** + *

+ * The factory method returns preconfigured Logger wrapper for the class. Method calls + * {@link #getSystemLoggerName(java.lang.Class)} to generate default logger name. + *

+ *

+ * Since there is no caching implemented, it is advised that the method is called only once + * per a class in order to initialize a final static logger variable, which is then used + * through the class to perform actual logging tasks. + *

+ * + * @param componentClass class of the component that will use the logger instance. Must not be {@code null}. + * @return logger instance preconfigured for use with the component + * @throws NullPointerException if the componentClass parameter is {@code null}. + */ + public static @NotNull Logger getLogger(final @NotNull Class componentClass) { + return new Logger(getSystemLoggerName(componentClass), componentClass.getName()); + } + + /** + * The factory method returns preconfigured Logger wrapper for the class. Since there is no caching implemented, + * it is advised that the method is called only once per a class in order to initialize a final static logger variable, + * which is then used through the class to perform actual logging tasks. + * + * This method should be only used in a special cases when overriding of a default logger name derived from the + * package of the component class is needed. For all common use cases please use {@link #getLogger(java.lang.Class)} + * method. + * + * @param customLoggerName custom name of the logger. + * @param componentClass class of the component that will use the logger instance. Must not be {@code null}. + * @return logger instance preconfigured for use with the component + * @throws NullPointerException if the componentClass parameter is {@code null}. + * + * @see #getLogger(java.lang.Class) + */ + public static @NotNull Logger getLogger(final @NotNull String customLoggerName, final @NotNull Class componentClass) { + return new Logger(customLoggerName, componentClass.getName()); + } + + /** + * Calculates the subsystem suffix based on the package of the component class + * @param componentClass class of the component that will use the logger instance. Must not be {@code null}. + * @return system logger name for the given {@code componentClass} instance + */ + static final String getSystemLoggerName(@NotNull Class componentClass) { + StringBuilder sb = new StringBuilder(componentClass.getPackage().getName()); + final int lastIndexOfWsPackage = sb.lastIndexOf(ROOT_WS_PACKAGE); + if (lastIndexOfWsPackage > -1) { + sb.replace(0, lastIndexOfWsPackage + ROOT_WS_PACKAGE.length(), ""); + + StringTokenizer st = new StringTokenizer(sb.toString(), "."); + sb = new StringBuilder(WS_LOGGING_SUBSYSTEM_NAME_ROOT).append("."); + if (st.hasMoreTokens()) { + String token = st.nextToken(); + if ("api".equals(token)) { + token = st.nextToken(); + } + sb.append(token); + } + } + + return sb.toString(); + } + + public void log(final Level level, final String message) { + if (!this.logger.isLoggable(level)) { + return; + } + logger.logp(level, componentClassName, getCallerMethodName(), message); + } + + public void log(final Level level, final String message, final Throwable thrown) { + if (!this.logger.isLoggable(level)) { + return; + } + logger.logp(level, componentClassName, getCallerMethodName(), message, thrown); + } + + public void finest(final String message) { + if (!this.logger.isLoggable(Level.FINEST)) { + return; + } + logger.logp(Level.FINEST, componentClassName, getCallerMethodName(), message); + } + + public void finest(final String message, final Throwable thrown) { + if (!this.logger.isLoggable(Level.FINEST)) { + return; + } + logger.logp(Level.FINEST, componentClassName, getCallerMethodName(), message, thrown); + } + + public void finer(final String message) { + if (!this.logger.isLoggable(Level.FINER)) { + return; + } + logger.logp(Level.FINER, componentClassName, getCallerMethodName(), message); + } + + public void finer(final String message, final Throwable thrown) { + if (!this.logger.isLoggable(Level.FINER)) { + return; + } + logger.logp(Level.FINER, componentClassName, getCallerMethodName(), message, thrown); + } + + public void fine(final String message) { + if (!this.logger.isLoggable(Level.FINE)) { + return; + } + logger.logp(Level.FINE, componentClassName, getCallerMethodName(), message); + } + + public void fine(final String message, final Throwable thrown) { + if (!this.logger.isLoggable(Level.FINE)) { + return; + } + logger.logp(Level.FINE, componentClassName, getCallerMethodName(), message, thrown); + } + + public void info(final String message) { + if (!this.logger.isLoggable(Level.INFO)) { + return; + } + logger.logp(Level.INFO, componentClassName, getCallerMethodName(), message); + } + + public void info(final String message, final Throwable thrown) { + if (!this.logger.isLoggable(Level.INFO)) { + return; + } + logger.logp(Level.INFO, componentClassName, getCallerMethodName(), message, thrown); + } + + public void config(final String message) { + if (!this.logger.isLoggable(Level.CONFIG)) { + return; + } + logger.logp(Level.CONFIG, componentClassName, getCallerMethodName(), message); + } + + public void config(final String message, final Throwable thrown) { + if (!this.logger.isLoggable(Level.CONFIG)) { + return; + } + logger.logp(Level.CONFIG, componentClassName, getCallerMethodName(), message, thrown); + } + + public void warning(final String message) { + if (!this.logger.isLoggable(Level.WARNING)) { + return; + } + logger.logp(Level.WARNING, componentClassName, getCallerMethodName(), message); + } + + public void warning(final String message, final Throwable thrown) { + if (!this.logger.isLoggable(Level.WARNING)) { + return; + } + logger.logp(Level.WARNING, componentClassName, getCallerMethodName(), message, thrown); + } + + public void severe(final String message) { + if (!this.logger.isLoggable(Level.SEVERE)) { + return; + } + logger.logp(Level.SEVERE, componentClassName, getCallerMethodName(), message); + } + + public void severe(final String message, final Throwable thrown) { + if (!this.logger.isLoggable(Level.SEVERE)) { + return; + } + logger.logp(Level.SEVERE, componentClassName, getCallerMethodName(), message, thrown); + } + + public boolean isMethodCallLoggable() { + return this.logger.isLoggable(METHOD_CALL_LEVEL_VALUE); + } + + public boolean isLoggable(final Level level) { + return this.logger.isLoggable(level); + } + + public void setLevel(final Level level) { + this.logger.setLevel(level); + } + + public void entering() { + if (!this.logger.isLoggable(METHOD_CALL_LEVEL_VALUE)) { + return; + } + + logger.entering(componentClassName, getCallerMethodName()); + } + + public void entering(final Object... parameters) { + if (!this.logger.isLoggable(METHOD_CALL_LEVEL_VALUE)) { + return; + } + + logger.entering(componentClassName, getCallerMethodName(), parameters); + } + + public void exiting() { + if (!this.logger.isLoggable(METHOD_CALL_LEVEL_VALUE)) { + return; + } + logger.exiting(componentClassName, getCallerMethodName()); + } + + public void exiting(final Object result) { + if (!this.logger.isLoggable(METHOD_CALL_LEVEL_VALUE)) { + return; + } + logger.exiting(componentClassName, getCallerMethodName(), result); + } + + /** + * Method logs {@code exception}'s message as a {@code SEVERE} logging level + * message. + *

+ * If {@code cause} parameter is not {@code null}, it is logged as well and + * {@code exception} original cause is initialized with instance referenced + * by {@code cause} parameter. + * + * @param exception exception whose message should be logged. Must not be + * {@code null}. + * @param cause initial cause of the exception that should be logged as well + * and set as {@code exception}'s original cause. May be {@code null}. + * @return the same exception instance that was passed in as the {@code exception} + * parameter. + */ + public T logSevereException(final T exception, final Throwable cause) { + if (this.logger.isLoggable(Level.SEVERE)) { + if (cause == null) { + logger.logp(Level.SEVERE, componentClassName, getCallerMethodName(), exception.getMessage()); + } else { + exception.initCause(cause); + logger.logp(Level.SEVERE, componentClassName, getCallerMethodName(), exception.getMessage(), cause); + } + } + + return exception; + } + + /** + * Method logs {@code exception}'s message as a {@code SEVERE} logging level + * message. + *

+ * If {@code logCause} parameter is {@code true}, {@code exception}'s original + * cause is logged as well (if exists). This may be used in cases when + * {@code exception}'s class provides constructor to initialize the original + * cause. In such case you do not need to use + * {@link #logSevereException(Throwable, Throwable)} + * method version but you might still want to log the original cause as well. + * + * @param exception exception whose message should be logged. Must not be + * {@code null}. + * @param logCause deterimnes whether initial cause of the exception should + * be logged as well + * @return the same exception instance that was passed in as the {@code exception} + * parameter. + */ + public T logSevereException(final T exception, final boolean logCause) { + if (this.logger.isLoggable(Level.SEVERE)) { + if (logCause && exception.getCause() != null) { + logger.logp(Level.SEVERE, componentClassName, getCallerMethodName(), exception.getMessage(), exception.getCause()); + } else { + logger.logp(Level.SEVERE, componentClassName, getCallerMethodName(), exception.getMessage()); + } + } + + return exception; + } + + /** + * Same as {@link #logSevereException(Throwable, boolean) logSevereException(exception, true)}. + */ + public T logSevereException(final T exception) { + if (this.logger.isLoggable(Level.SEVERE)) { + if (exception.getCause() == null) { + logger.logp(Level.SEVERE, componentClassName, getCallerMethodName(), exception.getMessage()); + } else { + logger.logp(Level.SEVERE, componentClassName, getCallerMethodName(), exception.getMessage(), exception.getCause()); + } + } + + return exception; + } + + /** + * Method logs {@code exception}'s message at the logging level specified by the + * {@code level} argument. + *

+ * If {@code cause} parameter is not {@code null}, it is logged as well and + * {@code exception} original cause is initialized with instance referenced + * by {@code cause} parameter. + * + * @param exception exception whose message should be logged. Must not be + * {@code null}. + * @param cause initial cause of the exception that should be logged as well + * and set as {@code exception}'s original cause. May be {@code null}. + * @param level loging level which should be used for logging + * @return the same exception instance that was passed in as the {@code exception} + * parameter. + */ + public T logException(final T exception, final Throwable cause, final Level level) { + if (this.logger.isLoggable(level)) { + if (cause == null) { + logger.logp(level, componentClassName, getCallerMethodName(), exception.getMessage()); + } else { + exception.initCause(cause); + logger.logp(level, componentClassName, getCallerMethodName(), exception.getMessage(), cause); + } + } + + return exception; + } + + /** + * Method logs {@code exception}'s message at the logging level specified by the + * {@code level} argument. + *

+ * If {@code logCause} parameter is {@code true}, {@code exception}'s original + * cause is logged as well (if exists). This may be used in cases when + * {@code exception}'s class provides constructor to initialize the original + * cause. In such case you do not need to use + * {@link #logException(Throwable, Throwable, Level) logException(exception, cause, level)} + * method version but you might still want to log the original cause as well. + * + * @param exception exception whose message should be logged. Must not be + * {@code null}. + * @param logCause deterimnes whether initial cause of the exception should + * be logged as well + * @param level loging level which should be used for logging + * @return the same exception instance that was passed in as the {@code exception} + * parameter. + */ + public T logException(final T exception, final boolean logCause, final Level level) { + if (this.logger.isLoggable(level)) { + if (logCause && exception.getCause() != null) { + logger.logp(level, componentClassName, getCallerMethodName(), exception.getMessage(), exception.getCause()); + } else { + logger.logp(level, componentClassName, getCallerMethodName(), exception.getMessage()); + } + } + + return exception; + } + + /** + * Same as {@link #logException(Throwable, Throwable, Level) + * logException(exception, true, level)}. + */ + public T logException(final T exception, final Level level) { + if (this.logger.isLoggable(level)) { + if (exception.getCause() == null) { + logger.logp(level, componentClassName, getCallerMethodName(), exception.getMessage()); + } else { + logger.logp(level, componentClassName, getCallerMethodName(), exception.getMessage(), exception.getCause()); + } + } + + return exception; + } + + /** + * Function returns the name of the caller method for the method executing this + * function. + * + * @return caller method name from the call stack of the current {@link Thread}. + */ + private static String getCallerMethodName() { + return getStackMethodName(5); + } + + /** + * Method returns the name of the method that is on the {@code methodIndexInStack} + * position in the call stack of the current {@link Thread}. + * + * @param methodIndexInStack index to the call stack to get the method name for. + * @return the name of the method that is on the {@code methodIndexInStack} + * position in the call stack of the current {@link Thread}. + */ + private static String getStackMethodName(final int methodIndexInStack) { + final String methodName; + + final StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + if (stack.length > methodIndexInStack + 1) { + methodName = stack[methodIndexInStack].getMethodName(); + } else { + methodName = "UNKNOWN METHOD"; + } + + return methodName; + } + +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/istack/internal/package-info.java b/jaxws/src/share/jaxws_classes/com/sun/istack/internal/package-info.java new file mode 100644 index 00000000000..66d999da93e --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/istack/internal/package-info.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * istack-commons runtime utilities. + */ +package com.sun.istack.internal; diff --git a/jaxws/src/share/jaxws_classes/com/sun/istack/internal/tools/MaskingClassLoader.java b/jaxws/src/share/jaxws_classes/com/sun/istack/internal/tools/MaskingClassLoader.java new file mode 100644 index 00000000000..426d5478f69 --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/istack/internal/tools/MaskingClassLoader.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.istack.internal.tools; + +import java.util.Collection; + +/** + * {@link ClassLoader} that masks a specified set of classes + * from its parent class loader. + * + *

+ * This code is used to create an isolated environment. + * + * @author Kohsuke Kawaguchi + */ +public class MaskingClassLoader extends ClassLoader { + + private final String[] masks; + + public MaskingClassLoader(String... masks) { + this.masks = masks; + } + + public MaskingClassLoader(Collection masks) { + this(masks.toArray(new String[masks.size()])); + } + + public MaskingClassLoader(ClassLoader parent, String... masks) { + super(parent); + this.masks = masks; + } + + public MaskingClassLoader(ClassLoader parent, Collection masks) { + this(parent, masks.toArray(new String[masks.size()])); + } + + @Override + protected synchronized Class loadClass(String name, boolean resolve) throws ClassNotFoundException { + for (String mask : masks) { + if(name.startsWith(mask)) + throw new ClassNotFoundException(); + } + + return super.loadClass(name, resolve); + } +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/istack/internal/tools/ParallelWorldClassLoader.java b/jaxws/src/share/jaxws_classes/com/sun/istack/internal/tools/ParallelWorldClassLoader.java new file mode 100644 index 00000000000..49a131601c3 --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/istack/internal/tools/ParallelWorldClassLoader.java @@ -0,0 +1,216 @@ +/* + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.istack.internal.tools; + +import java.io.InputStream; +import java.io.ByteArrayOutputStream; +import java.io.Closeable; +import java.io.File; +import java.io.IOException; +import java.net.JarURLConnection; +import java.net.URISyntaxException; +import java.net.URL; +import java.net.MalformedURLException; +import java.net.URLConnection; +import java.util.Collections; +import java.util.Enumeration; +import java.util.HashSet; +import java.util.Set; +import java.util.jar.JarFile; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * Load classes/resources from a side folder, so that + * classes of the same package can live in a single jar file. + * + *

+ * For example, with the following jar file: + *

+ *  /
+ *  +- foo
+ *     +- X.class
+ *  +- bar
+ *     +- X.class
+ * 
+ *

+ * {@link ParallelWorldClassLoader}("foo/") would load X.class from + * /foo/X.class (note that X is defined in the root package, not + * foo.X. + * + *

+ * This can be combined with {@link MaskingClassLoader} to mask classes which are loaded by the parent + * class loader so that the child class loader + * classes living in different folders are loaded + * before the parent class loader loads classes living the jar file publicly + * visible + * For example, with the following jar file: + *

+ *  /
+ *  +- foo
+ *     +- X.class
+ *  +- bar
+ *     +-foo
+ *        +- X.class
+ * 
+ *

+ * {@link ParallelWorldClassLoader}(MaskingClassLoader.class.getClassLoader()) would load foo.X.class from + * /bar/foo.X.class not the foo.X.class in the publicly visible place in the jar file, thus + * masking the parent classLoader from loading the class from foo.X.class + * (note that X is defined in the package foo, not + * bar.foo.X. + * + * @author Kohsuke Kawaguchi + */ +public class ParallelWorldClassLoader extends ClassLoader implements Closeable { + + /** + * Strings like "prefix/", "abc/", or "" to indicate + * classes should be loaded normally. + */ + private final String prefix; + private final Set jars; + + public ParallelWorldClassLoader(ClassLoader parent,String prefix) { + super(parent); + this.prefix = prefix; + jars = Collections.synchronizedSet(new HashSet()); + } + + protected Class findClass(String name) throws ClassNotFoundException { + + StringBuffer sb = new StringBuffer(name.length()+prefix.length()+6); + sb.append(prefix).append(name.replace('.','/')).append(".class"); + + URL u = getParent().getResource(sb.toString()); + if (u == null) { + throw new ClassNotFoundException(name); + } + + InputStream is = null; + URLConnection con = null; + + try { + con = u.openConnection(); + is = con.getInputStream(); + } catch (IOException ioe) { + throw new ClassNotFoundException(name); + } + + if (is==null) + throw new ClassNotFoundException(name); + + try { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + byte[] buf = new byte[1024]; + int len; + while((len=is.read(buf))>=0) + baos.write(buf,0,len); + + buf = baos.toByteArray(); + int packIndex = name.lastIndexOf('.'); + if (packIndex != -1) { + String pkgname = name.substring(0, packIndex); + // Check if package already loaded. + Package pkg = getPackage(pkgname); + if (pkg == null) { + definePackage(pkgname, null, null, null, null, null, null, null); + } + } + return defineClass(name,buf,0,buf.length); + } catch (IOException e) { + throw new ClassNotFoundException(name,e); + } finally { + try { + if (con != null && con instanceof JarURLConnection) { + jars.add(((JarURLConnection) con).getJarFile()); + } + } catch (IOException ioe) { + //ignore + } + if (is != null) { + try { + is.close(); + } catch (IOException ioe) { + //ignore + } + } + } + } + + @Override + protected URL findResource(String name) { + URL u = getParent().getResource(prefix + name); + if (u != null) { + try { + jars.add(new JarFile(new File(toJarUrl(u).toURI()))); + } catch (URISyntaxException ex) { + Logger.getLogger(ParallelWorldClassLoader.class.getName()).log(Level.WARNING, null, ex); + } catch (IOException ex) { + Logger.getLogger(ParallelWorldClassLoader.class.getName()).log(Level.WARNING, null, ex); + } catch (ClassNotFoundException ex) { + //ignore - not a jar + } + } + return u; + } + + @Override + protected Enumeration findResources(String name) throws IOException { + Enumeration en = getParent().getResources(prefix + name); + while (en.hasMoreElements()) { + try { + jars.add(new JarFile(new File(toJarUrl(en.nextElement()).toURI()))); + } catch (URISyntaxException ex) { + //should not happen + Logger.getLogger(ParallelWorldClassLoader.class.getName()).log(Level.WARNING, null, ex); + } catch (IOException ex) { + Logger.getLogger(ParallelWorldClassLoader.class.getName()).log(Level.WARNING, null, ex); + } catch (ClassNotFoundException ex) { + //ignore - not a jar + } + } + return en; + } + + public synchronized void close() throws IOException { + for (JarFile jar : jars) { + jar.close(); + } + } + + /** + * Given the URL inside jar, returns the URL to the jar itself. + */ + public static URL toJarUrl(URL res) throws ClassNotFoundException, MalformedURLException { + String url = res.toExternalForm(); + if(!url.startsWith("jar:")) + throw new ClassNotFoundException("Loaded outside a jar "+url); + url = url.substring(4); // cut off jar: + url = url.substring(0,url.lastIndexOf('!')); // cut off everything after '!' + return new URL(url); + } +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/istack/internal/tools/SecureLoader.java b/jaxws/src/share/jaxws_classes/com/sun/istack/internal/tools/SecureLoader.java new file mode 100644 index 00000000000..ffb60ae2b5c --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/istack/internal/tools/SecureLoader.java @@ -0,0 +1,89 @@ +/* + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.istack.internal.tools; + +/** + * Class defined for safe calls of getClassLoader methods of any kind (context/system/class + * classloader. This MUST be package private and defined in every package which + * uses such invocations. + * @author snajper + */ +class SecureLoader { + + static ClassLoader getContextClassLoader() { + if (System.getSecurityManager() == null) { + return Thread.currentThread().getContextClassLoader(); + } else { + return (ClassLoader) java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction() { + public java.lang.Object run() { + return Thread.currentThread().getContextClassLoader(); + } + }); + } + } + + static ClassLoader getClassClassLoader(final Class c) { + if (System.getSecurityManager() == null) { + return c.getClassLoader(); + } else { + return (ClassLoader) java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction() { + public java.lang.Object run() { + return c.getClassLoader(); + } + }); + } + } + + static ClassLoader getSystemClassLoader() { + if (System.getSecurityManager() == null) { + return ClassLoader.getSystemClassLoader(); + } else { + return (ClassLoader) java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction() { + public java.lang.Object run() { + return ClassLoader.getSystemClassLoader(); + } + }); + } + } + + static void setContextClassLoader(final ClassLoader cl) { + if (System.getSecurityManager() == null) { + Thread.currentThread().setContextClassLoader(cl); + } else { + java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction() { + public java.lang.Object run() { + Thread.currentThread().setContextClassLoader(cl); + return null; + } + }); + } + } + +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/istack/internal/tools/package-info.java b/jaxws/src/share/jaxws_classes/com/sun/istack/internal/tools/package-info.java new file mode 100644 index 00000000000..61e7dade1a2 --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/istack/internal/tools/package-info.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * istack-commons tool time utilities. + * + *

+ * This includes code that relies on APT, javac, etc. + */ +package com.sun.istack.internal.tools; diff --git a/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/external/amx/AMX.java b/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/external/amx/AMX.java new file mode 100644 index 00000000000..bbc7ea2c05a --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/external/amx/AMX.java @@ -0,0 +1,143 @@ +/* + * Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.org.glassfish.external.amx; + +/** + Constants reflecting the AMX specification. + See https://glassfish.dev.java.net/nonav/v3/admin/planning/V3Changes/V3_AMX_SPI.html + */ +public final class AMX +{ + private AMX() + { + // do not instantiate + } + + /** Attribute yielding the ObjectName of the parent MBean */ + public static final String ATTR_PARENT = "Parent"; + + /** Attribute yielding the children as an ObjectName[] */ + public static final String ATTR_CHILDREN = "Children"; + + /** Attribute yielding the name of the MBean, + possibly differing from the name as found in the ObjectName via the + property {@link #NAME_KEY} */ + public static final String ATTR_NAME = "Name"; + + /** ObjectName property for the type */ + public static final String TYPE_KEY = "type"; + + /** ObjectName property for the name */ + public static final String NAME_KEY = "name"; + + /** Implied name for singletons when the name property is not present */ + public static final String NO_NAME = ""; + + /** + The ObjectName property key denoting the path of the parent MBean. + Serves to disambiguitate the ObjectName from others + that might have the same type and/or name elsewhere in the hierarchy. + */ + public static final String PARENT_PATH_KEY = "pp"; + + /** Prefix for AMX descriptor fields */ + public static final String DESC_PREFIX = "amx."; + + /** Prefix for AMX notification types */ + public static final String NOTIFICATION_PREFIX = DESC_PREFIX; + + /** + Descriptor value defined by JMX standard: whether the MBeanInfo is *invariant* (immutable is a misnomer). + */ + public static final String DESC_STD_IMMUTABLE_INFO = "immutableInfo"; + + /** + Descriptor value defined by JMX standard, the classname of the interface for the MBean. + Mainly advisory, since client code might not have access to the class. + */ + public static final String DESC_STD_INTERFACE_NAME = "interfaceName"; + + /** + Descriptor value: The generic AMX interface to be used if the class found in {@link #DESC_STD_INTERFACE_NAME} + cannot be loaded. The class specified here must reside in the amx-core + module eg com.sun.org.glassfish.admin.amx.core eg AMXProxy or AMXConfigProxy. + */ + public static final String DESC_GENERIC_INTERFACE_NAME = DESC_PREFIX + "genericInterfaceName"; + + /** + Descriptor value: whether the MBean is a singleton, in spite of having a name property in its ObjectName. + This is mainly for compatibility; named singletons are strongly discouraged. + */ + public static final String DESC_IS_SINGLETON = DESC_PREFIX + "isSingleton"; + + /** + Descriptor value: whether the MBean is a global singleton eg whether in the AMX domain + it can be looked up by its type and is the only MBean of that type. + */ + public static final String DESC_IS_GLOBAL_SINGLETON = DESC_PREFIX + "isGlobalSingleton"; + + /** + Descriptor value: Arbitrary string denoting the general classification of MBean. + Predefined values include "configuration", "monitoring", "jsr77", "utility", "other". + */ + public static final String DESC_GROUP = DESC_PREFIX + "group"; + + /** + Descriptor value: whether new children may be added by code other than the implementation responsible for the MBean; + this allows extension points within the hierarchy. + Adding a new child means registering an MBean with an ObjectName that implies parentage via the ancestry type=name pairs. + */ + public static final String DESC_SUPPORTS_ADOPTION = DESC_PREFIX + "supportsAdoption"; + + /** + Descriptor value: denotes the possible types of MBeans that children might be. If present, SHOULD include all possible and pre-known types. + An empty array indicates that child MBeans might exist, but their types cannot be predicted. + */ + public static final String DESC_SUB_TYPES = DESC_PREFIX + "subTypes"; + + /** + Group value indicating that the AMX is a configuration MBean. + */ + public static final String GROUP_CONFIGURATION = "configuration"; + /** + Group value indicating that the AMX represents a monitoring MBean. + */ + public static final String GROUP_MONITORING = "monitoring"; + /** + Group value indicating that the AMX is a utility MBean. + */ + public static final String GROUP_UTILITY = "utility"; + /** + Group value indicating that the AMX is a JSR 77 MBean + (J2EE Management) . + */ + public static final String GROUP_JSR77 = "jsr77"; + /** + Group value indicating that the AMX is not one + of the other types. + */ + public static final String GROUP_OTHER = "other"; +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/external/amx/AMXGlassfish.java b/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/external/amx/AMXGlassfish.java new file mode 100644 index 00000000000..842b83858e0 --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/external/amx/AMXGlassfish.java @@ -0,0 +1,317 @@ +/* + * Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.org.glassfish.external.amx; + +import javax.management.ObjectName; +import javax.management.MBeanServer; +import javax.management.MBeanServerConnection; + +import java.io.IOException; + + +/** + * AMX behavior specific to Glassfish V3. + */ +public final class AMXGlassfish +{ + public static final String DEFAULT_JMX_DOMAIN = "amx"; + + /** Default domain support */ + public static final AMXGlassfish DEFAULT = new AMXGlassfish(DEFAULT_JMX_DOMAIN); + + private final String mJMXDomain; + private final ObjectName mDomainRoot; + + /** Anything other than {@link #DEFAULT} is not supported in Glassfish V3 */ + public AMXGlassfish(final String jmxDomain) + { + mJMXDomain = jmxDomain; + mDomainRoot = newObjectName("", "domain-root", null); + } + + /** Return a version string, or null if not running in Glassfish */ + public static String getGlassfishVersion() + { + // must all exist as a check to verify that it's Glassfish V3 + final String version = System.getProperty( "glassfish.version" ); + return version; + } + + + /** JMX domain used by AMX MBeans. + *

+ * All MBeans in this domain must be AMX-compliant, see http://tinyurl.com/nryoqp = + https://glassfish.dev.java.net/nonav/v3/admin/planning/V3Changes/V3_AMX_SPI.html + */ + public String amxJMXDomain() + { + return mJMXDomain; + } + + /** JMX domain used by AMX support MBeans. Private use only */ + public String amxSupportDomain() + { + return amxJMXDomain() + "-support"; + } + + /** name of the Domain Admin Server (DAS) as found in an ObjectName */ + public String dasName() + { + return "server"; + } + + /** name of the Domain Admin Server (DAS) <config> */ + public String dasConfig() + { + return dasName() + "-config"; + } + + /** return the ObjectName of the AMX DomainRoot MBean */ + public ObjectName domainRoot() + { + return mDomainRoot; + } + + /** ObjectName for top-level monitoring MBean (parent of those for each server) */ + public ObjectName monitoringRoot() + { + return newObjectName("/", "mon", null); + } + + /** ObjectName for top-level monitoring MBean for specified server */ + public ObjectName serverMon(final String serverName) + { + return newObjectName("/mon", "server-mon", serverName); + } + + /** ObjectName for top-level monitoring MBean for the DAS. */ + public ObjectName serverMonForDAS() { + return serverMon( "server" ) ; + } + + /** Make a new AMX ObjectName with unchecked exception. + * name must be null to create a singleton ObjectName. + * Note that the arguments must not contain the characters + * @param pp The parent part + * @param type The ObjectName type + * @param name The ObjectName name + * @return The objectname with pp, type, and (optionally) name. + */ + public ObjectName newObjectName( + final String pp, + final String type, + final String name) + { + String props = prop(AMX.PARENT_PATH_KEY, pp) + "," + prop(AMX.TYPE_KEY, type); + if (name != null) { + props = props + "," + prop(AMX.NAME_KEY, name); + } + + return newObjectName( props); + } + + /** Make a new ObjectName for AMX domain with unchecked exception */ + public ObjectName newObjectName(final String s) + { + String name = s; + if ( ! name.startsWith( amxJMXDomain() ) ) { + name = amxJMXDomain() + ":" + name; + } + + return AMXUtil.newObjectName( name ); + } + + private static String prop(final String key, final String value) + { + return key + "=" + value; + } + + /** + ObjectName for {@link BootAMXMBean} + */ + public ObjectName getBootAMXMBeanObjectName() + { + return AMXUtil.newObjectName( amxSupportDomain() + ":type=boot-amx" ); + } + + /** + Invoke the bootAMX() method on {@link BootAMXMBean}. Upon return, + AMX continues to load. + A cilent should call {@link invokeWaitAMXReady} prior to use. + */ + public void invokeBootAMX(final MBeanServerConnection conn) + { + // start AMX and wait for it to be ready + try + { + conn.invoke( getBootAMXMBeanObjectName(), BootAMXMBean.BOOT_AMX_OPERATION_NAME, null, null); + } + catch (final Exception e) + { + e.printStackTrace(); + throw new RuntimeException(e); + } + } + + /** + Invoke the waitAMXReady() method on the DomainRoot MBean, which must already be loaded. + */ + private static void invokeWaitAMXReady(final MBeanServerConnection conn, final ObjectName objectName) + { + try + { + conn.invoke( objectName, "waitAMXReady", null, null ); + } + catch( final Exception e ) + { + throw new RuntimeException(e); + } + } + + /** + Listen for the registration of AMX DomainRoot + Listening starts automatically. + */ + public MBeanListener listenForDomainRoot( + final MBeanServerConnection server, + final T callback) + { + final MBeanListener listener = new MBeanListener( server, domainRoot(), callback); + listener.startListening(); + return listener; + } + + private static final class WaitForDomainRootListenerCallback extends MBeanListener.CallbackImpl { + private final MBeanServerConnection mConn; + + public WaitForDomainRootListenerCallback( final MBeanServerConnection conn ) { + mConn = conn; + } + + @Override + public void mbeanRegistered(final ObjectName objectName, final MBeanListener listener) { + super.mbeanRegistered(objectName,listener); + invokeWaitAMXReady(mConn, objectName); + mLatch.countDown(); + } + } + + /** + Wait until AMX has loaded and is ready for use. +

+ This will not cause AMX to load; it will block forever until AMX is ready. In other words, + don't call this method unless it's a convenient thread that can wait forever. + */ + public ObjectName waitAMXReady( final MBeanServerConnection server) + { + final WaitForDomainRootListenerCallback callback = new WaitForDomainRootListenerCallback(server); + listenForDomainRoot( server, callback ); + callback.await(); + return callback.getRegistered(); + } + + /** + Listen for the registration of the {@link BootAMXMBean}. + Listening starts automatically. See {@link AMXBooter#BootAMXCallback}. + */ + public MBeanListener listenForBootAMX( + final MBeanServerConnection server, + final T callback) + { + final MBeanListener listener = new MBeanListener( server, getBootAMXMBeanObjectName(), callback); + listener.startListening(); + return listener; + } + + /** + Callback for {@link MBeanListener} that waits for the BootAMXMBean to appear; + it always will load early in server startup. Once it has loaded, AMX can be booted + via {@link #bootAMX}. A client should normally just call {@link #bootAMX}, but + this callback may be suclassed if desired, and used as a trigger to + boot AMX and then take other dependent actions. + */ + public static class BootAMXCallback extends MBeanListener.CallbackImpl + { + private final MBeanServerConnection mConn; + public BootAMXCallback(final MBeanServerConnection conn) + { + mConn = conn; + } + + @Override + public void mbeanRegistered(final ObjectName objectName, final MBeanListener listener) + { + super.mbeanRegistered(objectName, listener); + mLatch.countDown(); + } + } + + /** + Ensure that AMX is loaded and ready to use. This method returns only when all + AMX subsystems have been loaded. + It can be called more than once without ill effect, subsequent calls are ignored. + @param conn connection to the MBeanServer + @return the ObjectName of the domain-root MBean + */ + public ObjectName bootAMX(final MBeanServerConnection conn) + throws IOException + { + final ObjectName domainRoot = domainRoot(); + + if ( !conn.isRegistered( domainRoot ) ) + { + // wait for the BootAMXMBean to be available (loads at startup) + final BootAMXCallback callback = new BootAMXCallback(conn); + listenForBootAMX(conn, callback); + callback.await(); // block until the MBean appears + + invokeBootAMX(conn); + + final WaitForDomainRootListenerCallback drCallback = new WaitForDomainRootListenerCallback(conn); + listenForDomainRoot(conn, drCallback); + drCallback.await(); + + invokeWaitAMXReady(conn, domainRoot); + } + else + { + invokeWaitAMXReady(conn, domainRoot ); + } + return domainRoot; + } + + public ObjectName bootAMX(final MBeanServer server) + { + try + { + return bootAMX( (MBeanServerConnection)server); + } + catch( final IOException e ) + { + throw new RuntimeException(e); + } + } +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/external/amx/AMXUtil.java b/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/external/amx/AMXUtil.java new file mode 100644 index 00000000000..314bbccbf63 --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/external/amx/AMXUtil.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.org.glassfish.external.amx; + +import javax.management.MBeanServerConnection; +import javax.management.ObjectName; + +/** + Small utilities for AMXBooter and related. + */ +@com.sun.org.glassfish.external.arc.Taxonomy(stability = com.sun.org.glassfish.external.arc.Stability.UNCOMMITTED) +public final class AMXUtil +{ + private AMXUtil() {} + + /** + Make a new ObjectName (unchecked exception). + */ + public static ObjectName newObjectName(final String s) + { + try + { + return new ObjectName( s ); + } + catch( final Exception e ) + { + throw new RuntimeException("bad ObjectName", e); + } + } + + /** + Make a new ObjectName (unchecked exception). + @param domain + @param props + */ + public static ObjectName newObjectName( + final String domain, + final String props) + { + return newObjectName(domain + ":" + props); + } + + /** + Get the ObjectName of the MBeanServerDelegateObjectName. + */ + public static ObjectName getMBeanServerDelegateObjectName() + { + return newObjectName( "JMImplementation:type=MBeanServerDelegate" ); + } + + public static String prop(final String key, final String value) + { + return key + "=" + value; + } +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/external/amx/BootAMXMBean.java b/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/external/amx/BootAMXMBean.java new file mode 100644 index 00000000000..fa8f3ffa888 --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/external/amx/BootAMXMBean.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.org.glassfish.external.amx; + +import javax.management.ObjectName; +import javax.management.remote.JMXServiceURL; + +/** + MBean responsible for booting the AMX system. + To get its ObjectName, use {@link AMXGlassfish#getBootAMXMBeanObjectName}. + */ +@com.sun.org.glassfish.external.arc.Taxonomy(stability = com.sun.org.glassfish.external.arc.Stability.UNCOMMITTED) +public interface BootAMXMBean +{ + /** + Start AMX and return the ObjectName of DomainRoot. + */ + public ObjectName bootAMX(); + + /** same as method above */ + public static final String BOOT_AMX_OPERATION_NAME = "bootAMX"; + + public JMXServiceURL[] getJMXServiceURLs(); +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/external/amx/MBeanListener.java b/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/external/amx/MBeanListener.java new file mode 100644 index 00000000000..0bf5b606bc6 --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/external/amx/MBeanListener.java @@ -0,0 +1,329 @@ +/* + * Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.org.glassfish.external.amx; + +import java.util.Set; +import javax.management.MBeanServer; +import javax.management.MBeanServerConnection; +import javax.management.MBeanServerNotification; +import javax.management.Notification; +import javax.management.NotificationListener; +import javax.management.ObjectName; +import java.util.concurrent.CountDownLatch; + +import static com.sun.org.glassfish.external.amx.AMX.*; + +/** + * Listens for registration of MBeans of various types. + * Intended usage is for subsystems to lazy-load only when the Parent + * MBean is registered. + */ +@com.sun.org.glassfish.external.arc.Taxonomy(stability = com.sun.org.glassfish.external.arc.Stability.UNCOMMITTED) +public class MBeanListener implements NotificationListener +{ + private static void debug(final Object o) { System.out.println( "" + o ); } + + /** listen for MBeans in a given domain of a given type[name] + OR an ObjectName (below) */ + private final String mJMXDomain; + private final String mType; + private final String mName; + + /** mType and mName should be null if mObjectName is non-null, and vice versa */ + private final ObjectName mObjectName; + + private final MBeanServerConnection mMBeanServer; + + private final T mCallback; + + public String toString() + { + return "MBeanListener: ObjectName=" + mObjectName + ", type=" + mType + ", name=" + mName; + } + + public String getType() + { + return mType; + } + + public String getName() + { + return mName; + } + + public MBeanServerConnection getMBeanServer() + { + return mMBeanServer; + } + + /** Callback interface. */ + public interface Callback + { + public void mbeanRegistered(final ObjectName objectName, final MBeanListener listener); + public void mbeanUnregistered(final ObjectName objectName, final MBeanListener listener); + } + + /** + Default callback implementation, can be subclassed if needed + Remembers only the last MBean that was seen. + */ + public static class CallbackImpl implements MBeanListener.Callback + { + private volatile ObjectName mRegistered = null; + private volatile ObjectName mUnregistered = null; + private final boolean mStopAtFirst; + + public CallbackImpl() { + this(true); + } + + public CallbackImpl(final boolean stopAtFirst) + { + mStopAtFirst = stopAtFirst; + } + + public ObjectName getRegistered() { return mRegistered; } + public ObjectName getUnregistered() { return mUnregistered; } + + protected final CountDownLatch mLatch = new CountDownLatch(1); + + /** Optional: wait for the CountDownLatch to fire + If used, the subclass should countDown() the latch when the + appropriate event happens + */ + public void await() + { + try + { + mLatch.await(); // wait until BootAMXMBean is ready + } + catch (InterruptedException e) + { + throw new RuntimeException(e); + } + } + + public void mbeanRegistered(final ObjectName objectName, final MBeanListener listener) + { + mRegistered = objectName; + if ( mStopAtFirst ) + { + listener.stopListening(); + } + } + public void mbeanUnregistered(final ObjectName objectName, final MBeanListener listener) + { + mUnregistered = objectName; + if ( mStopAtFirst ) + { + listener.stopListening(); + } + } + } + + public T getCallback() + { + return mCallback; + } + + /** + * Listener for a specific MBean. + * Caller must call {@link #start} to start listening. + * @param server + * @param objectName + * @param callback + */ + public MBeanListener( + final MBeanServerConnection server, + final ObjectName objectName, + final T callback) + { + mMBeanServer = server; + mObjectName = objectName; + mJMXDomain = null; + mType = null; + mName = null; + mCallback = callback; + } + + /** + * Listener for all MBeans of specified type, with or without a name. + * Caller must call {@link #start} to start listening. + * @param server + * @param type type of the MBean (as found in the ObjectName) + * @param callback + */ + public MBeanListener( + final MBeanServerConnection server, + final String domain, + final String type, + final T callback) + { + this(server, domain, type, null, callback); + } + + /** + * Listener for MBeans of specified type, with specified name (or any name + * if null is passed for the name). + * Caller must call {@link #start} to start listening. + * @param server + * @param type type of the MBean (as found in the ObjectName) + * @param name name of the MBean, or null if none + * @param callback + */ + public MBeanListener( + final MBeanServerConnection server, + final String domain, + final String type, + final String name, + final T callback) + { + mMBeanServer = server; + mJMXDomain = domain; + mType = type; + mName = name; + mObjectName = null; + mCallback = callback; + } + + + private boolean isRegistered( final MBeanServerConnection conn, final ObjectName objectName ) + { + try + { + return conn.isRegistered(objectName); + } + catch (final Exception e) + { + throw new RuntimeException(e); + } + } + + /** + Start listening. If the required MBean(s) are already present, the callback + will be synchronously made before returning. It is also possible that the + callback could happen twice for the same MBean. + */ + public void startListening() + { + // race condition: must listen *before* looking for existing MBeans + try + { + mMBeanServer.addNotificationListener( AMXUtil.getMBeanServerDelegateObjectName(), this, null, this); + } + catch (final Exception e) + { + throw new RuntimeException("Can't add NotificationListener", e); + } + + if ( mObjectName != null ) + { + if ( isRegistered(mMBeanServer, mObjectName) ) + { + mCallback.mbeanRegistered(mObjectName, this); + } + } + else + { + // query for AMX MBeans of the requisite type + String props = TYPE_KEY + "=" + mType; + if (mName != null) + { + props = props + "," + NAME_KEY + mName; + } + + final ObjectName pattern = AMXUtil.newObjectName(mJMXDomain + ":" +props); + try + { + final Set matched = mMBeanServer.queryNames(pattern, null); + for (final ObjectName objectName : matched) + { + mCallback.mbeanRegistered(objectName, this); + } + } + catch( final Exception e ) + { + throw new RuntimeException(e); + } + } + } + + + /** unregister the listener */ + public void stopListening() + { + try + { + mMBeanServer.removeNotificationListener( AMXUtil.getMBeanServerDelegateObjectName(), this); + } + catch (final Exception e) + { + throw new RuntimeException("Can't remove NotificationListener " + this, e); + } + } + + public void handleNotification( + final Notification notifIn, + final Object handback) + { + if (notifIn instanceof MBeanServerNotification) + { + final MBeanServerNotification notif = (MBeanServerNotification) notifIn; + final ObjectName objectName = notif.getMBeanName(); + + boolean match = false; + if ( mObjectName != null && mObjectName.equals(objectName) ) + { + match = true; + } + else if ( objectName.getDomain().equals( mJMXDomain ) ) + { + if ( mType != null && mType.equals(objectName.getKeyProperty(TYPE_KEY)) ) + { + final String mbeanName = objectName.getKeyProperty(NAME_KEY); + if (mName != null && mName.equals(mbeanName)) + { + match = true; + } + } + } + + if ( match ) + { + final String notifType = notif.getType(); + if (MBeanServerNotification.REGISTRATION_NOTIFICATION.equals(notifType)) + { + mCallback.mbeanRegistered(objectName, this); + } + else if (MBeanServerNotification.UNREGISTRATION_NOTIFICATION.equals(notifType)) + { + mCallback.mbeanUnregistered(objectName, this); + } + } + } + } + +} diff --git a/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/external/arc/Stability.java b/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/external/arc/Stability.java new file mode 100644 index 00000000000..bcd53a7082c --- /dev/null +++ b/jaxws/src/share/jaxws_classes/com/sun/org/glassfish/external/arc/Stability.java @@ -0,0 +1,330 @@ +/* + * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.org.glassfish.external.arc; + + + +/** + Taxonomy values. + See http://opensolaris.org/os/community/arc/policies/interface-taxonomy/ +

+

Policy

+
    +
  • Applies to All software produced by SMI
  • +
  • Authority SAC
  • +
  • Approval SAC
  • +
  • Effective April, 1992
  • +
  • Policy
  • +
    • All software interfaces must be classified according to this taxonomy. + Interfaces are defined as APIs, files and directory structures, file formats, protocols, + (sometimes) even performance and reliability behaviors, and any other attribute upon + which another component might reasonably depend.
    • + +
    • An ARC must review, approve and archive the specification for all interfaces + other than Project Private and Internal. Unreviewed, unapproved interfaces are assumed + to be Internal. An adequate specification, suitable for archiving must exist for all + interfaces submitted for review. Often Project Private interfaces are also reviewed if + the presentation of them aids the understanding of the entire project or it is expected + they will be promoted to a broader classification in the future.
    • + +
    • Adequate customer documentation must exist for all Public interfaces. + It is strongly preferred that manual pages exist for all Public interfaces + (supported on Solaris), even if only significant content of those pages are SYNOPSIS + and ATTRIBUTES sections and a textual pointer to other documentation. + Independent of the form of documentation delivery, the interface taxonomy commitment + level must be presented to the consumer.
    • + +
    • In cases where the organization delivering the interface implementation does not + control the interface specification, the controlling body must be be clearly cited + in the documentation. In the case where a well-defined, versioned document is the + specification, both the name and precise version must be be cited.
    • +
    +
+ @author llc + */ +public enum Stability { + /** +
+    +----------------------------------------------------------------------------+
+    | Committed (formerly Stable, Public; encompasses Standard, Evolving)        |
+    |----------------------------------------------------------------------------|
+    |   | Specification       | Open                                             |
+    |   |---------------------+--------------------------------------------------|
+    |   | Incompatible Change | major release (X.0)                              |
+    |   |---------------------+--------------------------------------------------|
+    |   | ARC review of Specs | Yes                                              |
+    |   |---------------------+--------------------------------------------------|
+    |   | Examples            | Compiler command line options,                   |
+    |   |                     | hardware  (SBus, PCI, USB), RPC, POSIX utilities |
+    +----------------------------------------------------------------------------+
+    
+ We publish the specification of these interfaces, typically as manual pages or other product documentation. + We also tell customers we will remain compatible with them. (Scott McNealy's principle that "Compatibility is a + constraint, not a goal") The intention of a Committed interface is to enable arbitrary third parties to develop + applications to these interfaces, release them, and have confidence that they will run on all releases of the product + after the one in which the interface was introduced, and within the same Major release. Even at a Major release, + incompatible changes are expected to be rare, and to have strong justifications. +

+ Committed interfaces are often proposed to be industry standards, as was the case with RPC. + Also, interfaces defined and controlled as industry standards are most often treated as Committed interfaces. +

+ These are interfaces whose specification is often under the provider's control or which are specified by a + clearly versioned document controlled by a well-defined organization. If the interface specification is not + under the implementation provider's control, the provider must be willing to fork from the interface specification + if required to maintain compatibility. In the case of interface specifications controlled by a standards body, + the commitment must be to a clearly identified version of the specification, minimizing the likelihood of an + incompatible change (but it can happen through formal spec interpretations). +

+ Also, if the interface specification is not under the control of the interface implementation provider, + then the controlling body and/or public, versioned document must be be noted in the documentation. + This is particularly important for specifications controlled by recognized standards organizations. +

+ Although a truely exceptional event, incompatible changes are possible in any release if + the associated defect is serious enough as outlined in the EXEMPTIONS section of this document or + in a Minor release by following the End of Feature process. + */ + COMMITTED( "Committed" ), + +/** +

+    +--------------------------------------------------------------------------+
+    | Uncommitted (formerly Unstable)                                          |
+    |--------------------------------------------------------------------------|
+    |   | Specification       | Open                                           |
+    |   |---------------------+------------------------------------------------|
+    |   | Incompatible Change | minor release (x.Y) with impact assessment     |
+    |   |---------------------+------------------------------------------------|
+    |   | ARC review of Specs | Yes                                            |
+    |   |---------------------+------------------------------------------------|
+    |   | Examples            | SUNW* package abbreviations, some config utils |
+    +--------------------------------------------------------------------------+
+    
+ No guarantees are made about either source or binary compatibility of these interfaces + from one Minor release to the next. The most drastic incompatible change of removal of + the interface in a Minor release is allowed. Uncommitted interfaces are generally not + appropriate for use by release-independent products. +

+ Uncommitted is not a license for gratuitous change. Any incompatible changes to the + interface should be motivated by true improvement to the interface which may include + justifiable ease of use considerations. The general expectation is that Uncommitted + interfaces are not likely to change incompatibly and if such changes occur they will be + small in impact and should often have a mitigation plan. +

+ Uncommitted interfaces generally fall into one of the following subcategories: +

+