7150322: Stop using drop source bundles in jaxws

Reviewed-by: darcy, ohrstrom
This commit is contained in:
Kelly O'Hair 2012-03-06 16:09:35 -08:00
parent abf322bf84
commit bc113af571
3000 changed files with 489383 additions and 404 deletions

View File

@ -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.

View File

@ -1,150 +0,0 @@
<?xml version="1.0"?>
<!--
Copyright (c) 2009, 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.
-->
<project name="jaxws_defs" default="all" basedir=".">
<!-- Specific build properties. -->
<property file="jaxws.properties"/>
<!-- Where generated xml files will stay. -->
<property name="xml.gen.dir" value="${build.dir}/xml_generated"/>
<property name="xml.template" value="build-drop-template.xml"/>
<!-- ############### -->
<!-- Begin Macrodefs -->
<!-- Copies template file, replaces @DROP@ pattern, and imports it. -->
<macrodef name="drop-import">
<attribute name="name"/>
<sequential>
<property name="xml.gen.@{name}" value="${xml.gen.dir}/build-drop-@{name}.xml"/>
<mkdir dir="${xml.gen.dir}"/>
<copy file="${xml.template}" tofile="${xml.gen.@{name}}"/>
<replace file="${xml.gen.@{name}}" token="@DROP@" value="@{name}"/>
<import file="${xml.gen.@{name}}"/>
</sequential>
</macrodef>
<!-- End of Macrodefs -->
<!-- ############### -->
<!-- Create xml file and import it for these drops. -->
<drop-import name="jaxws_src"/>
<drop-import name="jaf_src"/>
<!-- <drop-import name="jaxws_tests"/> -->
<!-- Fail and print helpful messages if source does not exist. -->
<target name="-src-help">
<fail message="${failed.url.src.message}">
<condition>
<and>
<not>
<and>
<available file="${jaxws_src.src.dir}" type="dir"/>
<available file="${jaf_src.src.dir}" type="dir"/>
</and>
</not>
<istrue value="${allow.downloads}"/>
</and>
</condition>
</fail>
<fail message="${failed.nourl.src.message}">
<condition>
<not>
<and>
<available file="${jaxws_src.src.dir}" type="dir"/>
<available file="${jaf_src.src.dir}" type="dir"/>
</and>
</not>
</condition>
</fail>
</target>
<!-- Special build area setup. -->
<target name="-drop-build-setup" depends="init, -init-src-dirs">
<mkdir dir="${build.classes.dir}"/>
<copy todir="${build.classes.dir}">
<fileset dir="${primary.src.dir}"
includes="**/*.xsd, **/*.default, **/*.properties"
excludes="**/*.java, **/*.package.html"/>
</copy>
<replaceregexp match="#(.*)$" replace="#" flags="gm">
<fileset dir="${build.classes.dir}" includes="**/*.properties"/>
</replaceregexp>
<mkdir dir="${build.classes.dir}/META-INF/services"/>
<copy todir="${build.classes.dir}/META-INF"
file="${secondary.src.dir}/META-INF/mailcap.default"/>
<copy todir="${build.classes.dir}/META-INF"
file="${secondary.src.dir}/META-INF/mimetypes.default"/>
<copy todir="${build.classes.dir}/META-INF/services"
file="${primary.src.dir}/com/sun/tools/etc/META-INF/services/com.sun.tools.internal.ws.wscompile.Plugin"/>
<copy todir="${build.classes.dir}/META-INF/services"
file="${primary.src.dir}/com/sun/tools/etc/META-INF/services/com.sun.tools.internal.xjc.Plugin"/>
<mkdir dir="${build.classes.dir}/com/sun/tools/internal/xjc/runtime"/>
<copy todir="${build.classes.dir}/com/sun/tools/internal/xjc/runtime">
<fileset dir="${primary.src.dir}/com/sun/tools/internal/xjc/runtime"
includes="**/*.java"
excludes="**/*.package.html"/>
</copy>
</target>
<!-- Try to get drop sources. -->
<target name="-set-props"
depends="init,
jaxws_src-update,
jaf_src-update">
</target>
<!-- Set up source to use drop.dir. -->
<target name="-use-drop" depends="-set-props">
<property name="primary.src.dir" value="${jaxws_src.src.dir}"/>
<property name="secondary.src.dir" value="${jaf_src.src.dir}"/>
<path id="src.dir.id">
<pathelement path="${primary.src.dir}"/>
<pathelement path="${jaf_src.src.dir}"/>
</path>
</target>
<!-- Source directory selection. -->
<target name="-init-src-dirs"
depends="init, -use-drop,-src-help">
<echo message="Using primary.src.dir=${primary.src.dir}"/>
<pathconvert property="src.list.id" refid="src.dir.id"/>
<echo message="Using src.dir.id=${src.list.id}"/>
</target>
<!-- Create drop src.zip. -->
<target name="-drop-src-zip" depends="init, -set-props">
<zip file="${dist.src.zip}" basedir="${primary.src.dir}"/>
<zip file="${dist.src.zip}" basedir="${jaf_src.src.dir}" update="true"/>
</target>
<!-- Create src.zip. -->
<target name="-dist-src-zip" depends="init, -drop-src-zip">
</target>
</project>

View File

@ -1,144 +0,0 @@
<?xml version="1.0"?>
<!--
Copyright (c) 2009, 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.
-->
<project name="@DROP@-drop" default="all" basedir=".">
<!-- Locations of master drop bundles. -->
<property name="@DROP@.master.bundle.copy"
value="${@DROP@.master.bundle.dir}/${@DROP@.bundle.name}"/>
<property name="@DROP@.master.bundle.url"
value="${@DROP@.master.bundle.url.base}/${@DROP@.bundle.name}"/>
<!-- Location where the copied bundle lands. -->
<property name="@DROP@.bundle.copy"
value="${drop.expanded.dir}/bundles/${@DROP@.bundle.name}"/>
<!-- Root of exploded area. -->
<property name="@DROP@.root.dir" value="${drop.dir}/@DROP@"/>
<property name="@DROP@.src.dir" value="${@DROP@.root.dir}/src"/>
<!-- To see if the drop areas are ready. (ignoring bundles) -->
<target name="-@DROP@-ready">
<condition property="@DROP@.ready">
<or>
<available file="${drop.included.dir}" type="dir"/>
<and>
<available file="${@DROP@.root.dir}" type="dir"/>
<available file="${@DROP@.root.dir}/PATCHED" type="file"/>
</and>
</or>
</condition>
</target>
<!-- Copy over bundles from some shared master area. -->
<condition property="@DROP@.master.bundle.copy.exists">
<available file="${@DROP@.master.bundle.copy}" type="file"/>
</condition>
<target name="-@DROP@-copy-bundle"
depends="init, -@DROP@-ready"
if="@DROP@.master.bundle.copy.exists"
unless="@DROP@.ready">
<echo message="Copying from ${@DROP@.master.bundle.copy}"/>
<dirname property="@DROP@.bundle.dirname" file="${@DROP@.bundle.copy}"/>
<mkdir dir="${@DROP@.bundle.dirname}"/>
<delete file="${@DROP@.bundle.copy}.temp"/>
<delete file="${@DROP@.bundle.copy}"/>
<copy file="${@DROP@.master.bundle.copy}" tofile="${@DROP@.bundle.copy}.temp"/>
<move file="${@DROP@.bundle.copy}.temp" tofile="${@DROP@.bundle.copy}"/>
<property name="@DROP@.master.bundle.found" value="true"/>
</target>
<!-- Determine if the master url download should be used. -->
<target name="-@DROP@-url-should-be-used" unless="@DROP@.url.should.be.used">
<condition property="@DROP@.url.should.be.used">
<and>
<istrue value="${allow.downloads}"/>
<not>
<isset property="@DROP@.master.bundle.copy.exists"/>
</not>
</and>
</condition>
</target>
<!-- Download bundles from a url. -->
<target name="-@DROP@-url-bundle"
depends="init, -@DROP@-ready, -@DROP@-url-should-be-used"
if="@DROP@.url.should.be.used"
unless="@DROP@.ready">
<echo message="Downloading from ${@DROP@.master.bundle.url}"/>
<dirname property="@DROP@.bundle.dirname" file="${@DROP@.bundle.copy}"/>
<mkdir dir="${@DROP@.bundle.dirname}"/>
<delete file="${@DROP@.bundle.copy}.temp"/>
<delete file="${@DROP@.bundle.copy}"/>
<get src="${@DROP@.master.bundle.url}" dest="${@DROP@.bundle.copy}.temp"/>
<move file="${@DROP@.bundle.copy}.temp" tofile="${@DROP@.bundle.copy}"/>
<property name="@DROP@.master.bundle.found" value="true"/>
</target>
<!-- Fill in the drop zones, but just when needed. -->
<target name="@DROP@-update"
depends="init,
-@DROP@-copy-bundle,
-@DROP@-url-bundle,
-@DROP@-ready"
if="@DROP@.master.bundle.found"
unless="@DROP@.ready">
<delete dir="${@DROP@.root.dir}"/>
<delete dir="${@DROP@.root.dir}-temp"/>
<mkdir dir="${@DROP@.root.dir}-temp"/>
<checksum file="${@DROP@.bundle.copy}"
property="@DROP@.bundle.md5.checksum.is"/>
<condition property="@DROP@.bundle.md5.checksum.good">
<equals arg1="${@DROP@.bundle.md5.checksum}"
arg2="${@DROP@.bundle.md5.checksum.is}"/>
</condition>
<fail unless="@DROP@.bundle.md5.checksum.good">
Checksum on file ${@DROP@.bundle.copy} is
${@DROP@.bundle.md5.checksum.is}, not ${@DROP@.bundle.md5.checksum}
</fail>
<unzip src="${@DROP@.bundle.copy}" dest="${@DROP@.root.dir}-temp"/>
<move file="${@DROP@.root.dir}-temp" tofile="${@DROP@.root.dir}"/>
<touch>
<fileset dir="${@DROP@.root.dir}"/>
</touch>
<condition property="patch.utility" value="gpatch" else="patch">
<os name="SunOS"/>
</condition>
<apply executable="${patch.utility}"
dir="${@DROP@.root.dir}"
parallel="false"
failonerror="true"
verbose="true">
<arg value="-l"/>
<arg value="-p0"/>
<arg value="-i"/>
<filelist dir="${patches.dir}/@DROP@" files="${@DROP@.patch.list}"/>
</apply>
<echo file="${@DROP@.root.dir}/PATCHED"
message="Patches have been applied."/>
</target>
</project>

View File

@ -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}
#------------------------------------------------------------

View File

@ -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.
</description>
@ -46,15 +43,12 @@
<!-- Project build properties. -->
<property file="build.properties"/>
<!-- See if drop sources were included. -->
<condition property="drop.dir"
value="${drop.included.dir}"
else="${drop.expanded.dir}">
<available file="${drop.included.dir}" type="dir"/>
</condition>
<!-- Get shared targets. -->
<import file="build-defs.xml"/>
<property name="jaxws.src.dir" value="src/share/jaxws_classes"/>
<property name="jaf.src.dir" value="src/share/jaf_classes"/>
<path id="src.dir.id">
<pathelement path="${jaxws.src.dir}"/>
<pathelement path="${jaf.src.dir}"/>
</path>
<!-- Initialization of directories needed for build. -->
<target name="init">
@ -79,14 +73,20 @@
unless="javac.jar.exists">
<echo message="WARNING: Cannot find ${javac.jar}"/>
</target>
<!-- Create src.zip. -->
<target name="-dist-src-zip" depends="init">
<zip file="${dist.src.zip}" basedir="${jaxws.src.dir}"/>
<zip file="${dist.src.zip}" basedir="${jaf.src.dir}" update="true"/>
</target>
<!-- Creation of distribution files to jdk build process. -->
<target name="dist"
depends="init, -init-src-dirs, build, -dist-classes-jar, -dist-src-zip"
depends="init, build, -dist-classes-jar, -dist-src-zip"
description="Create all built distribution files.">
</target>
<target name="-dist-classes-jar-uptodate"
depends="init, -init-src-dirs">
depends="init">
<condition property="dist.classes.jar.uptodate">
<and>
<available file="${dist.classes.jar}" type="file"/>
@ -97,14 +97,39 @@
</condition>
</target>
<target name="-dist-classes-jar"
depends="init, -init-src-dirs, -dist-classes-jar-uptodate"
depends="init, -dist-classes-jar-uptodate"
unless="dist.classes.jar.uptodate">
<delete file="${dist.classes.jar}"/>
<jar file="${dist.classes.jar}" basedir="${build.classes.dir}"/>
</target>
<target name="-build-setup"
depends="init, -init-src-dirs, -drop-build-setup">
<!-- Special build area setup. -->
<target name="-build-setup" depends="init">
<mkdir dir="${build.classes.dir}"/>
<copy todir="${build.classes.dir}">
<fileset dir="${jaxws.src.dir}"
includes="**/*.xsd, **/*.default, **/*.properties"
excludes="**/*.java, **/*.package.html"/>
</copy>
<replaceregexp match="#(.*)$" replace="#" flags="gm">
<fileset dir="${build.classes.dir}" includes="**/*.properties"/>
</replaceregexp>
<mkdir dir="${build.classes.dir}/META-INF/services"/>
<copy todir="${build.classes.dir}/META-INF"
file="${jaf.src.dir}/META-INF/mailcap.default"/>
<copy todir="${build.classes.dir}/META-INF"
file="${jaf.src.dir}/META-INF/mimetypes.default"/>
<copy todir="${build.classes.dir}/META-INF/services"
file="${jaxws.src.dir}/com/sun/tools/etc/META-INF/services/com.sun.tools.internal.ws.wscompile.Plugin"/>
<copy todir="${build.classes.dir}/META-INF/services"
file="${jaxws.src.dir}/com/sun/tools/etc/META-INF/services/com.sun.tools.internal.xjc.Plugin"/>
<mkdir dir="${build.classes.dir}/com/sun/tools/internal/xjc/runtime"/>
<copy todir="${build.classes.dir}/com/sun/tools/internal/xjc/runtime">
<fileset dir="${jaxws.src.dir}/com/sun/tools/internal/xjc/runtime"
includes="**/*.java"
excludes="**/*.package.html"/>
</copy>
</target>
<!-- Build (compilation) of sources to class files. -->
@ -112,7 +137,7 @@
depends="compile, -build-setup">
</target>
<target name="compile"
depends="init, -init-src-dirs">
depends="init">
<mkdir dir="${build.classes.dir}"/>
<javac
includeAntRuntime="false"
@ -132,26 +157,16 @@
<!-- Test. (FIXME: Need to know how to run tests.) -->
<target name="test"
depends="init, -init-src-dirs, dist">
depends="init, dist">
<echo message="FIXME: How do you run the tests"/>
</target>
<!-- Populate source area if needed. -->
<target name="source"
depends="init, -init-src-dirs"
depends="init"
description="Populate all source file directories">
</target>
<!-- Populate drop_included area. -->
<target name="drop_included"
depends="clobber"
description="Populate all source file directories">
<delete dir="${drop.included.dir}"/>
<antcall target="source"/>
<move file="${drop.expanded.dir}" tofile="${drop.included.dir}"/>
<delete dir="${drop.included.dir}/bundles"/>
</target>
<!-- Clean up compiled files. -->
<target name="clean"
description="Delete all generated files">
@ -163,7 +178,6 @@
<target name="clobber"
depends="clean"
description="Delete all generated files, including imported sources">
<delete dir="${drop.expanded.dir}"/>
</target>
<target name="-banner">

View File

@ -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,\

View File

@ -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"

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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);
}
}

View File

@ -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.
*
* <p>
* <strong>Semantics:</strong> First check for the literal mime type,
* if that fails looks for wildcard <type>/\* 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.
*
* <p>
* <strong>Semantics:</strong> First check for the literal mime type,
* if that fails looks for wildcard <type>/\* 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 == "# <i>comment string</i>
* Entry == "mimetype; javabeanclass<nl>
*
* 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("");
}
}
*/
}

View File

@ -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);
}
}

View File

@ -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("");
}
}
*/
}

View File

@ -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;
}
}

View File

@ -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.
* <p>
*
* @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 <code>true</code> if there are more tokens available from this
* tokenizer's string; <code>false</code> 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);
}
}

View File

@ -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
* <code>java.awt.datatransfer.DataFlavor</code>. 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 <code>equals
* </code> 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.
* <p>
* The returned DataFlavor will have the following characteristics:
* <p>
* representationClass = representationClass<br>
* mimeType = mimeType<br>
* humanName = humanName
* <p>
*
* @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.
* <p>
* The returned DataFlavor will have the following characteristics:
* <p>
* If the mimeType is "application/x-java-serialized-object;
* class=", the result is the same as calling new
* DataFlavor(Class.forName()) as above.
* <p>
* otherwise:
* <p>
* representationClass = InputStream<p>
* mimeType = mimeType<p>
*
* @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.
* <p>
* The returned DataFlavor will have the following characteristics:
* <p>
* If the mimeType is "application/x-java-serialized-object; class=",
* the result is the same as calling new DataFlavor(Class.forName()) as
* above, otherwise:
* <p>
* representationClass = InputStream<p>
* 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 <code>isMimeTypeEqual</code> 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. <p>
*
* 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).
* <p>
* 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;
}
}

View File

@ -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 <i>it is not guaranteed to
* return a valid value</i>. 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. <i>This method MAY return null in
* cases where a CommandMap subclassed CommandInfo for its
* own purposes.</i> In other words, it might not be possible to
* create the correct state in the command by merely knowing
* its class name. <b>DO NOT DEPEND ON THIS METHOD RETURNING
* A VALID VALUE!</b>
*
* @return The class name of the command, or <i>null</i>
*/
public String getCommandClass() {
return className;
}
/**
* Return the instantiated JavaBean component.
* <p>
* Begin by instantiating the component with
* <code>Beans.instantiate()</code>.
* <p>
* If the bean implements the <code>javax.activation.CommandObject</code>
* interface, call its <code>setCommandContext</code> method.
* <p>
* 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.
* <p>
* 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.<p>
*
* @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;
}
}

View File

@ -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.
* <p>
*
* <ul>
* <li> In cases where a CommandMap instance has been previously set
* to some value (via <i>setDefaultCommandMap</i>)
* return the CommandMap.
* <li>
* In cases where no CommandMap has been set, the CommandMap
* creates an instance of <code>MailcapCommandMap</code> and
* set that to the default, returning its value.
*
* </ul>
*
* @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 <code>null</code>.
*
* @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. <p>
*
* The <code>DataSource</code> 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 <code>getPreferredCommands</code>
* 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. <p>
*
* The <code>DataSource</code> 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 <code>getAllCommands</code>
* 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. <p>
*
* The <code>DataSource</code> 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 <code>getCommand</code>
* 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. <p>
*
* The <code>DataSource</code> 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 <code>createDataContentHandler</code>
* 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;
}
}

View File

@ -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.<p>
*
* @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. <b>NOTE:</b> it is acceptable for the caller
* to pass <i>null</i> as the value for <code>DataHandler</code>.
*
* @param verb The Command Verb this object refers to.
* @param dh The DataHandler.
*/
public void setCommandContext(String verb, DataHandler dh)
throws IOException;
}

View File

@ -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 <code>DataContentHandlers</code>
* the framework can be extended to convert streams in to objects, and
* to write objects to streams. <p>
*
* 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 <code>getTransferDataFlavors</code> 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;
}

View File

@ -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 <code>DataContentHandlers</code>. 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
* <code>java.net.URL</code>.
*
* @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 <code>DataContentHandler</code>, or <i>null</i>
* if none are found.
*/
public DataContentHandler createDataContentHandler(String mimeType);
}

View File

@ -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. <p>
*
* <b>DataHandler and the Transferable Interface</b><p>
* 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.<p>
*
* <b>DataHandler and CommandMaps</b><p>
* The DataHandler keeps track of the current CommandMap that it uses to
* service requests for commands (<code>getCommand</code>,
* <code>getAllCommands</code>, <code>getPreferredCommands</code>).
* Each instance of a DataHandler may have a CommandMap associated with
* it using the <code>setCommandMap</code> method. If a CommandMap was
* not set, DataHandler calls the <code>getDefaultCommandMap</code>
* method in CommandMap and uses the value it returns. See
* <i>CommandMap</i> for more information. <p>
*
* <b>DataHandler and URLs</b><p>
* 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 <code>DataHandler</code> 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 <code>DataHandler</code> 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 <code>DataHandler</code> instance referencing a URL.
* The DataHandler internally creates a <code>URLDataSource</code>
* 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.
* <p>
* 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 <b>not</b>
* 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 <code>DataSource.getName</code> method, otherwise it
* returns <i>null</i>.
*
* @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 <i>full</i>
* 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. <p>
*
* For DataHandlers instantiated with a DataSource, the DataHandler
* calls the <code>DataSource.getInputStream</code> method and
* returns the result to the caller.
* <p>
* 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 <code>writeTo</code> 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.<p>
*
* @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 <code>OutputStream</code>.<p>
*
* If the DataHandler was created with a DataSource, writeTo
* retrieves the InputStream and copies the bytes from the
* InputStream to the OutputStream passed in.
* <p>
* 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
* <code>writeTo</code> method on the <code>DataContentHandler</code>.
*
* @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 <code>getOutputStream</code> method is called.
* Otherwise, <code>null</code> 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. <p>
*
* 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.<p>
*
* 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
* <code>getTransferDataFlavors</code> method. <p>
*
* If a DataContentHandler can <i>not</i> 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 <code>java.io.InputStream</code> 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.<p>
*
* This method iterates through the DataFlavors returned from
* <code>getTransferDataFlavors</code>, 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.<p>
*
* <b>For DataHandler's created with DataSources or URLs:</b><p>
*
* 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 <code>getTransferData</code>
* method. If the DataHandler fails to locate a DataContentHandler
* and the flavor specifies this object's MIME type and the
* <code>java.io.InputStream</code> class, this object's InputStream
* is returned.
* Otherwise it throws an UnsupportedFlavorException. <p>
*
* <b>For DataHandler's created with Objects:</b><p>
*
* 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 <code>null</code> causes the CommandMap to revert
* to the CommandMap returned by the
* <code>CommandMap.getDefaultCommandMap</code> method.
* Changing the CommandMap, or setting it to <code>null</code>,
* 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 <i>preferred</i> commands for this type of data.
* This method calls the <code>getPreferredCommands</code> 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 <code>getAllCommands</code> 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 <i>cmdName</i>. 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 <code>getCommand</code> 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. <p>
*
* If the DataHandler was instantiated with an object, return
* the object. <p>
*
* 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
* <code>DataContentHandler</code> 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.
* <p>
* This method calls the CommandInfo's <code>getCommandObject</code>
* method with the <code>ClassLoader</code> used to load
* the <code>javax.activation.DataHandler</code> 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: <p>
*
* If a DataContentHandlerFactory is set, use it.
* Otherwise look for an object to serve DCH in the
* following order: <p>
*
* 1) if a factory is set, use it <p>
* 2) if a CommandMap is set, use it <p>
* 3) use the default CommandMap <p>
*
* 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.
* <p>
* 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 <code>InputStream</code> representing this object.
* @return the <code>InputStream</code>
*/
public InputStream getInputStream() throws IOException {
return dataHandler.getInputStream();
}
/**
* Returns the <code>OutputStream</code> for this object.
* @return the <code>OutputStream</code>
*/
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 <i>private</i> 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 <code>DataContentHandler</code>.
* @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 <i>private</i> 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 <code>DataContentHandler</code>.
* @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);
}
}

View File

@ -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 <code>InputStreams</code> and
* <code>OutputStreams</code> where appropriate.
*
* @since 1.6
*/
public interface DataSource {
/**
* This method returns an <code>InputStream</code> representing
* the data and throws the appropriate exception if it can
* not do so. Note that a new <code>InputStream</code> 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 <code>OutputStream</code> where the
* data can be written and throws the appropriate exception if it can
* not do so. Note that a new <code>OutputStream</code> 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 <i>name</i> 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();
}

View File

@ -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. <p>
*
* <b>FileDataSource Typing Semantics</b><p>
*
* The FileDataSource class delegates data typing of files
* to an object subclassed from the FileTypeMap class.
* The <code>setFileTypeMap</code> 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. <i>Note:
* The file will not actually be opened until a method is
* called that requires the file to be opened.</i>
*
* @param file the file
*/
public FileDataSource(File file) {
_file = file; // save the file Object...
}
/**
* Creates a FileDataSource from
* the specified path name. <i>Note:
* The file will not actually be opened until a method is
* called that requires the file to be opened.</i>
*
* @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 <code>getDefaultFileTypeMap</code> method on
* FileTypeMap to acquire a default FileTypeMap. <i>Note: By
* default, the FileTypeMap used will be a MimetypesFileTypeMap.</i>
*
* @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 <i>name</i> 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;
}
}

View File

@ -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
* <code>MimetypesFileTypeMap</code>.
*
* @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;
}
}

View File

@ -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
* (<A HREF="http://www.ietf.org/rfc/rfc1524.txt">RFC 1524</A>).
* The MailcapCommandMap can be configured both programmatically
* and via configuration files.
* <p>
* <b>Mailcap file search order:</b><p>
* 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:
* <p>
* <ol>
* <li> Programatically added entries to the MailcapCommandMap instance.
* <li> The file <code>.mailcap</code> in the user's home directory.
* <li> The file &lt;<i>java.home</i>&gt;<code>/lib/mailcap</code>.
* <li> The file or resources named <code>META-INF/mailcap</code>.
* <li> The file or resource named <code>META-INF/mailcap.default</code>
* (usually found only in the <code>activation.jar</code> file).
* </ol>
* <p>
* <b>Mailcap file format:</b><p>
*
* Mailcap files must conform to the mailcap
* file specification (RFC 1524, <i>A User Agent Configuration Mechanism
* For Multimedia Mail Format Information</i>).
* The file format consists of entries corresponding to
* particular MIME types. In general, the specification
* specifies <i>applications</i> 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.<p>
*
* When a mailcap file is
* parsed, the MailcapCommandMap recognizes certain parameter signatures,
* specifically those parameter names that begin with <code>x-java-</code>.
* The MailcapCommandMap uses this signature to find
* command entries for inclusion into its registries.
* Parameter names with the form <code>x-java-&lt;name></code>
* are read by the MailcapCommandMap as identifying a command
* with the name <i>name</i>. When the <i>name</i> is <code>
* content-handler</code> the MailcapCommandMap recognizes the class
* signified by this parameter as a <i>DataContentHandler</i>.
* 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: <code>x-java-view=com.foo.ViewBean</code>.<p>
*
* When the command name is <code>fallback-entry</code>, the value of
* the command may be <code>true</code> or <code>false</code>. An
* entry for a MIME type that includes a parameter of
* <code>x-java-fallback-entry=true</code> 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 <code>text/*; ;
* x-java-fallback-entry=true; x-java-view=com.sun.TextViewer</code>
* 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.<p>
*
* MailcapCommandMap aware mailcap files have the
* following general form:<p>
* <code>
* # Comments begin with a '#' and continue to the end of the line.<br>
* &lt;mime type>; ; &lt;parameter list><br>
* # Where a parameter list consists of one or more parameters,<br>
* # where parameters look like: x-java-view=com.sun.TextViewer<br>
* # and a parameter list looks like: <br>
* text/plain; ; x-java-view=com.sun.TextViewer; x-java-edit=com.sun.TextEdit
* <br>
* # Note that mailcap entries that do not contain 'x-java' parameters<br>
* # and comply to RFC 1524 are simply ignored:<br>
* image/gif; /usr/dt/bin/sdtimage %s<br>
*
* </code>
* <p>
*
* @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 <i>mailcap</i> file.
*
* @param fileName The name of the <i>mailcap</i> 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 <i>InputStream</i>
* containing a mailcap file.
*
* @param is InputStream of the <i>mailcap</i> 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
* <i>Mailcap file search order</i>.<p>
*
* 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 <code>cmdName</code> 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.<p>
*
* 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
* <A HREF="http://www.ietf.org/rfc/rfc1524.txt">RFC 1524</A>
* 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);
}
*/
}

View File

@ -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();
}
}
*/
}

View File

@ -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();
}
}

View File

@ -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);
}
}

View File

@ -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 <code>.mime.types</code> format. <p>
*
* <b>MIME types file search order:</b><p>
* 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:
* <p>
* <ol>
* <li> Programmatically added entries to the MimetypesFileTypeMap instance.
* <li> The file <code>.mime.types</code> in the user's home directory.
* <li> The file &lt;<i>java.home</i>&gt;<code>/lib/mime.types</code>.
* <li> The file or resources named <code>META-INF/mime.types</code>.
* <li> The file or resource named <code>META-INF/mimetypes.default</code>
* (usually found only in the <code>activation.jar</code> file).
* </ol>
* <p>
* <b>MIME types file format:</b><p>
*
* <code>
* # comments begin with a '#'<br>
* # the format is &lt;mime type> &lt;space separated file extensions><br>
* # for example:<br>
* text/plain txt text TXT<br>
* # this would map file.txt, file.text, and file.TXT to<br>
* # the mime type "text/plain"<br>
* </code>
*
* @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
* <code>getContentType(f.getName())</code>.
*
* @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
* <i>MIME types file search order</i>.
* 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);
}
*/
}

View File

@ -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();
}
}
}

View File

@ -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 <code>URL</code>
* 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. <i>NOTE: The
* DataHandler object creates a URLDataSource internally,
* when it is constructed with a URL.</i>
*
* @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 <code>URLConnection.getContentType</code> method
* after retrieving a URLConnection object.
* <i>Note: this method attempts to call the <code>openConnection</code>
* 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.</i>
*
* @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 <code>getFile</code> 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
* <code>openStream</code> 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;
}
}

View File

@ -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);
}
}

View File

@ -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");
}

View File

@ -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.
*
* <p>
* 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.
*
* <p>
* 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;
}

View File

@ -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 <? extends Annotation> clazz);
/**
* Adds an annotation to this program element
* and returns a type-safe writer to fill in the values of such annotations.
*/
<W extends JAnnotationWriter> W annotate2(Class<W> clazz);
/**
* Read-only live view of all annotations on this {@link JAnnotatable}
*
* @return
* Can be empty but never null.
*/
Collection<JAnnotationUse> annotations();
}

View File

@ -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
*
* <p>
* 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<JAnnotationValue> values = new ArrayList<JAnnotationValue>();
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<? extends Annotation> 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 extends JAnnotationWriter> W annotate2(Class<W> clazz) {
return TypedAnnotationWriter.create(clazz,this);
}
/**
* {@link JAnnotatable#annotations()}
*/
@SuppressWarnings("unchecked")
public Collection<JAnnotationUse> 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.<JAnnotationUse>unmodifiableList((List)values);
}
/**
* Adds an annotation member to this annotation array
* This can be used for e.g &#64;XmlCollection(values= &#64;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('}');
}
}

View File

@ -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);
}
}

View File

@ -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<String,JAnnotationValue> memberValues;
JAnnotationUse(JClass clazz){
this.clazz = clazz;
}
public JClass getAnnotationClass() {
return clazz;
}
public Map<String, JAnnotationValue> 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<String, JAnnotationValue>();
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<? extends Annotation> 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
* <pre>
* &#64;XmlCollectionItem(type=Integer.class);
* <pre>
* For adding a value of Class<? extends Annotation>
* @link
* #annotationParam(java.lang.String, java.lang.Class<? extends java.lang.annotation.Annotation>)
* @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 &#64;XmlCollection(values= &#64;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 &#64;XmlCollection(values= &#64;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 <? extends Annotation> 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<String, JAnnotationValue> 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");
}
}

View File

@ -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 {
}

View File

@ -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.
*
* <p>
* 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.
*
* <p>
* The type parameter 'A' represents the
* @author Kohsuke Kawaguchi
*/
public interface JAnnotationWriter<A extends Annotation> {
/**
* Gets the underlying annotation use object to which we are writing.
*/
JAnnotationUse getAnnotationUse();
/**
* The type of the annotation that this writer is writing.
*/
Class<A> getAnnotationType();
}

View File

@ -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);
}
}

View File

@ -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<JExpression> exprs = null;
/**
* Add an element to the array initializer
*/
public JArray add(JExpression e) {
if (exprs == null)
exprs = new ArrayList<JExpression>();
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<arrayCount; i++ )
f.p("[]");
if ((size == null) || (exprs != null))
f.p('{');
if (exprs != null) {
f.g(exprs);
} else {
f.p(' ');
}
if ((size == null) || (exprs != null))
f.p('}');
}
}

View File

@ -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;
import java.util.Iterator;
import java.util.Collections;
import java.util.List;
/**
* Array class.
*
* @author
* Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
*/
final class JArrayClass extends JClass {
// array component type
private final JType componentType;
JArrayClass( JCodeModel owner, JType component ) {
super(owner);
this.componentType = component;
}
public String name() {
return componentType.name()+"[]";
}
public String fullName() {
return componentType.fullName()+"[]";
}
public String binaryName() {
return componentType.binaryName()+"[]";
}
public void generate(JFormatter f) {
f.g(componentType).p("[]");
}
public JPackage _package() {
return owner().rootPackage();
}
public JClass _extends() {
return owner().ref(Object.class);
}
public Iterator<JClass> _implements() {
return Collections.<JClass>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<JClass> bindings) {
if( componentType.isPrimitive() )
return this;
JClass c = ((JClass)componentType).substituteParams(variables,bindings);
if(c==componentType)
return this;
return new JArrayClass(owner(),c);
}
}

View File

@ -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);
}
}

View File

@ -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();
}
}

View File

@ -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);
}

View File

@ -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);
}
}

View File

@ -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.
*
* <p>
* {@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<Object> content = new ArrayList<Object>();
/**
* 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<Object> getContents() {
return Collections.unmodifiableList(content);
}
private <T> 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
* <code>continue</code> and <code>break</code> 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.
*
* <p>
* Specified string is printed as-is.
* This is useful as a short-cut.
*
* <p>
* For example, you can invoke this method as:
* <code>directStatement("a=b+c;")</code>.
*/
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();
}
}

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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(')');
}
}

View File

@ -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);
}
}

View File

@ -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.
*
* <p>
* 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
* <code>java.lang.String</code>.
*/
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 <tt>null</tt> 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<JClass> _implements();
/**
* Iterates all the type parameters of this class/interface.
*
* <p>
* For example, if this {@link JClass} represents
* <code>Set&lt;T></code>, 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 <tt>this</tt>.
*/
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.
* <p>
* 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<JClass> itfs = derived._implements();
while( itfs.hasNext() )
if( this.isAssignableFrom(itfs.next()) )
return true;
}
return false;
}
/**
* Gets the parameterization of the given base type.
*
* <p>
* For example, given the following
* <pre><xmp>
* interface Foo<T> extends List<List<T>> {}
* interface Bar extends Foo<String> {}
* </xmp></pre>
* This method works like this:
* <pre><xmp>
* 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>
* </xmp></pre>
*
* @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<JClass> 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.
*
* <p>
* <code>.narrow(X)</code> builds <code>Set&lt;X></code> from <code>Set</code>.
*/
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<clazz.length; i++ )
r[i] = owner().ref(clazz[i]);
return narrow(r);
}
/**
* "Narrows" a generic class to a concrete class by specifying
* a type argument.
*
* <p>
* <code>.narrow(X)</code> builds <code>Set&lt;X></code> from <code>Set</code>.
*/
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<? extends JClass> clazz ) {
return new JNarrowedClass(this,new ArrayList<JClass>(clazz));
}
/**
* If this class is parameterized, return the type parameter of the given index.
*/
public List<JClass> 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.
*
* <p>
* For example, when this class is Map&lt;String,Map&lt;V>>,
* (where V then doing
* substituteParams( V, Integer ) returns a {@link JClass}
* for <code>Map&lt;String,Map&lt;Integer>></code>.
*
* <p>
* This method needs to work recursively.
*/
protected abstract JClass substituteParams( JTypeVar[] variables, List<JClass> 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('}');
}
}

View File

@ -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;
}
}

View File

@ -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<JDefinedClass> 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.
*
* <p>
* If <tt>this.isPackage()</tt>, then return <tt>this</tt>.
*/
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;
}

View File

@ -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.
*
* <p>
* Here's your typical CodeModel application.
*
* <pre>
* JCodeModel cm = new JCodeModel();
*
* // generate source code by populating the 'cm' tree.
* cm._class(...);
* ...
*
* // write them out
* cm.build(new File("."));
* </pre>
*
* <p>
* Every CodeModel node is always owned by one {@link JCodeModel} object
* at any given time (which can be often accesesd by the <tt>owner()</tt> 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.
*
*
* <h2>Where to go from here?</h2>
* <p>
* 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<String,JPackage> packages = new HashMap<String,JPackage>();
/** All JReferencedClasses are pooled here. */
private final HashMap<Class<?>,JReferencedClass> refClasses = new HashMap<Class<?>,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<JPackage> 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.
*
* <p>
* 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 <code>build(destDir,destDir,System.out)</code>.
*
* @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 <code>build(destDir,System.out)</code>.
*/
public void build( File destDir ) throws IOException {
build(destDir,System.out);
}
/**
* A convenience method for <code>build(srcDir,resourceDir,System.out)</code>.
*/
public void build( File srcDir, File resourceDir ) throws IOException {
build(srcDir,resourceDir,System.out);
}
/**
* A convenience method for <code>build(out,out)</code>.
*/
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.
*
* <p>
* 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.
*
* <p>
* 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.
*
* <p>
* 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<s.length()) {
char ch = s.charAt(idx);
if(Character.isJavaIdentifierStart(ch)
|| Character.isJavaIdentifierPart(ch)
|| ch=='.')
idx++;
else
break;
}
JClass clazz = ref(s.substring(start,idx));
return parseSuffix(clazz);
}
/**
* Parses additional left-associative suffixes, like type arguments
* and array specifiers.
*/
private JClass parseSuffix(JClass clazz) throws ClassNotFoundException {
if(idx==s.length())
return clazz; // hit EOL
char ch = s.charAt(idx);
if(ch=='<')
return parseSuffix(parseArguments(clazz));
if(ch=='[') {
if(s.charAt(idx+1)==']') {
idx+=2;
return parseSuffix(clazz.array());
}
throw new IllegalArgumentException("Expected ']' but found "+s.substring(idx+1));
}
return clazz;
}
/**
* Skips whitespaces
*/
private void ws() {
while(Character.isWhitespace(s.charAt(idx)) && idx<s.length())
idx++;
}
/**
* Parses '&lt;T1,T2,...,Tn>'
*
* @return the index of the character next to '>'
*/
private JClass parseArguments(JClass rawType) throws ClassNotFoundException {
if(s.charAt(idx)!='<')
throw new IllegalArgumentException();
idx++;
List<JClass> args = new ArrayList<JClass>();
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.
*
* <p>
* JReferencedClass is kept in a pool so that they are shared.
* There is one pool for each JCodeModel object.
*
* <p>
* 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<JClass> _implements() {
final Class<?>[] interfaces = _class.getInterfaces();
return new Iterator<JClass>() {
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<JClass> 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 <tt>Integer.class</tt>)
*/
public static final Map<Class<?>,Class<?>> primitiveToBox;
/**
* The reverse look up for {@link #primitiveToBox}
*/
public static final Map<Class<?>,Class<?>> boxToPrimitive;
static {
Map<Class<?>,Class<?>> m1 = new HashMap<Class<?>,Class<?>>();
Map<Class<?>,Class<?>> m2 = new HashMap<Class<?>,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<?>, Class<?>> e : m1.entrySet())
m2.put(e.getValue(),e.getKey());
boxToPrimitive = Collections.unmodifiableMap(m1);
primitiveToBox = Collections.unmodifiableMap(m2);
}
}

View File

@ -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.
*
* <p>
* 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.
*
* <p>
* Values can be added through the various append methods one by one or in a bulk.
*
* @author Kohsuke Kawaguchi
*/
public class JCommentPart extends ArrayList<Object> {
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<Object> 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);
}
}
}

View File

@ -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 <tt>... else if(...) ...</tt> 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();
}
}

View File

@ -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();
}
}

View File

@ -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);
}

View File

@ -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/....
*
* <p>
* This class models a declaration, and since a declaration can be always
* used as a reference, it inherits {@link JClass}.
*
* <h2>Where to go from here?</h2>
* <p>
* 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<JClass> interfaces = new TreeSet<JClass>();
/** Fields keyed by their names. */
/*package*/ final Map<String,JFieldVar> fields = new LinkedHashMap<String,JFieldVar>();
/** 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<JMethod> constructors = new ArrayList<JMethod>();
/** Set of methods that are members of this class */
private final List<JMethod> methods = new ArrayList<JMethod>();
/**
* 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<String,JDefinedClass> 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<String,JEnumConstant> enumConstantsByName = new LinkedHashMap<String,JEnumConstant>();
/**
* Annotations on this variable. Lazily created.
*/
private List<JAnnotationUse> 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<JClass> _implements() {
return interfaces.iterator();
}
/**
* JClass name accessor.
*
* <p>
* For example, for <code>java.util.List</code>, this method
* returns <code>"List"</code>"
*
* @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<String,JFieldVar> 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<JMethod> 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<JMethod> 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.
*
* <p>
* 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<JDefinedClass> classes() {
if(classes==null)
return Collections.<JDefinedClass>emptyList().iterator();
else
return classes.values().iterator();
}
private Map<String,JDefinedClass> getClasses() {
if(classes==null)
classes = new TreeMap<String,JDefinedClass>();
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<JClass> bindings) {
return this;
}
/** Adding ability to annotate a class
* @param clazz
* The annotation class to annotate the class with
*/
public JAnnotationUse annotate(Class <? extends Annotation> 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>();
JAnnotationUse a = new JAnnotationUse(clazz);
annotations.add(a);
return a;
}
public <W extends JAnnotationWriter> W annotate2(Class<W> clazz) {
return TypedAnnotationWriter.create(clazz,this);
}
/**
* {@link JAnnotatable#annotations()}
*/
public Collection<JAnnotationUse> annotations() {
if (annotations == null)
annotations = new ArrayList<JAnnotationUse>();
return Collections.unmodifiableCollection(annotations);
}
/**
* @return
* the current modifiers of this class.
* Always return non-null valid object.
*/
public JMods mods() {
return mods;
}
}

View File

@ -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<JClass> _implements() {
return Collections.<JClass>emptyList().iterator();
}
public boolean isInterface() {
return false;
}
public boolean isAbstract() {
return false;
}
protected JClass substituteParams(JTypeVar[] variables, List<JClass> bindings) {
return this;
}
}

View File

@ -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();
}
}

View File

@ -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.
*
* <p>
* 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<String,JCommentPart> atParams = new HashMap<String,JCommentPart>();
/** list of xdoclets */
private final Map<String,Map<String,String>> atXdoclets = new HashMap<String,Map<String,String>>();
/** list of @throws tags */
private final Map<JClass,JCommentPart> atThrows = new HashMap<JClass,JCommentPart>();
/**
* 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<? extends Throwable> 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<String,String> addXdoclet(String name) {
Map<String,String> p = atXdoclets.get(name);
if(p==null)
atXdoclets.put(name,p=new HashMap<String,String>());
return p;
}
/**
* add an xdoclet.
*/
public Map<String,String> addXdoclet(String name, Map<String,String> attributes) {
Map<String,String> p = atXdoclets.get(name);
if(p==null)
atXdoclets.put(name,p=new HashMap<String,String>());
p.putAll(attributes);
return p;
}
/**
* add an xdoclet.
*/
public Map<String,String> addXdoclet(String name, String attribute, String value) {
Map<String,String> p = atXdoclets.get(name);
if(p==null)
atXdoclets.put(name,p=new HashMap<String,String>());
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<String,JCommentPart> 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<JClass,JCommentPart> 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<String,Map<String,String>> e : atXdoclets.entrySet()) {
f.p(" * @").p(e.getKey());
if (e.getValue() != null) {
for (Map.Entry<String,String> a : e.getValue().entrySet()) {
f.p(" ").p(a.getKey()).p("= \"").p(a.getValue()).p("\"");
}
}
f.nl();
}
f.p(" */").nl();
}
private static final String INDENT = " * ";
}

View File

@ -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();
}

View File

@ -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<JAnnotationUse> annotations = null;
/**
* List of the constructor argument expressions.
* Lazily constructed.
*/
private List<JExpression> 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<JExpression>();
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>();
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 <? extends Annotation> clazz){
return annotate(type.owner().ref(clazz));
}
public <W extends JAnnotationWriter> W annotate2(Class<W> clazz) {
return TypedAnnotationWriter.create(clazz,this);
}
/**
* {@link JAnnotatable#annotations()}
*/
public Collection<JAnnotationUse> annotations() {
if (annotations == null)
annotations = new ArrayList<JAnnotationUse>();
return Collections.unmodifiableList(annotations);
}
public void declare(JFormatter f) {
if( jdoc != null )
f.nl().g( jdoc );
if (annotations != null) {
for( int i=0; i<annotations.size(); i++ )
f.g(annotations.get(i)).nl();
}
f.id(name);
if(args!=null) {
f.p('(').g(args).p(')');
}
}
public void generate(JFormatter f) {
f.t(type).p('.').p(name);
}
}

View File

@ -0,0 +1,289 @@
/*
* 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;
/**
* Factory methods that generate various {@link JExpression}s.
*/
public abstract class JExpr {
/**
* This class is not instanciable.
*/
private JExpr() { }
public static JExpression assign(JAssignmentTarget lhs, JExpression rhs) {
return new JAssignment(lhs, rhs);
}
public static JExpression assignPlus(JAssignmentTarget lhs, JExpression rhs) {
return new JAssignment(lhs, rhs, "+");
}
public static JInvocation _new(JClass c) {
return new JInvocation(c);
}
public static JInvocation _new(JType t) {
return new JInvocation(t);
}
public static JInvocation invoke(String method) {
return new JInvocation((JExpression)null, method);
}
public static JInvocation invoke(JMethod method) {
return new JInvocation((JExpression)null,method);
}
public static JInvocation invoke(JExpression lhs, JMethod method) {
return new JInvocation(lhs, method);
}
public static JInvocation invoke(JExpression lhs, String method) {
return new JInvocation(lhs, method);
}
public static JFieldRef ref(String field) {
return new JFieldRef((JExpression)null, field);
}
public static JFieldRef ref(JExpression lhs, JVar field) {
return new JFieldRef(lhs,field);
}
public static JFieldRef ref(JExpression lhs, String field) {
return new JFieldRef(lhs, field);
}
public static JFieldRef refthis(String field) {
return new JFieldRef(null, field, true);
}
public static JExpression dotclass(final JClass cl) {
return new JExpressionImpl() {
public void generate(JFormatter f) {
JClass c;
if(cl instanceof JNarrowedClass)
c = ((JNarrowedClass)cl).basis;
else
c = cl;
f.g(c).p(".class");
}
};
}
public static JArrayCompRef component(JExpression lhs, JExpression index) {
return new JArrayCompRef(lhs, index);
}
public static JCast cast(JType type, JExpression expr) {
return new JCast(type, expr);
}
public static JArray newArray(JType type) {
return newArray(type,null);
}
/**
* Generates {@code new T[size]}.
*
* @param type
* The type of the array component. 'T' or {@code new T[size]}.
*/
public static JArray newArray(JType type, JExpression size) {
// you cannot create an array whose component type is a generic
return new JArray(type.erasure(), size);
}
/**
* Generates {@code new T[size]}.
*
* @param type
* The type of the array component. 'T' or {@code new T[size]}.
*/
public static JArray newArray(JType type, int size) {
return newArray(type,lit(size));
}
private static final JExpression __this = new JAtom("this");
/**
* Returns a reference to "this", an implicit reference
* to the current object.
*/
public static JExpression _this() { return __this; }
private static final JExpression __super = new JAtom("super");
/**
* Returns a reference to "super", an implicit reference
* to the super class.
*/
public static JExpression _super() { return __super; }
/* -- Literals -- */
private static final JExpression __null = new JAtom("null");
public static JExpression _null() {
return __null;
}
/**
* Boolean constant that represents <code>true</code>
*/
public static final JExpression TRUE = new JAtom("true");
/**
* Boolean constant that represents <code>false</code>
*/
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<c ) {
// not printable. use Unicode escape
sb.append("\\u");
String hex = Integer.toHexString(((int)c)&0xFFFF);
for( int k=hex.length(); k<4; k++ )
sb.append('0');
sb.append(hex);
} else {
sb.append(c);
}
}
}
sb.append(quote);
return sb.toString();
}
public static JExpression lit(char c) {
return new JAtom(quotify('\'', "" + c));
}
public static JExpression lit(String s) {
return new JStringLiteral(s);
}
/**
* Creates an expression directly from a source code fragment.
*
* <p>
* This method can be used as a short-cut to create a JExpression.
* For example, instead of <code>_a.gt(_b)</code>, you can write
* it as: <code>JExpr.direct("a>b")</code>.
*
* <p>
* 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(')');
}
};
}
}

View File

@ -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.
*
* <p>
* Unlike most of CodeModel, JExpressions are built bottom-up (
* meaning you start from leaves and then gradually build compliated expressions
* by combining them.)
*
* <p>
* {@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
* <tt>JExpr.lit(5).add(JExpr.lit(2))</tt>
*/
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]&lt;&lt;[right]"
*/
JExpression shl(JExpression right);
/**
* Returns "[this]>>[right]"
*/
JExpression shr(JExpression right);
/**
* Returns "[this]>>>[right]"
*/
JExpression shrz(JExpression right);
/** Bit-wise AND '&amp;'. */
JExpression band(JExpression right);
/** Bit-wise OR '|'. */
JExpression bor(JExpression right);
/** Logical AND '&amp;&amp;'. */
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);
}

View File

@ -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 <tt>'!x'</tt>.
*/
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);
}
}

View File

@ -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);
}
}

View File

@ -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 );
}
}

View File

@ -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();
}
}

View File

@ -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<Object> inits = new ArrayList<Object>();
private JExpression test = null;
private List<JExpression> updates = new ArrayList<JExpression>();
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();
}
}

View File

@ -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<String,ReferenceList> collectedReferences;
/** set of imported types (including package java types, eventhough we won't generate imports for them) */
private HashSet<JClass> 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<String,ReferenceList>();
//ids = new HashSet<String>();
importedClasses = new HashSet<JClass>();
}
/**
* 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<Bar> test;"
if(c2=='(') // but not "new Foo<Bar>()"
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.
*
* <p>
* 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<? extends JGenerable> 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<JClass> classes = new ArrayList<JClass>();
/** 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<JDefinedClass> 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<JClass> 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;
}
}
}

View File

@ -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);
}

View File

@ -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();
}

View File

@ -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<JTypeVar> 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<JTypeVar>(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()]);
}
}

View File

@ -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<JExpression> args = new ArrayList<JExpression>();
/**
* 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
* <code>new int[]{1,2,3,4,5}</code>.
*/
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();
}
}

View File

@ -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;
}
/**
* <b>Experimental API:</b> 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)
* <p>
* Although this method only works for English words, it handles non-English
* words gracefully (by just returning it as-is.) For example, &#x65E5;&#x672C;&#x8A9E;
* will be returned as-is without modified, not "&#x65E5;&#x672C;&#x8A9E;s"
* <p>
* 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<word.length(); i++ ) {
char ch = word.charAt(i);
if(ch >=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<String> reservedKeywords = new HashSet<String>();
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<source.length; i+=2 ) {
TABLE[i/2] = new Entry(source[i],source[i+1]);
}
}
}

View File

@ -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;
/**
* Label that can be used for continue and break.
*
* @author
* Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
*/
public class JLabel implements JStatement {
final String label;
/**
* JBreak constructor
*
* @param _label
* break label or null.
*/
JLabel( String _label ) {
this.label = _label;
}
public void state(JFormatter f) {
f.p(label+':').nl();
}
}

View File

@ -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.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import java.util.Collections;
import java.util.Collection;
import com.sun.codemodel.internal.util.ClassNameComparator;
/**
* Java method.
*/
public class JMethod extends JGenerifiableImpl implements JDeclaration, JAnnotatable, JDocCommentable {
/**
* Modifiers for this method
*/
private JMods mods;
/**
* Return type for this method
*/
private JType type = null;
/**
* Name of this method
*/
private String name = null;
/**
* List of parameters for this method's declaration
*/
private final List<JVar> params = new ArrayList<JVar>();
/**
* Set of exceptions that this method may throw.
* A set instance lazily created.
*/
private Set<JClass> _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<JAnnotationUse> 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<JClass> getThrows() {
if(_throws==null)
_throws = new TreeSet<JClass>(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<? extends Throwable> 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<JVar> params() {
return Collections.<JVar>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>();
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 <? extends Annotation> clazz){
return annotate(owner().ref(clazz));
}
public <W extends JAnnotationWriter> W annotate2(Class<W> clazz) {
return TypedAnnotationWriter.create(clazz,this);
}
public Collection<JAnnotationUse> annotations() {
if (annotations == null)
annotations = new ArrayList<JAnnotationUse>();
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();
}
}

View File

@ -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;
}

View File

@ -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();
}
}

View File

@ -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&lt;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<JClass> args;
JNarrowedClass(JClass basis, JClass arg) {
this(basis,Collections.singletonList(arg));
}
JNarrowedClass(JClass basis, List<JClass> args) {
super(basis.owner());
this.basis = basis;
assert !(basis instanceof JNarrowedClass);
this.args = args;
}
@Override
public JClass narrow( JClass clazz ) {
List<JClass> newArgs = new ArrayList<JClass>(args);
newArgs.add(clazz);
return new JNarrowedClass(basis,newArgs);
}
@Override
public JClass narrow( JClass... clazz ) {
List<JClass> newArgs = new ArrayList<JClass>(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<JClass> _implements() {
return new Iterator<JClass>() {
private final Iterator<JClass> 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<JClass> bindings) {
JClass b = basis.substituteParams(variables,bindings);
boolean different = b!=basis;
List<JClass> clazz = new ArrayList<JClass>(args.size());
for( int i=0; i<clazz.size(); i++ ) {
JClass c = args.get(i).substituteParams(variables,bindings);
clazz.set(i,c);
different |= c != args.get(i);
}
if(different)
return new JNarrowedClass(b,clazz);
else
return this;
}
@Override
public List<JClass> getTypeParameters() {
return args;
}
}

View File

@ -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".
*
* <p>
* 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<JClass> _implements() {
return Collections.<JClass>emptyList().iterator();
}
public boolean isInterface() { return false; }
public boolean isAbstract() { return false; }
protected JClass substituteParams(JTypeVar[] variables, List<JClass> bindings) {
return this;
}
}

View File

@ -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 <tt>'!x'</tt>.
*/
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);
}
}

View File

@ -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<JPackage>, 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<String,JDefinedClass> classes = new TreeMap<String,JDefinedClass>();
/**
* List of resources files inside this package.
*/
private final Set<JResourceFile> resources = new HashSet<JResourceFile>();
/**
* 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<String,JDefinedClass> upperCaseClassMap;
/**
* Lazily created list of package annotations.
*/
private List<JAnnotationUse> 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<String,JDefinedClass>();
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<JResourceFile> 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<JDefinedClass> classes() {
return classes.values().iterator();
}
/**
* Checks if a given name is already defined as a class/interface
*/
public boolean isDefined(String classLocalName) {
Iterator<JDefinedClass> 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
* <code>"java.lang"</code>
*/
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>();
JAnnotationUse a = new JAnnotationUse(clazz);
annotations.add(a);
return a;
}
public JAnnotationUse annotate(Class<? extends Annotation> clazz) {
return annotate(owner.ref(clazz));
}
public <W extends JAnnotationWriter> W annotate2(Class<W> clazz) {
return TypedAnnotationWriter.create(clazz,this);
}
public Collection<JAnnotationUse> annotations() {
if (annotations == null)
annotations = new ArrayList<JAnnotationUse>();
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));
}
}

View File

@ -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 <tt>this</tt>.
*/
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 <code>new Float(x)</code> 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);
}
}

View File

@ -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.
*
* <p>
* 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;
}

View File

@ -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();
}
}

View File

@ -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);
}

View File

@ -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));
}
}

View File

@ -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<JCase> cases = new ArrayList<JCase>();
/**
* 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<JCase> 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();
}
}

View File

@ -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();
}
}

View File

@ -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<JCatchBlock> catches = new ArrayList<JCatchBlock>();
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();
}
}

View File

@ -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<JType> {
/**
* 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 <tt>this</tt>.
*
* <p>
* 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 <tt>this</tt>.
*
* <p>
* 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);
}
}
}

View File

@ -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.
*
* <p>
* 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<JClass> _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<JClass> bindings) {
for(int i=0;i<variables.length;i++)
if(variables[i]==this)
return bindings.get(i);
return this;
}
public void generate(JFormatter f) {
f.id(name);
}
}

View File

@ -0,0 +1,109 @@
/*
* 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;
/**
* Represents a wildcard type like "? extends Foo".
*
* <p>
* Instances of this class can be obtained from {@link JClass#wildcard()}
*
* TODO: extend this to cover "? super Integer".
*
* <p>
* 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.
*
* <p>
* 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<JClass> _implements() {
return bound._implements();
}
public boolean isInterface() {
return false;
}
public boolean isAbstract() {
return false;
}
protected JClass substituteParams(JTypeVar[] variables, List<JClass> 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);
}
}

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