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

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

View File

@@ -0,0 +1,51 @@
/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.accessibility;
/**
* Interface Accessible is the main interface for the accessibility package.
* All components that support
* the accessibility package must implement this interface.
* It contains a single method, {@link #getAccessibleContext}, which
* returns an instance of the class {@link AccessibleContext}.
*
* @author Peter Korn
* @author Hans Muller
* @author Willie Walker
*/
public interface Accessible {
/**
* Returns the AccessibleContext associated with this object. In most
* cases, the return value should not be null if the object implements
* interface Accessible. If a component developer creates a subclass
* of an object that implements Accessible, and that subclass
* is not Accessible, the developer should override the
* getAccessibleContext method to return null.
* @return the AccessibleContext associated with this object
*/
public AccessibleContext getAccessibleContext();
}

View File

@@ -0,0 +1,113 @@
/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.accessibility;
/**
* The AccessibleAction interface should be supported by any object
* that can perform one or more actions. This interface
* provides the standard mechanism for an assistive technology to determine
* what those actions are as well as tell the object to perform them.
* Any object that can be manipulated should support this
* interface. Applications can determine if an object supports the
* AccessibleAction interface by first obtaining its AccessibleContext (see
* {@link Accessible}) and then calling the {@link AccessibleContext#getAccessibleAction}
* method. If the return value is not null, the object supports this interface.
*
* @see Accessible
* @see Accessible#getAccessibleContext
* @see AccessibleContext
* @see AccessibleContext#getAccessibleAction
*
* @author Peter Korn
* @author Hans Muller
* @author Willie Walker
* @author Lynn Monsanto
*/
public interface AccessibleAction {
/**
* An action which causes a tree node to
* collapse if expanded and expand if collapsed.
* @since 1.5
*/
public static final String TOGGLE_EXPAND =
new String ("toggleexpand");
/**
* An action which increments a value.
* @since 1.5
*/
public static final String INCREMENT =
new String ("increment");
/**
* An action which decrements a value.
* @since 1.5
*/
public static final String DECREMENT =
new String ("decrement");
/**
* An action which causes a component to execute its default action.
* @since 1.6
*/
public static final String CLICK = new String("click");
/**
* An action which causes a popup to become visible if it is hidden and
* hidden if it is visible.
* @since 1.6
*/
public static final String TOGGLE_POPUP = new String("toggle popup");
/**
* Returns the number of accessible actions available in this object
* If there are more than one, the first one is considered the "default"
* action of the object.
*
* @return the zero-based number of Actions in this object
*/
public int getAccessibleActionCount();
/**
* Returns a description of the specified action of the object.
*
* @param i zero-based index of the actions
* @return a String description of the action
* @see #getAccessibleActionCount
*/
public String getAccessibleActionDescription(int i);
/**
* Performs the specified Action on the object
*
* @param i zero-based index of actions
* @return true if the action was performed; otherwise false.
* @see #getAccessibleActionCount
*/
public boolean doAccessibleAction(int i);
}

View File

@@ -0,0 +1,78 @@
/*
* 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 javax.accessibility;
import javax.swing.text.AttributeSet;
/**
* <P>The AccessibleAttributeSequence provides information about
* a contiguous sequence of text attributes
*
* @see Accessible
* @see Accessible#getAccessibleContext
* @see AccessibleContext
* @see AccessibleContext#getAccessibleText
* @see AccessibleTextSequence
*
* @author Lynn Monsanto
*/
/**
* This class collects together the span of text that share the same
* contiguous set of attributes, along with that set of attributes. It
* is used by implementors of the class <code>AccessibleContext</code> in
* order to generate <code>ACCESSIBLE_TEXT_ATTRIBUTES_CHANGED</code> events.
*
* @see javax.accessibility.AccessibleContext
* @see javax.accessibility.AccessibleContext#ACCESSIBLE_TEXT_ATTRIBUTES_CHANGED
*/
public class AccessibleAttributeSequence {
/** The start index of the text sequence */
public int startIndex;
/** The end index of the text sequence */
public int endIndex;
/** The text attributes */
public AttributeSet attributes;
/**
* Constructs an <code>AccessibleAttributeSequence</code> with the given
* parameters.
*
* @param start the beginning index of the span of text
* @param end the ending index of the span of text
* @param attr the <code>AttributeSet</code> shared by this text span
*
* @since 1.6
*/
public AccessibleAttributeSequence(int start, int end, AttributeSet attr) {
startIndex = start;
endIndex = end;
attributes = attr;
}
};

View File

@@ -0,0 +1,158 @@
/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.accessibility;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
/**
* <p>Base class used to maintain a strongly typed enumeration. This is
* the superclass of {@link AccessibleState} and {@link AccessibleRole}.
* <p>The toDisplayString method allows you to obtain the localized string
* for a locale independent key from a predefined ResourceBundle for the
* keys defined in this class. This localized string is intended to be
* readable by humans.
*
* @see AccessibleRole
* @see AccessibleState
*
* @author Willie Walker
* @author Peter Korn
* @author Lynn Monsanto
*/
public abstract class AccessibleBundle {
private static Hashtable table = new Hashtable();
private final String defaultResourceBundleName
= "com.sun.accessibility.internal.resources.accessibility";
/**
* Construct an {@code AccessibleBundle}.
*/
public AccessibleBundle() {
}
/**
* The locale independent name of the state. This is a programmatic
* name that is not intended to be read by humans.
* @see #toDisplayString
*/
protected String key = null;
/**
* Obtains the key as a localized string.
* If a localized string cannot be found for the key, the
* locale independent key stored in the role will be returned.
* This method is intended to be used only by subclasses so that they
* can specify their own resource bundles which contain localized
* strings for their keys.
* @param resourceBundleName the name of the resource bundle to use for
* lookup
* @param locale the locale for which to obtain a localized string
* @return a localized String for the key.
*/
protected String toDisplayString(String resourceBundleName,
Locale locale) {
// loads the resource bundle if necessary
loadResourceBundle(resourceBundleName, locale);
// returns the localized string
Object o = table.get(locale);
if (o != null && o instanceof Hashtable) {
Hashtable resourceTable = (Hashtable) o;
o = resourceTable.get(key);
if (o != null && o instanceof String) {
return (String)o;
}
}
return key;
}
/**
* Obtains the key as a localized string.
* If a localized string cannot be found for the key, the
* locale independent key stored in the role will be returned.
*
* @param locale the locale for which to obtain a localized string
* @return a localized String for the key.
*/
public String toDisplayString(Locale locale) {
return toDisplayString(defaultResourceBundleName, locale);
}
/**
* Gets localized string describing the key using the default locale.
* @return a localized String describing the key for the default locale
*/
public String toDisplayString() {
return toDisplayString(Locale.getDefault());
}
/**
* Gets localized string describing the key using the default locale.
* @return a localized String describing the key using the default locale
* @see #toDisplayString
*/
public String toString() {
return toDisplayString();
}
/*
* Loads the Accessibility resource bundle if necessary.
*/
private void loadResourceBundle(String resourceBundleName,
Locale locale) {
if (! table.contains(locale)) {
try {
Hashtable resourceTable = new Hashtable();
ResourceBundle bundle = ResourceBundle.getBundle(resourceBundleName, locale);
Enumeration iter = bundle.getKeys();
while(iter.hasMoreElements()) {
String key = (String)iter.nextElement();
resourceTable.put(key, bundle.getObject(key));
}
table.put(locale, resourceTable);
}
catch (MissingResourceException e) {
System.err.println("loadResourceBundle: " + e);
// Just return so toDisplayString() returns the
// non-localized key.
return;
}
}
}
}

View File

@@ -0,0 +1,315 @@
/*
* 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 javax.accessibility;
import java.awt.*;
import java.awt.event.*;
/**
* The AccessibleComponent interface should be supported by any object
* that is rendered on the screen. This interface provides the standard
* mechanism for an assistive technology to determine and set the
* graphical representation of an object. Applications can determine
* if an object supports the AccessibleComponent interface by first
* obtaining its AccessibleContext
* and then calling the
* {@link AccessibleContext#getAccessibleComponent} method.
* If the return value is not null, the object supports this interface.
*
* @see Accessible
* @see Accessible#getAccessibleContext
* @see AccessibleContext
* @see AccessibleContext#getAccessibleComponent
*
* @author Peter Korn
* @author Hans Muller
* @author Willie Walker
*/
public interface AccessibleComponent {
/**
* Gets the background color of this object.
*
* @return the background color, if supported, of the object;
* otherwise, null
* @see #setBackground
*/
public Color getBackground();
/**
* Sets the background color of this object.
*
* @param c the new Color for the background
* @see #setBackground
*/
public void setBackground(Color c);
/**
* Gets the foreground color of this object.
*
* @return the foreground color, if supported, of the object;
* otherwise, null
* @see #setForeground
*/
public Color getForeground();
/**
* Sets the foreground color of this object.
*
* @param c the new Color for the foreground
* @see #getForeground
*/
public void setForeground(Color c);
/**
* Gets the Cursor of this object.
*
* @return the Cursor, if supported, of the object; otherwise, null
* @see #setCursor
*/
public Cursor getCursor();
/**
* Sets the Cursor of this object.
*
* @param cursor the new Cursor for the object
* @see #getCursor
*/
public void setCursor(Cursor cursor);
/**
* Gets the Font of this object.
*
* @return the Font,if supported, for the object; otherwise, null
* @see #setFont
*/
public Font getFont();
/**
* Sets the Font of this object.
*
* @param f the new Font for the object
* @see #getFont
*/
public void setFont(Font f);
/**
* Gets the FontMetrics of this object.
*
* @param f the Font
* @return the FontMetrics, if supported, the object; otherwise, null
* @see #getFont
*/
public FontMetrics getFontMetrics(Font f);
/**
* Determines if the object is enabled. Objects that are enabled
* will also have the AccessibleState.ENABLED state set in their
* AccessibleStateSets.
*
* @return true if object is enabled; otherwise, false
* @see #setEnabled
* @see AccessibleContext#getAccessibleStateSet
* @see AccessibleState#ENABLED
* @see AccessibleStateSet
*/
public boolean isEnabled();
/**
* Sets the enabled state of the object.
*
* @param b if true, enables this object; otherwise, disables it
* @see #isEnabled
*/
public void setEnabled(boolean b);
/**
* Determines if the object is visible. Note: this means that the
* object intends to be visible; however, it may not be
* showing on the screen because one of the objects that this object
* is contained by is currently not visible. To determine if an object is
* showing on the screen, use isShowing().
* <p>Objects that are visible will also have the
* AccessibleState.VISIBLE state set in their AccessibleStateSets.
*
* @return true if object is visible; otherwise, false
* @see #setVisible
* @see AccessibleContext#getAccessibleStateSet
* @see AccessibleState#VISIBLE
* @see AccessibleStateSet
*/
public boolean isVisible();
/**
* Sets the visible state of the object.
*
* @param b if true, shows this object; otherwise, hides it
* @see #isVisible
*/
public void setVisible(boolean b);
/**
* Determines if the object is showing. This is determined by checking
* the visibility of the object and its ancestors.
* Note: this
* will return true even if the object is obscured by another (for example,
* it is underneath a menu that was pulled down).
*
* @return true if object is showing; otherwise, false
*/
public boolean isShowing();
/**
* Checks whether the specified point is within this object's bounds,
* where the point's x and y coordinates are defined to be relative to the
* coordinate system of the object.
*
* @param p the Point relative to the coordinate system of the object
* @return true if object contains Point; otherwise false
* @see #getBounds
*/
public boolean contains(Point p);
/**
* Returns the location of the object on the screen.
*
* @return the location of the object on screen; null if this object
* is not on the screen
* @see #getBounds
* @see #getLocation
*/
public Point getLocationOnScreen();
/**
* Gets the location of the object relative to the parent in the form
* of a point specifying the object's top-left corner in the screen's
* coordinate space.
*
* @return An instance of Point representing the top-left corner of the
* object's bounds in the coordinate space of the screen; null if
* this object or its parent are not on the screen
* @see #getBounds
* @see #getLocationOnScreen
*/
public Point getLocation();
/**
* Sets the location of the object relative to the parent.
* @param p the new position for the top-left corner
* @see #getLocation
*/
public void setLocation(Point p);
/**
* Gets the bounds of this object in the form of a Rectangle object.
* The bounds specify this object's width, height, and location
* relative to its parent.
*
* @return A rectangle indicating this component's bounds; null if
* this object is not on the screen.
* @see #contains
*/
public Rectangle getBounds();
/**
* Sets the bounds of this object in the form of a Rectangle object.
* The bounds specify this object's width, height, and location
* relative to its parent.
*
* @param r rectangle indicating this component's bounds
* @see #getBounds
*/
public void setBounds(Rectangle r);
/**
* Returns the size of this object in the form of a Dimension object.
* The height field of the Dimension object contains this object's
* height, and the width field of the Dimension object contains this
* object's width.
*
* @return A Dimension object that indicates the size of this component;
* null if this object is not on the screen
* @see #setSize
*/
public Dimension getSize();
/**
* Resizes this object so that it has width and height.
*
* @param d The dimension specifying the new size of the object.
* @see #getSize
*/
public void setSize(Dimension d);
/**
* Returns the Accessible child, if one exists, contained at the local
* coordinate Point.
*
* @param p The point relative to the coordinate system of this object.
* @return the Accessible, if it exists, at the specified location;
* otherwise null
*/
public Accessible getAccessibleAt(Point p);
/**
* Returns whether this object can accept focus or not. Objects that
* can accept focus will also have the AccessibleState.FOCUSABLE state
* set in their AccessibleStateSets.
*
* @return true if object can accept focus; otherwise false
* @see AccessibleContext#getAccessibleStateSet
* @see AccessibleState#FOCUSABLE
* @see AccessibleState#FOCUSED
* @see AccessibleStateSet
*/
public boolean isFocusTraversable();
/**
* Requests focus for this object. If this object cannot accept focus,
* nothing will happen. Otherwise, the object will attempt to take
* focus.
* @see #isFocusTraversable
*/
public void requestFocus();
/**
* Adds the specified focus listener to receive focus events from this
* component.
*
* @param l the focus listener
* @see #removeFocusListener
*/
public void addFocusListener(FocusListener l);
/**
* Removes the specified focus listener so it no longer receives focus
* events from this component.
*
* @param l the focus listener
* @see #addFocusListener
*/
public void removeFocusListener(FocusListener l);
}

View File

@@ -0,0 +1,774 @@
/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.accessibility;
import sun.awt.AWTAccessor;
import sun.awt.AppContext;
import java.util.Locale;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.beans.PropertyChangeEvent;
import java.awt.IllegalComponentStateException;
/**
* AccessibleContext represents the minimum information all accessible objects
* return. This information includes the accessible name, description, role,
* and state of the object, as well as information about its parent and
* children. AccessibleContext also contains methods for
* obtaining more specific accessibility information about a component.
* If the component supports them, these methods will return an object that
* implements one or more of the following interfaces:
* <P><ul>
* <li>{@link AccessibleAction} - the object can perform one or more actions.
* This interface provides the standard mechanism for an assistive
* technology to determine what those actions are and tell the object
* to perform them. Any object that can be manipulated should
* support this interface.
* <li>{@link AccessibleComponent} - the object has a graphical representation.
* This interface provides the standard mechanism for an assistive
* technology to determine and set the graphical representation of the
* object. Any object that is rendered on the screen should support
* this interface.
* <li>{@link AccessibleSelection} - the object allows its children to be
* selected. This interface provides the standard mechanism for an
* assistive technology to determine the currently selected children of the object
* as well as modify its selection set. Any object that has children
* that can be selected should support this interface.
* <li>{@link AccessibleText} - the object presents editable textual information
* on the display. This interface provides the standard mechanism for
* an assistive technology to access that text via its content, attributes,
* and spatial location. Any object that contains editable text should
* support this interface.
* <li>{@link AccessibleValue} - the object supports a numerical value. This
* interface provides the standard mechanism for an assistive technology
* to determine and set the current value of the object, as well as obtain its
* minimum and maximum values. Any object that supports a numerical value
* should support this interface.</ul>
*
*
* @beaninfo
* attribute: isContainer false
* description: Minimal information that all accessible objects return
*
* @author Peter Korn
* @author Hans Muller
* @author Willie Walker
* @author Lynn Monsanto
*/
public abstract class AccessibleContext {
/**
* The AppContext that should be used to dispatch events for this
* AccessibleContext
*/
private volatile AppContext targetAppContext;
static {
AWTAccessor.setAccessibleContextAccessor(new AWTAccessor.AccessibleContextAccessor() {
@Override
public void setAppContext(AccessibleContext accessibleContext, AppContext appContext) {
accessibleContext.targetAppContext = appContext;
}
@Override
public AppContext getAppContext(AccessibleContext accessibleContext) {
return accessibleContext.targetAppContext;
}
});
}
/**
* Constant used to determine when the accessibleName property has
* changed. The old value in the PropertyChangeEvent will be the old
* accessibleName and the new value will be the new accessibleName.
*
* @see #getAccessibleName
* @see #addPropertyChangeListener
*/
public static final String ACCESSIBLE_NAME_PROPERTY = "AccessibleName";
/**
* Constant used to determine when the accessibleDescription property has
* changed. The old value in the PropertyChangeEvent will be the
* old accessibleDescription and the new value will be the new
* accessibleDescription.
*
* @see #getAccessibleDescription
* @see #addPropertyChangeListener
*/
public static final String ACCESSIBLE_DESCRIPTION_PROPERTY = "AccessibleDescription";
/**
* Constant used to determine when the accessibleStateSet property has
* changed. The old value will be the old AccessibleState and the new
* value will be the new AccessibleState in the accessibleStateSet.
* For example, if a component that supports the vertical and horizontal
* states changes its orientation from vertical to horizontal, the old
* value will be AccessibleState.VERTICAL and the new value will be
* AccessibleState.HORIZONTAL. Please note that either value can also
* be null. For example, when a component changes from being enabled
* to disabled, the old value will be AccessibleState.ENABLED
* and the new value will be null.
*
* @see #getAccessibleStateSet
* @see AccessibleState
* @see AccessibleStateSet
* @see #addPropertyChangeListener
*/
public static final String ACCESSIBLE_STATE_PROPERTY = "AccessibleState";
/**
* Constant used to determine when the accessibleValue property has
* changed. The old value in the PropertyChangeEvent will be a Number
* representing the old value and the new value will be a Number
* representing the new value
*
* @see #getAccessibleValue
* @see #addPropertyChangeListener
*/
public static final String ACCESSIBLE_VALUE_PROPERTY = "AccessibleValue";
/**
* Constant used to determine when the accessibleSelection has changed.
* The old and new values in the PropertyChangeEvent are currently
* reserved for future use.
*
* @see #getAccessibleSelection
* @see #addPropertyChangeListener
*/
public static final String ACCESSIBLE_SELECTION_PROPERTY = "AccessibleSelection";
/**
* Constant used to determine when the accessibleText caret has changed.
* The old value in the PropertyChangeEvent will be an
* integer representing the old caret position, and the new value will
* be an integer representing the new/current caret position.
*
* @see #addPropertyChangeListener
*/
public static final String ACCESSIBLE_CARET_PROPERTY = "AccessibleCaret";
/**
* Constant used to determine when the visual appearance of the object
* has changed. The old and new values in the PropertyChangeEvent are
* currently reserved for future use.
*
* @see #addPropertyChangeListener
*/
public static final String ACCESSIBLE_VISIBLE_DATA_PROPERTY = "AccessibleVisibleData";
/**
* Constant used to determine when Accessible children are added/removed
* from the object. If an Accessible child is being added, the old
* value will be null and the new value will be the Accessible child. If an
* Accessible child is being removed, the old value will be the Accessible
* child, and the new value will be null.
*
* @see #addPropertyChangeListener
*/
public static final String ACCESSIBLE_CHILD_PROPERTY = "AccessibleChild";
/**
* Constant used to determine when the active descendant of a component
* has changed. The active descendant is used for objects such as
* list, tree, and table, which may have transient children. When the
* active descendant has changed, the old value of the property change
* event will be the Accessible representing the previous active child, and
* the new value will be the Accessible representing the current active
* child.
*
* @see #addPropertyChangeListener
*/
public static final String ACCESSIBLE_ACTIVE_DESCENDANT_PROPERTY = "AccessibleActiveDescendant";
/**
* Constant used to indicate that the table caption has changed
* The old value in the PropertyChangeEvent will be an Accessible
* representing the previous table caption and the new value will
* be an Accessible representing the new table caption.
* @see Accessible
* @see AccessibleTable
*/
public static final String ACCESSIBLE_TABLE_CAPTION_CHANGED =
"accessibleTableCaptionChanged";
/**
* Constant used to indicate that the table summary has changed
* The old value in the PropertyChangeEvent will be an Accessible
* representing the previous table summary and the new value will
* be an Accessible representing the new table summary.
* @see Accessible
* @see AccessibleTable
*/
public static final String ACCESSIBLE_TABLE_SUMMARY_CHANGED =
"accessibleTableSummaryChanged";
/**
* Constant used to indicate that table data has changed.
* The old value in the PropertyChangeEvent will be null and the
* new value will be an AccessibleTableModelChange representing
* the table change.
* @see AccessibleTable
* @see AccessibleTableModelChange
*/
public static final String ACCESSIBLE_TABLE_MODEL_CHANGED =
"accessibleTableModelChanged";
/**
* Constant used to indicate that the row header has changed
* The old value in the PropertyChangeEvent will be null and the
* new value will be an AccessibleTableModelChange representing
* the header change.
* @see AccessibleTable
* @see AccessibleTableModelChange
*/
public static final String ACCESSIBLE_TABLE_ROW_HEADER_CHANGED =
"accessibleTableRowHeaderChanged";
/**
* Constant used to indicate that the row description has changed
* The old value in the PropertyChangeEvent will be null and the
* new value will be an Integer representing the row index.
* @see AccessibleTable
*/
public static final String ACCESSIBLE_TABLE_ROW_DESCRIPTION_CHANGED =
"accessibleTableRowDescriptionChanged";
/**
* Constant used to indicate that the column header has changed
* The old value in the PropertyChangeEvent will be null and the
* new value will be an AccessibleTableModelChange representing
* the header change.
* @see AccessibleTable
* @see AccessibleTableModelChange
*/
public static final String ACCESSIBLE_TABLE_COLUMN_HEADER_CHANGED =
"accessibleTableColumnHeaderChanged";
/**
* Constant used to indicate that the column description has changed
* The old value in the PropertyChangeEvent will be null and the
* new value will be an Integer representing the column index.
* @see AccessibleTable
*/
public static final String ACCESSIBLE_TABLE_COLUMN_DESCRIPTION_CHANGED =
"accessibleTableColumnDescriptionChanged";
/**
* Constant used to indicate that the supported set of actions
* has changed. The old value in the PropertyChangeEvent will
* be an Integer representing the old number of actions supported
* and the new value will be an Integer representing the new
* number of actions supported.
* @see AccessibleAction
*/
public static final String ACCESSIBLE_ACTION_PROPERTY =
"accessibleActionProperty";
/**
* Constant used to indicate that a hypertext element has received focus.
* The old value in the PropertyChangeEvent will be an Integer
* representing the start index in the document of the previous element
* that had focus and the new value will be an Integer representing
* the start index in the document of the current element that has
* focus. A value of -1 indicates that an element does not or did
* not have focus.
* @see AccessibleHyperlink
*/
public static final String ACCESSIBLE_HYPERTEXT_OFFSET =
"AccessibleHypertextOffset";
/**
* PropertyChangeEvent which indicates that text has changed.
* <br>
* For text insertion, the oldValue is null and the newValue
* is an AccessibleTextSequence specifying the text that was
* inserted.
* <br>
* For text deletion, the oldValue is an AccessibleTextSequence
* specifying the text that was deleted and the newValue is null.
* <br>
* For text replacement, the oldValue is an AccessibleTextSequence
* specifying the old text and the newValue is an AccessibleTextSequence
* specifying the new text.
*
* @see #getAccessibleText
* @see #addPropertyChangeListener
* @see AccessibleTextSequence
*/
public static final String ACCESSIBLE_TEXT_PROPERTY
= "AccessibleText";
/**
* PropertyChangeEvent which indicates that a significant change
* has occurred to the children of a component like a tree or text.
* This change notifies the event listener that it needs to
* reacquire the state of the subcomponents. The oldValue is
* null and the newValue is the component whose children have
* become invalid.
*
* @see #getAccessibleText
* @see #addPropertyChangeListener
* @see AccessibleTextSequence
*
* @since 1.5
*/
public static final String ACCESSIBLE_INVALIDATE_CHILDREN =
"accessibleInvalidateChildren";
/**
* PropertyChangeEvent which indicates that text attributes have changed.
* <br>
* For attribute insertion, the oldValue is null and the newValue
* is an AccessibleAttributeSequence specifying the attributes that were
* inserted.
* <br>
* For attribute deletion, the oldValue is an AccessibleAttributeSequence
* specifying the attributes that were deleted and the newValue is null.
* <br>
* For attribute replacement, the oldValue is an AccessibleAttributeSequence
* specifying the old attributes and the newValue is an
* AccessibleAttributeSequence specifying the new attributes.
*
* @see #getAccessibleText
* @see #addPropertyChangeListener
* @see AccessibleAttributeSequence
*
* @since 1.5
*/
public static final String ACCESSIBLE_TEXT_ATTRIBUTES_CHANGED =
"accessibleTextAttributesChanged";
/**
* PropertyChangeEvent which indicates that a change has occurred
* in a component's bounds.
* The oldValue is the old component bounds and the newValue is
* the new component bounds.
*
* @see #addPropertyChangeListener
*
* @since 1.5
*/
public static final String ACCESSIBLE_COMPONENT_BOUNDS_CHANGED =
"accessibleComponentBoundsChanged";
/**
* The accessible parent of this object.
*
* @see #getAccessibleParent
* @see #setAccessibleParent
*/
protected Accessible accessibleParent = null;
/**
* A localized String containing the name of the object.
*
* @see #getAccessibleName
* @see #setAccessibleName
*/
protected String accessibleName = null;
/**
* A localized String containing the description of the object.
*
* @see #getAccessibleDescription
* @see #setAccessibleDescription
*/
protected String accessibleDescription = null;
/**
* Used to handle the listener list for property change events.
*
* @see #addPropertyChangeListener
* @see #removePropertyChangeListener
* @see #firePropertyChangeListener
*/
private PropertyChangeSupport accessibleChangeSupport = null;
/**
* Used to represent the context's relation set
* @see #getAccessibleRelationSet
*/
private AccessibleRelationSet relationSet
= new AccessibleRelationSet();
private Object nativeAXResource;
/**
* Gets the accessibleName property of this object. The accessibleName
* property of an object is a localized String that designates the purpose
* of the object. For example, the accessibleName property of a label
* or button might be the text of the label or button itself. In the
* case of an object that doesn't display its name, the accessibleName
* should still be set. For example, in the case of a text field used
* to enter the name of a city, the accessibleName for the en_US locale
* could be 'city.'
*
* @return the localized name of the object; null if this
* object does not have a name
*
* @see #setAccessibleName
*/
public String getAccessibleName() {
return accessibleName;
}
/**
* Sets the localized accessible name of this object. Changing the
* name will cause a PropertyChangeEvent to be fired for the
* ACCESSIBLE_NAME_PROPERTY property.
*
* @param s the new localized name of the object.
*
* @see #getAccessibleName
* @see #addPropertyChangeListener
*
* @beaninfo
* preferred: true
* description: Sets the accessible name for the component.
*/
public void setAccessibleName(String s) {
String oldName = accessibleName;
accessibleName = s;
firePropertyChange(ACCESSIBLE_NAME_PROPERTY,oldName,accessibleName);
}
/**
* Gets the accessibleDescription property of this object. The
* accessibleDescription property of this object is a short localized
* phrase describing the purpose of the object. For example, in the
* case of a 'Cancel' button, the accessibleDescription could be
* 'Ignore changes and close dialog box.'
*
* @return the localized description of the object; null if
* this object does not have a description
*
* @see #setAccessibleDescription
*/
public String getAccessibleDescription() {
return accessibleDescription;
}
/**
* Sets the accessible description of this object. Changing the
* name will cause a PropertyChangeEvent to be fired for the
* ACCESSIBLE_DESCRIPTION_PROPERTY property.
*
* @param s the new localized description of the object
*
* @see #setAccessibleName
* @see #addPropertyChangeListener
*
* @beaninfo
* preferred: true
* description: Sets the accessible description for the component.
*/
public void setAccessibleDescription(String s) {
String oldDescription = accessibleDescription;
accessibleDescription = s;
firePropertyChange(ACCESSIBLE_DESCRIPTION_PROPERTY,
oldDescription,accessibleDescription);
}
/**
* Gets the role of this object. The role of the object is the generic
* purpose or use of the class of this object. For example, the role
* of a push button is AccessibleRole.PUSH_BUTTON. The roles in
* AccessibleRole are provided so component developers can pick from
* a set of predefined roles. This enables assistive technologies to
* provide a consistent interface to various tweaked subclasses of
* components (e.g., use AccessibleRole.PUSH_BUTTON for all components
* that act like a push button) as well as distinguish between subclasses
* that behave differently (e.g., AccessibleRole.CHECK_BOX for check boxes
* and AccessibleRole.RADIO_BUTTON for radio buttons).
* <p>Note that the AccessibleRole class is also extensible, so
* custom component developers can define their own AccessibleRole's
* if the set of predefined roles is inadequate.
*
* @return an instance of AccessibleRole describing the role of the object
* @see AccessibleRole
*/
public abstract AccessibleRole getAccessibleRole();
/**
* Gets the state set of this object. The AccessibleStateSet of an object
* is composed of a set of unique AccessibleStates. A change in the
* AccessibleStateSet of an object will cause a PropertyChangeEvent to
* be fired for the ACCESSIBLE_STATE_PROPERTY property.
*
* @return an instance of AccessibleStateSet containing the
* current state set of the object
* @see AccessibleStateSet
* @see AccessibleState
* @see #addPropertyChangeListener
*/
public abstract AccessibleStateSet getAccessibleStateSet();
/**
* Gets the Accessible parent of this object.
*
* @return the Accessible parent of this object; null if this
* object does not have an Accessible parent
*/
public Accessible getAccessibleParent() {
return accessibleParent;
}
/**
* Sets the Accessible parent of this object. This is meant to be used
* only in the situations where the actual component's parent should
* not be treated as the component's accessible parent and is a method
* that should only be called by the parent of the accessible child.
*
* @param a - Accessible to be set as the parent
*/
public void setAccessibleParent(Accessible a) {
accessibleParent = a;
}
/**
* Gets the 0-based index of this object in its accessible parent.
*
* @return the 0-based index of this object in its parent; -1 if this
* object does not have an accessible parent.
*
* @see #getAccessibleParent
* @see #getAccessibleChildrenCount
* @see #getAccessibleChild
*/
public abstract int getAccessibleIndexInParent();
/**
* Returns the number of accessible children of the object.
*
* @return the number of accessible children of the object.
*/
public abstract int getAccessibleChildrenCount();
/**
* Returns the specified Accessible child of the object. The Accessible
* children of an Accessible object are zero-based, so the first child
* of an Accessible child is at index 0, the second child is at index 1,
* and so on.
*
* @param i zero-based index of child
* @return the Accessible child of the object
* @see #getAccessibleChildrenCount
*/
public abstract Accessible getAccessibleChild(int i);
/**
* Gets the locale of the component. If the component does not have a
* locale, then the locale of its parent is returned.
*
* @return this component's locale. If this component does not have
* a locale, the locale of its parent is returned.
*
* @exception IllegalComponentStateException
* If the Component does not have its own locale and has not yet been
* added to a containment hierarchy such that the locale can be
* determined from the containing parent.
*/
public abstract Locale getLocale() throws IllegalComponentStateException;
/**
* Adds a PropertyChangeListener to the listener list.
* The listener is registered for all Accessible properties and will
* be called when those properties change.
*
* @see #ACCESSIBLE_NAME_PROPERTY
* @see #ACCESSIBLE_DESCRIPTION_PROPERTY
* @see #ACCESSIBLE_STATE_PROPERTY
* @see #ACCESSIBLE_VALUE_PROPERTY
* @see #ACCESSIBLE_SELECTION_PROPERTY
* @see #ACCESSIBLE_TEXT_PROPERTY
* @see #ACCESSIBLE_VISIBLE_DATA_PROPERTY
*
* @param listener The PropertyChangeListener to be added
*/
public void addPropertyChangeListener(PropertyChangeListener listener) {
if (accessibleChangeSupport == null) {
accessibleChangeSupport = new PropertyChangeSupport(this);
}
accessibleChangeSupport.addPropertyChangeListener(listener);
}
/**
* Removes a PropertyChangeListener from the listener list.
* This removes a PropertyChangeListener that was registered
* for all properties.
*
* @param listener The PropertyChangeListener to be removed
*/
public void removePropertyChangeListener(PropertyChangeListener listener) {
if (accessibleChangeSupport != null) {
accessibleChangeSupport.removePropertyChangeListener(listener);
}
}
/**
* Gets the AccessibleAction associated with this object that supports
* one or more actions.
*
* @return AccessibleAction if supported by object; else return null
* @see AccessibleAction
*/
public AccessibleAction getAccessibleAction() {
return null;
}
/**
* Gets the AccessibleComponent associated with this object that has a
* graphical representation.
*
* @return AccessibleComponent if supported by object; else return null
* @see AccessibleComponent
*/
public AccessibleComponent getAccessibleComponent() {
return null;
}
/**
* Gets the AccessibleSelection associated with this object which allows its
* Accessible children to be selected.
*
* @return AccessibleSelection if supported by object; else return null
* @see AccessibleSelection
*/
public AccessibleSelection getAccessibleSelection() {
return null;
}
/**
* Gets the AccessibleText associated with this object presenting
* text on the display.
*
* @return AccessibleText if supported by object; else return null
* @see AccessibleText
*/
public AccessibleText getAccessibleText() {
return null;
}
/**
* Gets the AccessibleEditableText associated with this object
* presenting editable text on the display.
*
* @return AccessibleEditableText if supported by object; else return null
* @see AccessibleEditableText
* @since 1.4
*/
public AccessibleEditableText getAccessibleEditableText() {
return null;
}
/**
* Gets the AccessibleValue associated with this object that supports a
* Numerical value.
*
* @return AccessibleValue if supported by object; else return null
* @see AccessibleValue
*/
public AccessibleValue getAccessibleValue() {
return null;
}
/**
* Gets the AccessibleIcons associated with an object that has
* one or more associated icons
*
* @return an array of AccessibleIcon if supported by object;
* otherwise return null
* @see AccessibleIcon
* @since 1.3
*/
public AccessibleIcon [] getAccessibleIcon() {
return null;
}
/**
* Gets the AccessibleRelationSet associated with an object
*
* @return an AccessibleRelationSet if supported by object;
* otherwise return null
* @see AccessibleRelationSet
* @since 1.3
*/
public AccessibleRelationSet getAccessibleRelationSet() {
return relationSet;
}
/**
* Gets the AccessibleTable associated with an object
*
* @return an AccessibleTable if supported by object;
* otherwise return null
* @see AccessibleTable
* @since 1.3
*/
public AccessibleTable getAccessibleTable() {
return null;
}
/**
* Support for reporting bound property changes. If oldValue and
* newValue are not equal and the PropertyChangeEvent listener list
* is not empty, then fire a PropertyChange event to each listener.
* In general, this is for use by the Accessible objects themselves
* and should not be called by an application program.
* @param propertyName The programmatic name of the property that
* was changed.
* @param oldValue The old value of the property.
* @param newValue The new value of the property.
* @see java.beans.PropertyChangeSupport
* @see #addPropertyChangeListener
* @see #removePropertyChangeListener
* @see #ACCESSIBLE_NAME_PROPERTY
* @see #ACCESSIBLE_DESCRIPTION_PROPERTY
* @see #ACCESSIBLE_STATE_PROPERTY
* @see #ACCESSIBLE_VALUE_PROPERTY
* @see #ACCESSIBLE_SELECTION_PROPERTY
* @see #ACCESSIBLE_TEXT_PROPERTY
* @see #ACCESSIBLE_VISIBLE_DATA_PROPERTY
*/
public void firePropertyChange(String propertyName,
Object oldValue,
Object newValue) {
if (accessibleChangeSupport != null) {
if (newValue instanceof PropertyChangeEvent) {
PropertyChangeEvent pce = (PropertyChangeEvent)newValue;
accessibleChangeSupport.firePropertyChange(pce);
} else {
accessibleChangeSupport.firePropertyChange(propertyName,
oldValue,
newValue);
}
}
}
}

View File

@@ -0,0 +1,133 @@
/*
* Copyright (c) 2000, 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.accessibility;
import java.util.*;
import java.awt.*;
import javax.swing.text.*;
/**
* <P>The AccessibleEditableText interface should be implemented by all
* classes that present editable textual information on the display.
* Along with the AccessibleText interface, this interface provides
* the standard mechanism for an assistive technology to access
* that text via its content, attributes, and spatial location.
* Applications can determine if an object supports the AccessibleEditableText
* interface by first obtaining its AccessibleContext (see {@link Accessible})
* and then calling the {@link AccessibleContext#getAccessibleEditableText}
* method of AccessibleContext. If the return value is not null, the object
* supports this interface.
*
* @see Accessible
* @see Accessible#getAccessibleContext
* @see AccessibleContext
* @see AccessibleContext#getAccessibleText
* @see AccessibleContext#getAccessibleEditableText
*
* @author Lynn Monsanto
* @since 1.4
*/
public interface AccessibleEditableText extends AccessibleText {
/**
* Sets the text contents to the specified string.
*
* @param s the string to set the text contents
*/
public void setTextContents(String s);
/**
* Inserts the specified string at the given index/
*
* @param index the index in the text where the string will
* be inserted
* @param s the string to insert in the text
*/
public void insertTextAtIndex(int index, String s);
/**
* Returns the text string between two indices.
*
* @param startIndex the starting index in the text
* @param endIndex the ending index in the text
* @return the text string between the indices
*/
public String getTextRange(int startIndex, int endIndex);
/**
* Deletes the text between two indices
*
* @param startIndex the starting index in the text
* @param endIndex the ending index in the text
*/
public void delete(int startIndex, int endIndex);
/**
* Cuts the text between two indices into the system clipboard.
*
* @param startIndex the starting index in the text
* @param endIndex the ending index in the text
*/
public void cut(int startIndex, int endIndex);
/**
* Pastes the text from the system clipboard into the text
* starting at the specified index.
*
* @param startIndex the starting index in the text
*/
public void paste(int startIndex);
/**
* Replaces the text between two indices with the specified
* string.
*
* @param startIndex the starting index in the text
* @param endIndex the ending index in the text
* @param s the string to replace the text between two indices
*/
public void replaceText(int startIndex, int endIndex, String s);
/**
* Selects the text between two indices.
*
* @param startIndex the starting index in the text
* @param endIndex the ending index in the text
*/
public void selectText(int startIndex, int endIndex);
/**
* Sets attributes for the text between two indices.
*
* @param startIndex the starting index in the text
* @param endIndex the ending index in the text
* @param as the attribute set
* @see AttributeSet
*/
public void setAttributes(int startIndex, int endIndex, AttributeSet as);
}

View File

@@ -0,0 +1,74 @@
/*
* Copyright (c) 2000, 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.accessibility;
/**
* The AccessibleExtendedComponent interface should be supported by any object
* that is rendered on the screen. This interface provides the standard
* mechanism for an assistive technology to determine the extended
* graphical representation of an object. Applications can determine
* if an object supports the AccessibleExtendedComponent interface by first
* obtaining its AccessibleContext
* and then calling the
* {@link AccessibleContext#getAccessibleComponent} method.
* If the return value is not null and the type of the return value is
* AccessibleExtendedComponent, the object supports this interface.
*
* @see Accessible
* @see Accessible#getAccessibleContext
* @see AccessibleContext
* @see AccessibleContext#getAccessibleComponent
*
* @author Lynn Monsanto
* @since 1.4
*/
public interface AccessibleExtendedComponent extends AccessibleComponent {
/**
* Returns the tool tip text
*
* @return the tool tip text, if supported, of the object;
* otherwise, null
*/
public String getToolTipText();
/**
* Returns the titled border text
*
* @return the titled border text, if supported, of the object;
* otherwise, null
*/
public String getTitledBorderText();
/**
* Returns key bindings associated with this object
*
* @return the key bindings, if supported, of the object;
* otherwise, null
* @see AccessibleKeyBinding
*/
public AccessibleKeyBinding getAccessibleKeyBinding();
}

View File

@@ -0,0 +1,73 @@
/*
* Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.accessibility;
/**
* Class AccessibleExtendedTable provides extended information about
* a user-interface component that presents data in a two-dimensional
* table format.
* Applications can determine if an object supports the
* AccessibleExtendedTable interface by first obtaining its
* AccessibleContext and then calling the
* {@link AccessibleContext#getAccessibleTable} method.
* If the return value is not null and the type of the return value is
* AccessibleExtendedTable, the object supports this interface.
*
* @author Lynn Monsanto
* @since 1.4
*/
public interface AccessibleExtendedTable extends AccessibleTable {
/**
* Returns the row number of an index in the table.
*
* @param index the zero-based index in the table. The index is
* the table cell offset from row == 0 and column == 0.
* @return the zero-based row of the table if one exists;
* otherwise -1.
*/
public int getAccessibleRow(int index);
/**
* Returns the column number of an index in the table.
*
* @param index the zero-based index in the table. The index is
* the table cell offset from row == 0 and column == 0.
* @return the zero-based column of the table if one exists;
* otherwise -1.
*/
public int getAccessibleColumn(int index);
/**
* Returns the index at a row and column in the table.
*
* @param r zero-based row of the table
* @param c zero-based column of the table
* @return the zero-based index in the table if one exists;
* otherwise -1. The index is the table cell offset from
* row == 0 and column == 0.
*/
public int getAccessibleIndex(int r, int c);
}

View File

@@ -0,0 +1,142 @@
/*
* Copyright (c) 2003, 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.accessibility;
import java.util.*;
import java.awt.*;
import javax.swing.text.*;
/**
* <P>The AccessibleExtendedText interface contains additional methods
* not provided by the AccessibleText interface
*
* Applications can determine if an object supports the AccessibleExtendedText
* interface by first obtaining its AccessibleContext (see {@link Accessible})
* and then calling the {@link AccessibleContext#getAccessibleText} method of
* AccessibleContext. If the return value is an instance of
* AccessibleExtendedText, the object supports this interface.
*
* @see Accessible
* @see Accessible#getAccessibleContext
* @see AccessibleContext
* @see AccessibleContext#getAccessibleText
*
* @author Peter Korn
* @author Lynn Monsanto
* @since 1.5
*/
public interface AccessibleExtendedText {
/**
* Constant used to indicate that the part of the text that should be
* retrieved is a line of text.
*
* @see AccessibleText#getAtIndex
* @see AccessibleText#getAfterIndex
* @see AccessibleText#getBeforeIndex
*/
public static final int LINE = 4; // BugID: 4849720
/**
* Constant used to indicate that the part of the text that should be
* retrieved is contiguous text with the same text attributes.
*
* @see AccessibleText#getAtIndex
* @see AccessibleText#getAfterIndex
* @see AccessibleText#getBeforeIndex
*/
public static final int ATTRIBUTE_RUN = 5; // BugID: 4849720
/**
* Returns the text between two indices
*
* @param startIndex the start index in the text
* @param endIndex the end index in the text
* @return the text string if the indices are valid.
* Otherwise, null is returned.
*/
public String getTextRange(int startIndex, int endIndex);
/**
* Returns the <code>AccessibleTextSequence</code> at a given index.
*
* @param part the <code>CHARACTER</code>, <code>WORD</code>,
* <code>SENTENCE</code>, <code>LINE</code> or <code>ATTRIBUTE_RUN</code>
* to retrieve
* @param index an index within the text
* @return an <code>AccessibleTextSequence</code> specifying the text
* if part and index are valid. Otherwise, null is returned.
*
* @see AccessibleText#CHARACTER
* @see AccessibleText#WORD
* @see AccessibleText#SENTENCE
*/
public AccessibleTextSequence getTextSequenceAt(int part, int index);
/**
* Returns the <code>AccessibleTextSequence</code> after a given index.
*
* @param part the <code>CHARACTER</code>, <code>WORD</code>,
* <code>SENTENCE</code>, <code>LINE</code> or <code>ATTRIBUTE_RUN</code>
* to retrieve
* @param index an index within the text
* @return an <code>AccessibleTextSequence</code> specifying the text
* if part and index are valid. Otherwise, null is returned.
*
* @see AccessibleText#CHARACTER
* @see AccessibleText#WORD
* @see AccessibleText#SENTENCE
*/
public AccessibleTextSequence getTextSequenceAfter(int part, int index);
/**
* Returns the <code>AccessibleTextSequence</code> before a given index.
*
* @param part the <code>CHARACTER</code>, <code>WORD</code>,
* <code>SENTENCE</code>, <code>LINE</code> or <code>ATTRIBUTE_RUN</code>
* to retrieve
* @param index an index within the text
* @return an <code>AccessibleTextSequence</code> specifying the text
* if part and index are valid. Otherwise, null is returned.
*
* @see AccessibleText#CHARACTER
* @see AccessibleText#WORD
* @see AccessibleText#SENTENCE
*/
public AccessibleTextSequence getTextSequenceBefore(int part, int index);
/**
* Returns the bounding rectangle of the text between two indices.
*
* @param startIndex the start index in the text
* @param endIndex the end index in the text
* @return the bounding rectangle of the text if the indices are valid.
* Otherwise, null is returned.
*/
public Rectangle getTextBounds(int startIndex, int endIndex);
}

View File

@@ -0,0 +1,140 @@
/*
* Copyright (c) 1998, 2000, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact 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.accessibility;
import java.util.*;
import java.awt.*;
import javax.swing.text.*;
/**
* Encapsulation of a link, or set of links (e.g. client side imagemap)
* in a Hypertext document
*
* @see Accessible
* @see Accessible#getAccessibleContext
* @see AccessibleContext
* @see AccessibleText
* @see AccessibleContext#getAccessibleText
*
* @author Peter Korn
*/
public abstract class AccessibleHyperlink implements AccessibleAction {
/**
* Since the document a link is associated with may have
* changed, this method returns whether or not this Link is still valid
* (with respect to the document it references).
*
* @return a flag indicating whether this link is still valid with
* respect to the AccessibleHypertext it belongs to
*/
public abstract boolean isValid();
/**
* Returns the number of accessible actions available in this Link
* If there are more than one, the first one is NOT considered the
* "default" action of this LINK object (e.g. in an HTML imagemap).
* In general, links will have only one AccessibleAction in them.
*
* @return the zero-based number of Actions in this object
*/
public abstract int getAccessibleActionCount();
/**
* Performs the specified Action on the object
*
* @param i zero-based index of actions
* @return true if the action was performed; otherwise false.
* @see #getAccessibleActionCount
*/
public abstract boolean doAccessibleAction(int i);
/**
* Returns a String description of this particular
* link action. This should be a text string
* associated with anchoring text, this should be the
* anchor text. E.g. from HTML:
* &lt;a HREF="http://www.sun.com/access"&gt;Accessibility&lt;/a&gt;
* this method would return "Accessibility".
*
* Similarly, from this HTML:
* &lt;a HREF="#top"&gt;&lt;img src="top-hat.gif" alt="top hat"&gt;&lt;/a&gt;
* this method would return "top hat"
*
* @param i zero-based index of the actions
* @return a String description of the action
* @see #getAccessibleActionCount
*/
public abstract String getAccessibleActionDescription(int i);
/**
* Returns an object that represents the link action,
* as appropriate for that link. E.g. from HTML:
* &lt;a HREF="http://www.sun.com/access"&gt;Accessibility&lt;/a&gt;
* this method would return a
* java.net.URL("http://www.sun.com/access.html");
*
* @param i zero-based index of the actions
* @return an Object representing the hypertext link itself
* @see #getAccessibleActionCount
*/
public abstract Object getAccessibleActionObject(int i);
/**
* Returns an object that represents the link anchor,
* as appropriate for that link. E.g. from HTML:
* &lt;a href="http://www.sun.com/access"&gt;Accessibility&lt;/a&gt;
* this method would return a String containing the text:
* "Accessibility".
*
* Similarly, from this HTML:
* &lt;a HREF="#top"&gt;&lt;img src="top-hat.gif" alt="top hat"&gt;&lt;/a&gt;
* this might return the object ImageIcon("top-hat.gif", "top hat");
*
* @param i zero-based index of the actions
* @return an Object representing the hypertext anchor
* @see #getAccessibleActionCount
*/
public abstract Object getAccessibleActionAnchor(int i);
/**
* Gets the index with the hypertext document at which this
* link begins
*
* @return index of start of link
*/
public abstract int getStartIndex();
/**
* Gets the index with the hypertext document at which this
* link ends
*
* @return index of end of link
*/
public abstract int getEndIndex();
}

View File

@@ -0,0 +1,80 @@
/*
* Copyright (c) 1998, 2000, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact 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.accessibility;
import java.util.*;
import java.awt.*;
import javax.swing.text.*;
/**
* <P>The AccessibleHypertext class is the base class for all
* classes that present hypertext information on the display. This class
* provides the standard mechanism for an assistive technology to access
* that text via its content, attributes, and spatial location.
* It also provides standard mechanisms for manipulating hyperlinks.
* Applications can determine if an object supports the AccessibleHypertext
* interface by first obtaining its AccessibleContext (see {@link Accessible})
* and then calling the {@link AccessibleContext#getAccessibleText}
* method of AccessibleContext. If the return value is a class which extends
* AccessibleHypertext, then that object supports AccessibleHypertext.
*
* @see Accessible
* @see Accessible#getAccessibleContext
* @see AccessibleContext
* @see AccessibleText
* @see AccessibleContext#getAccessibleText
*
* @author Peter Korn
*/
public interface AccessibleHypertext extends AccessibleText {
/**
* Returns the number of links within this hypertext document.
*
* @return number of links in this hypertext doc.
*/
public abstract int getLinkCount();
/**
* Returns the nth Link of this Hypertext document.
*
* @param linkIndex within the links of this Hypertext
* @return Link object encapsulating the nth link(s)
*/
public abstract AccessibleHyperlink getLink(int linkIndex);
/**
* Returns the index into an array of hyperlinks that
* is associated with this character index, or -1 if there
* is no hyperlink associated with this index.
*
* @param charIndex index within the text
* @return index into the set of hyperlinks for this hypertext doc.
*/
public abstract int getLinkIndex(int charIndex);
}

View File

@@ -0,0 +1,82 @@
/*
* Copyright (c) 1999, 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.accessibility;
/**
* The AccessibleIcon interface should be supported by any object
* that has an associated icon (e.g., buttons). This interface
* provides the standard mechanism for an assistive technology
* to get descriptive information about icons.
* Applications can determine
* if an object supports the AccessibleIcon interface by first
* obtaining its AccessibleContext (see
* {@link Accessible}) and then calling the
* {@link AccessibleContext#getAccessibleIcon} method.
* If the return value is not null, the object supports this interface.
*
* @see Accessible
* @see AccessibleContext
*
* @author Lynn Monsanto
* @since 1.3
*/
public interface AccessibleIcon {
/**
* Gets the description of the icon. This is meant to be a brief
* textual description of the object. For example, it might be
* presented to a blind user to give an indication of the purpose
* of the icon.
*
* @return the description of the icon
*/
public String getAccessibleIconDescription();
/**
* Sets the description of the icon. This is meant to be a brief
* textual description of the object. For example, it might be
* presented to a blind user to give an indication of the purpose
* of the icon.
*
* @param description the description of the icon
*/
public void setAccessibleIconDescription(String description);
/**
* Gets the width of the icon
*
* @return the width of the icon.
*/
public int getAccessibleIconWidth();
/**
* Gets the height of the icon
*
* @return the height of the icon.
*/
public int getAccessibleIconHeight();
}

View File

@@ -0,0 +1,63 @@
/*
* Copyright (c) 2000, 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.accessibility;
/**
* The AccessibleKeyBinding interface should be supported by any object
* that has a keyboard bindings such as a keyboard mnemonic and/or keyboard
* shortcut which can be used to select the object. This interface provides
* the standard mechanism for an assistive technology to determine the
* key bindings which exist for this object.
* Any object that has such key bindings should support this
* interface.
*
* @see Accessible
* @see Accessible#getAccessibleContext
* @see AccessibleContext
*
* @author Lynn Monsanto
* @since 1.4
*/
public interface AccessibleKeyBinding {
/**
* Returns the number of key bindings for this object
*
* @return the zero-based number of key bindings for this object
*/
public int getAccessibleKeyBindingCount();
/**
* Returns a key binding for this object. The value returned is an
* java.lang.Object which must be cast to appropriate type depending
* on the underlying implementation of the key.
*
* @param i zero-based index of the key bindings
* @return a javax.lang.Object which specifies the key binding
* @see #getAccessibleKeyBindingCount
*/
public java.lang.Object getAccessibleKeyBinding(int i);
}

View File

@@ -0,0 +1,369 @@
/*
* Copyright (c) 1999, 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.accessibility;
import java.util.Vector;
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
/**
* <P>Class AccessibleRelation describes a relation between the
* object that implements the AccessibleRelation and one or more other
* objects. The actual relations that an object has with other
* objects are defined as an AccessibleRelationSet, which is a composed
* set of AccessibleRelations.
* <p>The toDisplayString method allows you to obtain the localized string
* for a locale independent key from a predefined ResourceBundle for the
* keys defined in this class.
* <p>The constants in this class present a strongly typed enumeration
* of common object roles. If the constants in this class are not sufficient
* to describe the role of an object, a subclass should be generated
* from this class and it should provide constants in a similar manner.
*
* @author Lynn Monsanto
* @since 1.3
*/
public class AccessibleRelation extends AccessibleBundle {
/*
* The group of objects that participate in the relation.
* The relation may be one-to-one or one-to-many. For
* example, in the case of a LABEL_FOR relation, the target
* vector would contain a list of objects labeled by the object
* that implements this AccessibleRelation. In the case of a
* MEMBER_OF relation, the target vector would contain all
* of the components that are members of the same group as the
* object that implements this AccessibleRelation.
*/
private Object [] target = new Object[0];
/**
* Indicates an object is a label for one or more target objects.
*
* @see #getTarget
* @see #CONTROLLER_FOR
* @see #CONTROLLED_BY
* @see #LABELED_BY
* @see #MEMBER_OF
*/
public static final String LABEL_FOR = new String("labelFor");
/**
* Indicates an object is labeled by one or more target objects.
*
* @see #getTarget
* @see #CONTROLLER_FOR
* @see #CONTROLLED_BY
* @see #LABEL_FOR
* @see #MEMBER_OF
*/
public static final String LABELED_BY = new String("labeledBy");
/**
* Indicates an object is a member of a group of one or more
* target objects.
*
* @see #getTarget
* @see #CONTROLLER_FOR
* @see #CONTROLLED_BY
* @see #LABEL_FOR
* @see #LABELED_BY
*/
public static final String MEMBER_OF = new String("memberOf");
/**
* Indicates an object is a controller for one or more target
* objects.
*
* @see #getTarget
* @see #CONTROLLED_BY
* @see #LABEL_FOR
* @see #LABELED_BY
* @see #MEMBER_OF
*/
public static final String CONTROLLER_FOR = new String("controllerFor");
/**
* Indicates an object is controlled by one or more target
* objects.
*
* @see #getTarget
* @see #CONTROLLER_FOR
* @see #LABEL_FOR
* @see #LABELED_BY
* @see #MEMBER_OF
*/
public static final String CONTROLLED_BY = new String("controlledBy");
/**
* Indicates an object is logically contiguous with a second
* object where the second object occurs after the object.
* An example is a paragraph of text that runs to the end of
* a page and continues on the next page with an intervening
* text footer and/or text header. The two parts of
* the paragraph are separate text elements but are related
* in that the second element is a continuation
* of the first
* element. In other words, the first element "flows to"
* the second element.
*
* @since 1.5
*/
public static final String FLOWS_TO = "flowsTo";
/**
* Indicates an object is logically contiguous with a second
* object where the second object occurs before the object.
* An example is a paragraph of text that runs to the end of
* a page and continues on the next page with an intervening
* text footer and/or text header. The two parts of
* the paragraph are separate text elements but are related
* in that the second element is a continuation of the first
* element. In other words, the second element "flows from"
* the second element.
*
* @since 1.5
*/
public static final String FLOWS_FROM = "flowsFrom";
/**
* Indicates that an object is a subwindow of one or more
* objects.
*
* @since 1.5
*/
public static final String SUBWINDOW_OF = "subwindowOf";
/**
* Indicates that an object is a parent window of one or more
* objects.
*
* @since 1.5
*/
public static final String PARENT_WINDOW_OF = "parentWindowOf";
/**
* Indicates that an object has one or more objects
* embedded in it.
*
* @since 1.5
*/
public static final String EMBEDS = "embeds";
/**
* Indicates that an object is embedded in one or more
* objects.
*
* @since 1.5
*/
public static final String EMBEDDED_BY = "embeddedBy";
/**
* Indicates that an object is a child node of one
* or more objects.
*
* @since 1.5
*/
public static final String CHILD_NODE_OF = "childNodeOf";
/**
* Identifies that the target group for a label has changed
*/
public static final String LABEL_FOR_PROPERTY = "labelForProperty";
/**
* Identifies that the objects that are doing the labeling have changed
*/
public static final String LABELED_BY_PROPERTY = "labeledByProperty";
/**
* Identifies that group membership has changed.
*/
public static final String MEMBER_OF_PROPERTY = "memberOfProperty";
/**
* Identifies that the controller for the target object has changed
*/
public static final String CONTROLLER_FOR_PROPERTY = "controllerForProperty";
/**
* Identifies that the target object that is doing the controlling has
* changed
*/
public static final String CONTROLLED_BY_PROPERTY = "controlledByProperty";
/**
* Indicates the FLOWS_TO relation between two objects
* has changed.
*
* @since 1.5
*/
public static final String FLOWS_TO_PROPERTY = "flowsToProperty";
/**
* Indicates the FLOWS_FROM relation between two objects
* has changed.
*
* @since 1.5
*/
public static final String FLOWS_FROM_PROPERTY = "flowsFromProperty";
/**
* Indicates the SUBWINDOW_OF relation between two or more objects
* has changed.
*
* @since 1.5
*/
public static final String SUBWINDOW_OF_PROPERTY = "subwindowOfProperty";
/**
* Indicates the PARENT_WINDOW_OF relation between two or more objects
* has changed.
*
* @since 1.5
*/
public static final String PARENT_WINDOW_OF_PROPERTY = "parentWindowOfProperty";
/**
* Indicates the EMBEDS relation between two or more objects
* has changed.
*
* @since 1.5
*/
public static final String EMBEDS_PROPERTY = "embedsProperty";
/**
* Indicates the EMBEDDED_BY relation between two or more objects
* has changed.
*
* @since 1.5
*/
public static final String EMBEDDED_BY_PROPERTY = "embeddedByProperty";
/**
* Indicates the CHILD_NODE_OF relation between two or more objects
* has changed.
*
* @since 1.5
*/
public static final String CHILD_NODE_OF_PROPERTY = "childNodeOfProperty";
/**
* Create a new AccessibleRelation using the given locale independent key.
* The key String should be a locale independent key for the relation.
* It is not intended to be used as the actual String to display
* to the user. To get the localized string, use toDisplayString.
*
* @param key the locale independent name of the relation.
* @see AccessibleBundle#toDisplayString
*/
public AccessibleRelation(String key) {
this.key = key;
this.target = null;
}
/**
* Creates a new AccessibleRelation using the given locale independent key.
* The key String should be a locale independent key for the relation.
* It is not intended to be used as the actual String to display
* to the user. To get the localized string, use toDisplayString.
*
* @param key the locale independent name of the relation.
* @param target the target object for this relation
* @see AccessibleBundle#toDisplayString
*/
public AccessibleRelation(String key, Object target) {
this.key = key;
this.target = new Object[1];
this.target[0] = target;
}
/**
* Creates a new AccessibleRelation using the given locale independent key.
* The key String should be a locale independent key for the relation.
* It is not intended to be used as the actual String to display
* to the user. To get the localized string, use toDisplayString.
*
* @param key the locale independent name of the relation.
* @param target the target object(s) for this relation
* @see AccessibleBundle#toDisplayString
*/
public AccessibleRelation(String key, Object [] target) {
this.key = key;
this.target = target;
}
/**
* Returns the key for this relation
*
* @return the key for this relation
*
* @see #CONTROLLER_FOR
* @see #CONTROLLED_BY
* @see #LABEL_FOR
* @see #LABELED_BY
* @see #MEMBER_OF
*/
public String getKey() {
return this.key;
}
/**
* Returns the target objects for this relation
*
* @return an array containing the target objects for this relation
*/
public Object [] getTarget() {
if (target == null) {
target = new Object[0];
}
Object [] retval = new Object[target.length];
for (int i = 0; i < target.length; i++) {
retval[i] = target[i];
}
return retval;
}
/**
* Sets the target object for this relation
*
* @param target the target object for this relation
*/
public void setTarget(Object target) {
this.target = new Object[1];
this.target[0] = target;
}
/**
* Sets the target objects for this relation
*
* @param target an array containing the target objects for this relation
*/
public void setTarget(Object [] target) {
this.target = target;
}
}

View File

@@ -0,0 +1,244 @@
/*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.accessibility;
import java.util.Vector;
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
/**
* Class AccessibleRelationSet determines a component's relation set. The
* relation set of a component is a set of AccessibleRelation objects that
* describe the component's relationships with other components.
*
* @see AccessibleRelation
*
* @author Lynn Monsanto
* @since 1.3
*/
public class AccessibleRelationSet {
/**
* Each entry in the Vector represents an AccessibleRelation.
* @see #add
* @see #addAll
* @see #remove
* @see #contains
* @see #get
* @see #size
* @see #toArray
* @see #clear
*/
protected Vector<AccessibleRelation> relations = null;
/**
* Creates a new empty relation set.
*/
public AccessibleRelationSet() {
relations = null;
}
/**
* Creates a new relation with the initial set of relations contained in
* the array of relations passed in. Duplicate entries are ignored.
*
* @param relations an array of AccessibleRelation describing the
* relation set.
*/
public AccessibleRelationSet(AccessibleRelation[] relations) {
if (relations.length != 0) {
this.relations = new Vector(relations.length);
for (int i = 0; i < relations.length; i++) {
add(relations[i]);
}
}
}
/**
* Adds a new relation to the current relation set. If the relation
* is already in the relation set, the target(s) of the specified
* relation is merged with the target(s) of the existing relation.
* Otherwise, the new relation is added to the relation set.
*
* @param relation the relation to add to the relation set
* @return true if relation is added to the relation set; false if the
* relation set is unchanged
*/
public boolean add(AccessibleRelation relation) {
if (relations == null) {
relations = new Vector();
}
// Merge the relation targets if the key exists
AccessibleRelation existingRelation = get(relation.getKey());
if (existingRelation == null) {
relations.addElement(relation);
return true;
} else {
Object [] existingTarget = existingRelation.getTarget();
Object [] newTarget = relation.getTarget();
int mergedLength = existingTarget.length + newTarget.length;
Object [] mergedTarget = new Object[mergedLength];
for (int i = 0; i < existingTarget.length; i++) {
mergedTarget[i] = existingTarget[i];
}
for (int i = existingTarget.length, j = 0;
i < mergedLength;
i++, j++) {
mergedTarget[i] = newTarget[j];
}
existingRelation.setTarget(mergedTarget);
}
return true;
}
/**
* Adds all of the relations to the existing relation set. Duplicate
* entries are ignored.
*
* @param relations AccessibleRelation array describing the relation set.
*/
public void addAll(AccessibleRelation[] relations) {
if (relations.length != 0) {
if (this.relations == null) {
this.relations = new Vector(relations.length);
}
for (int i = 0; i < relations.length; i++) {
add(relations[i]);
}
}
}
/**
* Removes a relation from the current relation set. If the relation
* is not in the set, the relation set will be unchanged and the
* return value will be false. If the relation is in the relation
* set, it will be removed from the set and the return value will be
* true.
*
* @param relation the relation to remove from the relation set
* @return true if the relation is in the relation set; false if the
* relation set is unchanged
*/
public boolean remove(AccessibleRelation relation) {
if (relations == null) {
return false;
} else {
return relations.removeElement(relation);
}
}
/**
* Removes all the relations from the current relation set.
*/
public void clear() {
if (relations != null) {
relations.removeAllElements();
}
}
/**
* Returns the number of relations in the relation set.
* @return the number of relations in the relation set
*/
public int size() {
if (relations == null) {
return 0;
} else {
return relations.size();
}
}
/**
* Returns whether the relation set contains a relation
* that matches the specified key.
* @param key the AccessibleRelation key
* @return true if the relation is in the relation set; otherwise false
*/
public boolean contains(String key) {
return get(key) != null;
}
/**
* Returns the relation that matches the specified key.
* @param key the AccessibleRelation key
* @return the relation, if one exists, that matches the specified key.
* Otherwise, null is returned.
*/
public AccessibleRelation get(String key) {
if (relations == null) {
return null;
} else {
int len = relations.size();
for (int i = 0; i < len; i++) {
AccessibleRelation relation =
(AccessibleRelation)relations.elementAt(i);
if (relation != null && relation.getKey().equals(key)) {
return relation;
}
}
return null;
}
}
/**
* Returns the current relation set as an array of AccessibleRelation
* @return AccessibleRelation array contacting the current relation.
*/
public AccessibleRelation[] toArray() {
if (relations == null) {
return new AccessibleRelation[0];
} else {
AccessibleRelation[] relationArray
= new AccessibleRelation[relations.size()];
for (int i = 0; i < relationArray.length; i++) {
relationArray[i] = (AccessibleRelation) relations.elementAt(i);
}
return relationArray;
}
}
/**
* Creates a localized String representing all the relations in the set
* using the default locale.
*
* @return comma separated localized String
* @see AccessibleBundle#toDisplayString
*/
public String toString() {
String ret = "";
if ((relations != null) && (relations.size() > 0)) {
ret = ((AccessibleRelation) (relations.elementAt(0))).toDisplayString();
for (int i = 1; i < relations.size(); i++) {
ret = ret + ","
+ ((AccessibleRelation) (relations.elementAt(i))).
toDisplayString();
}
}
return ret;
}
}

View File

@@ -0,0 +1,152 @@
/*
* 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.accessibility;
import java.util.ListResourceBundle;
/**
* A resource bundle containing the localized strings in the accessibility
* package. This is meant only for internal use by Java Accessibility and
* is not meant to be used by assistive technologies or applications.
*
* @author Willie Walker
* @deprecated This class is deprecated as of version 1.3 of the
* Java Platform.
*/
@Deprecated
public class AccessibleResourceBundle extends ListResourceBundle {
/**
* Returns the mapping between the programmatic keys and the
* localized display strings.
*/
public Object[][] getContents() {
// The table holding the mapping between the programmatic keys
// and the display strings for the en_US locale.
return new Object[][] {
// LOCALIZE THIS
// Role names
// { "application","application" },
// { "border","border" },
// { "checkboxmenuitem","check box menu item" },
// { "choice","choice" },
// { "column","column" },
// { "cursor","cursor" },
// { "document","document" },
// { "grouping","grouping" },
// { "image","image" },
// { "indicator","indicator" },
// { "radiobuttonmenuitem","radio button menu item" },
// { "row","row" },
// { "tablecell","table cell" },
// { "treenode","tree node" },
{ "alert","alert" },
{ "awtcomponent","AWT component" },
{ "checkbox","check box" },
{ "colorchooser","color chooser" },
{ "columnheader","column header" },
{ "combobox","combo box" },
{ "canvas","canvas" },
{ "desktopicon","desktop icon" },
{ "desktoppane","desktop pane" },
{ "dialog","dialog" },
{ "directorypane","directory pane" },
{ "glasspane","glass pane" },
{ "filechooser","file chooser" },
{ "filler","filler" },
{ "frame","frame" },
{ "internalframe","internal frame" },
{ "label","label" },
{ "layeredpane","layered pane" },
{ "list","list" },
{ "listitem","list item" },
{ "menubar","menu bar" },
{ "menu","menu" },
{ "menuitem","menu item" },
{ "optionpane","option pane" },
{ "pagetab","page tab" },
{ "pagetablist","page tab list" },
{ "panel","panel" },
{ "passwordtext","password text" },
{ "popupmenu","popup menu" },
{ "progressbar","progress bar" },
{ "pushbutton","push button" },
{ "radiobutton","radio button" },
{ "rootpane","root pane" },
{ "rowheader","row header" },
{ "scrollbar","scroll bar" },
{ "scrollpane","scroll pane" },
{ "separator","separator" },
{ "slider","slider" },
{ "splitpane","split pane" },
{ "swingcomponent","swing component" },
{ "table","table" },
{ "text","text" },
{ "tree","tree" },
{ "togglebutton","toggle button" },
{ "toolbar","tool bar" },
{ "tooltip","tool tip" },
{ "unknown","unknown" },
{ "viewport","viewport" },
{ "window","window" },
// Relations
{ "labelFor","label for" },
{ "labeledBy","labeled by" },
{ "memberOf","member of" },
{ "controlledBy","controlledBy" },
{ "controllerFor","controllerFor" },
// State modes
{ "active","active" },
{ "armed","armed" },
{ "busy","busy" },
{ "checked","checked" },
{ "collapsed", "collapsed" },
{ "editable","editable" },
{ "expandable", "expandable" },
{ "expanded", "expanded" },
{ "enabled","enabled" },
{ "focusable","focusable" },
{ "focused","focused" },
{ "iconified", "iconified" },
{ "modal", "modal" },
{ "multiline", "multiple line" },
{ "multiselectable","multiselectable" },
{ "opaque", "opaque" },
{ "pressed","pressed" },
{ "resizable", "resizable" },
{ "selectable","selectable" },
{ "selected","selected" },
{ "showing","showing" },
{ "singleline", "single line" },
{ "transient", "transient" },
{ "visible","visible" },
{ "vertical","vertical" },
{ "horizontal","horizontal" }
// END OF MATERIAL TO LOCALIZE
};
}
}

View File

@@ -0,0 +1,661 @@
/*
* 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.accessibility;
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
/**
* <P>Class AccessibleRole determines the role of a component. The role of a
* component describes its generic function. (E.G.,
* "push button," "table," or "list.")
* <p>The toDisplayString method allows you to obtain the localized string
* for a locale independent key from a predefined ResourceBundle for the
* keys defined in this class.
* <p>The constants in this class present a strongly typed enumeration
* of common object roles. A public constructor for this class has been
* purposely omitted and applications should use one of the constants
* from this class. If the constants in this class are not sufficient
* to describe the role of an object, a subclass should be generated
* from this class and it should provide constants in a similar manner.
*
* @author Willie Walker
* @author Peter Korn
* @author Lynn Monsanto
*/
public class AccessibleRole extends AccessibleBundle {
// If you add or remove anything from here, make sure you
// update AccessibleResourceBundle.java.
/**
* Object is used to alert the user about something.
*/
public static final AccessibleRole ALERT
= new AccessibleRole("alert");
/**
* The header for a column of data.
*/
public static final AccessibleRole COLUMN_HEADER
= new AccessibleRole("columnheader");
/**
* Object that can be drawn into and is used to trap
* events.
* @see #FRAME
* @see #GLASS_PANE
* @see #LAYERED_PANE
*/
public static final AccessibleRole CANVAS
= new AccessibleRole("canvas");
/**
* A list of choices the user can select from. Also optionally
* allows the user to enter a choice of their own.
*/
public static final AccessibleRole COMBO_BOX
= new AccessibleRole("combobox");
/**
* An iconified internal frame in a DESKTOP_PANE.
* @see #DESKTOP_PANE
* @see #INTERNAL_FRAME
*/
public static final AccessibleRole DESKTOP_ICON
= new AccessibleRole("desktopicon");
/**
* An object containing a collection of <code>Accessibles</code> that
* together represents <code>HTML</code> content. The child
* <code>Accessibles</code> would include objects implementing
* <code>AccessibleText</code>, <code>AccessibleHypertext</code>,
* <code>AccessibleIcon</code>, and other interfaces.
* @see #HYPERLINK
* @see AccessibleText
* @see AccessibleHypertext
* @see AccessibleHyperlink
* @see AccessibleIcon
* @since 1.6
*/
public static final AccessibleRole HTML_CONTAINER
= new AccessibleRole("htmlcontainer");
/**
* A frame-like object that is clipped by a desktop pane. The
* desktop pane, internal frame, and desktop icon objects are
* often used to create multiple document interfaces within an
* application.
* @see #DESKTOP_ICON
* @see #DESKTOP_PANE
* @see #FRAME
*/
public static final AccessibleRole INTERNAL_FRAME
= new AccessibleRole("internalframe");
/**
* A pane that supports internal frames and
* iconified versions of those internal frames.
* @see #DESKTOP_ICON
* @see #INTERNAL_FRAME
*/
public static final AccessibleRole DESKTOP_PANE
= new AccessibleRole("desktoppane");
/**
* A specialized pane whose primary use is inside a DIALOG
* @see #DIALOG
*/
public static final AccessibleRole OPTION_PANE
= new AccessibleRole("optionpane");
/**
* A top level window with no title or border.
* @see #FRAME
* @see #DIALOG
*/
public static final AccessibleRole WINDOW
= new AccessibleRole("window");
/**
* A top level window with a title bar, border, menu bar, etc. It is
* often used as the primary window for an application.
* @see #DIALOG
* @see #CANVAS
* @see #WINDOW
*/
public static final AccessibleRole FRAME
= new AccessibleRole("frame");
/**
* A top level window with title bar and a border. A dialog is similar
* to a frame, but it has fewer properties and is often used as a
* secondary window for an application.
* @see #FRAME
* @see #WINDOW
*/
public static final AccessibleRole DIALOG
= new AccessibleRole("dialog");
/**
* A specialized pane that lets the user choose a color.
*/
public static final AccessibleRole COLOR_CHOOSER
= new AccessibleRole("colorchooser");
/**
* A pane that allows the user to navigate through
* and select the contents of a directory. May be used
* by a file chooser.
* @see #FILE_CHOOSER
*/
public static final AccessibleRole DIRECTORY_PANE
= new AccessibleRole("directorypane");
/**
* A specialized dialog that displays the files in the directory
* and lets the user select a file, browse a different directory,
* or specify a filename. May use the directory pane to show the
* contents of a directory.
* @see #DIRECTORY_PANE
*/
public static final AccessibleRole FILE_CHOOSER
= new AccessibleRole("filechooser");
/**
* An object that fills up space in a user interface. It is often
* used in interfaces to tweak the spacing between components,
* but serves no other purpose.
*/
public static final AccessibleRole FILLER
= new AccessibleRole("filler");
/**
* A hypertext anchor
*/
public static final AccessibleRole HYPERLINK
= new AccessibleRole("hyperlink");
/**
* A small fixed size picture, typically used to decorate components.
*/
public static final AccessibleRole ICON
= new AccessibleRole("icon");
/**
* An object used to present an icon or short string in an interface.
*/
public static final AccessibleRole LABEL
= new AccessibleRole("label");
/**
* A specialized pane that has a glass pane and a layered pane as its
* children.
* @see #GLASS_PANE
* @see #LAYERED_PANE
*/
public static final AccessibleRole ROOT_PANE
= new AccessibleRole("rootpane");
/**
* A pane that is guaranteed to be painted on top
* of all panes beneath it.
* @see #ROOT_PANE
* @see #CANVAS
*/
public static final AccessibleRole GLASS_PANE
= new AccessibleRole("glasspane");
/**
* A specialized pane that allows its children to be drawn in layers,
* providing a form of stacking order. This is usually the pane that
* holds the menu bar as well as the pane that contains most of the
* visual components in a window.
* @see #GLASS_PANE
* @see #ROOT_PANE
*/
public static final AccessibleRole LAYERED_PANE
= new AccessibleRole("layeredpane");
/**
* An object that presents a list of objects to the user and allows the
* user to select one or more of them. A list is usually contained
* within a scroll pane.
* @see #SCROLL_PANE
* @see #LIST_ITEM
*/
public static final AccessibleRole LIST
= new AccessibleRole("list");
/**
* An object that presents an element in a list. A list is usually
* contained within a scroll pane.
* @see #SCROLL_PANE
* @see #LIST
*/
public static final AccessibleRole LIST_ITEM
= new AccessibleRole("listitem");
/**
* An object usually drawn at the top of the primary dialog box of
* an application that contains a list of menus the user can choose
* from. For example, a menu bar might contain menus for "File,"
* "Edit," and "Help."
* @see #MENU
* @see #POPUP_MENU
* @see #LAYERED_PANE
*/
public static final AccessibleRole MENU_BAR
= new AccessibleRole("menubar");
/**
* A temporary window that is usually used to offer the user a
* list of choices, and then hides when the user selects one of
* those choices.
* @see #MENU
* @see #MENU_ITEM
*/
public static final AccessibleRole POPUP_MENU
= new AccessibleRole("popupmenu");
/**
* An object usually found inside a menu bar that contains a list
* of actions the user can choose from. A menu can have any object
* as its children, but most often they are menu items, other menus,
* or rudimentary objects such as radio buttons, check boxes, or
* separators. For example, an application may have an "Edit" menu
* that contains menu items for "Cut" and "Paste."
* @see #MENU_BAR
* @see #MENU_ITEM
* @see #SEPARATOR
* @see #RADIO_BUTTON
* @see #CHECK_BOX
* @see #POPUP_MENU
*/
public static final AccessibleRole MENU
= new AccessibleRole("menu");
/**
* An object usually contained in a menu that presents an action
* the user can choose. For example, the "Cut" menu item in an
* "Edit" menu would be an action the user can select to cut the
* selected area of text in a document.
* @see #MENU_BAR
* @see #SEPARATOR
* @see #POPUP_MENU
*/
public static final AccessibleRole MENU_ITEM
= new AccessibleRole("menuitem");
/**
* An object usually contained in a menu to provide a visual
* and logical separation of the contents in a menu. For example,
* the "File" menu of an application might contain menu items for
* "Open," "Close," and "Exit," and will place a separator between
* "Close" and "Exit" menu items.
* @see #MENU
* @see #MENU_ITEM
*/
public static final AccessibleRole SEPARATOR
= new AccessibleRole("separator");
/**
* An object that presents a series of panels (or page tabs), one at a
* time, through some mechanism provided by the object. The most common
* mechanism is a list of tabs at the top of the panel. The children of
* a page tab list are all page tabs.
* @see #PAGE_TAB
*/
public static final AccessibleRole PAGE_TAB_LIST
= new AccessibleRole("pagetablist");
/**
* An object that is a child of a page tab list. Its sole child is
* the panel that is to be presented to the user when the user
* selects the page tab from the list of tabs in the page tab list.
* @see #PAGE_TAB_LIST
*/
public static final AccessibleRole PAGE_TAB
= new AccessibleRole("pagetab");
/**
* A generic container that is often used to group objects.
*/
public static final AccessibleRole PANEL
= new AccessibleRole("panel");
/**
* An object used to indicate how much of a task has been completed.
*/
public static final AccessibleRole PROGRESS_BAR
= new AccessibleRole("progressbar");
/**
* A text object used for passwords, or other places where the
* text contents is not shown visibly to the user
*/
public static final AccessibleRole PASSWORD_TEXT
= new AccessibleRole("passwordtext");
/**
* An object the user can manipulate to tell the application to do
* something.
* @see #CHECK_BOX
* @see #TOGGLE_BUTTON
* @see #RADIO_BUTTON
*/
public static final AccessibleRole PUSH_BUTTON
= new AccessibleRole("pushbutton");
/**
* A specialized push button that can be checked or unchecked, but
* does not provide a separate indicator for the current state.
* @see #PUSH_BUTTON
* @see #CHECK_BOX
* @see #RADIO_BUTTON
*/
public static final AccessibleRole TOGGLE_BUTTON
= new AccessibleRole("togglebutton");
/**
* A choice that can be checked or unchecked and provides a
* separate indicator for the current state.
* @see #PUSH_BUTTON
* @see #TOGGLE_BUTTON
* @see #RADIO_BUTTON
*/
public static final AccessibleRole CHECK_BOX
= new AccessibleRole("checkbox");
/**
* A specialized check box that will cause other radio buttons in the
* same group to become unchecked when this one is checked.
* @see #PUSH_BUTTON
* @see #TOGGLE_BUTTON
* @see #CHECK_BOX
*/
public static final AccessibleRole RADIO_BUTTON
= new AccessibleRole("radiobutton");
/**
* The header for a row of data.
*/
public static final AccessibleRole ROW_HEADER
= new AccessibleRole("rowheader");
/**
* An object that allows a user to incrementally view a large amount
* of information. Its children can include scroll bars and a viewport.
* @see #SCROLL_BAR
* @see #VIEWPORT
*/
public static final AccessibleRole SCROLL_PANE
= new AccessibleRole("scrollpane");
/**
* An object usually used to allow a user to incrementally view a
* large amount of data. Usually used only by a scroll pane.
* @see #SCROLL_PANE
*/
public static final AccessibleRole SCROLL_BAR
= new AccessibleRole("scrollbar");
/**
* An object usually used in a scroll pane. It represents the portion
* of the entire data that the user can see. As the user manipulates
* the scroll bars, the contents of the viewport can change.
* @see #SCROLL_PANE
*/
public static final AccessibleRole VIEWPORT
= new AccessibleRole("viewport");
/**
* An object that allows the user to select from a bounded range. For
* example, a slider might be used to select a number between 0 and 100.
*/
public static final AccessibleRole SLIDER
= new AccessibleRole("slider");
/**
* A specialized panel that presents two other panels at the same time.
* Between the two panels is a divider the user can manipulate to make
* one panel larger and the other panel smaller.
*/
public static final AccessibleRole SPLIT_PANE
= new AccessibleRole("splitpane");
/**
* An object used to present information in terms of rows and columns.
* An example might include a spreadsheet application.
*/
public static final AccessibleRole TABLE
= new AccessibleRole("table");
/**
* An object that presents text to the user. The text is usually
* editable by the user as opposed to a label.
* @see #LABEL
*/
public static final AccessibleRole TEXT
= new AccessibleRole("text");
/**
* An object used to present hierarchical information to the user.
* The individual nodes in the tree can be collapsed and expanded
* to provide selective disclosure of the tree's contents.
*/
public static final AccessibleRole TREE
= new AccessibleRole("tree");
/**
* A bar or palette usually composed of push buttons or toggle buttons.
* It is often used to provide the most frequently used functions for an
* application.
*/
public static final AccessibleRole TOOL_BAR
= new AccessibleRole("toolbar");
/**
* An object that provides information about another object. The
* accessibleDescription property of the tool tip is often displayed
* to the user in a small "help bubble" when the user causes the
* mouse to hover over the object associated with the tool tip.
*/
public static final AccessibleRole TOOL_TIP
= new AccessibleRole("tooltip");
/**
* An AWT component, but nothing else is known about it.
* @see #SWING_COMPONENT
* @see #UNKNOWN
*/
public static final AccessibleRole AWT_COMPONENT
= new AccessibleRole("awtcomponent");
/**
* A Swing component, but nothing else is known about it.
* @see #AWT_COMPONENT
* @see #UNKNOWN
*/
public static final AccessibleRole SWING_COMPONENT
= new AccessibleRole("swingcomponent");
/**
* The object contains some Accessible information, but its role is
* not known.
* @see #AWT_COMPONENT
* @see #SWING_COMPONENT
*/
public static final AccessibleRole UNKNOWN
= new AccessibleRole("unknown");
/**
* A STATUS_BAR is an simple component that can contain
* multiple labels of status information to the user.
*/
public static final AccessibleRole STATUS_BAR
= new AccessibleRole("statusbar");
/**
* A DATE_EDITOR is a component that allows users to edit
* java.util.Date and java.util.Time objects
*/
public static final AccessibleRole DATE_EDITOR
= new AccessibleRole("dateeditor");
/**
* A SPIN_BOX is a simple spinner component and its main use
* is for simple numbers.
*/
public static final AccessibleRole SPIN_BOX
= new AccessibleRole("spinbox");
/**
* A FONT_CHOOSER is a component that lets the user pick various
* attributes for fonts.
*/
public static final AccessibleRole FONT_CHOOSER
= new AccessibleRole("fontchooser");
/**
* A GROUP_BOX is a simple container that contains a border
* around it and contains components inside it.
*/
public static final AccessibleRole GROUP_BOX
= new AccessibleRole("groupbox");
/**
* A text header
*
* @since 1.5
*/
public static final AccessibleRole HEADER =
new AccessibleRole("header");
/**
* A text footer
*
* @since 1.5
*/
public static final AccessibleRole FOOTER =
new AccessibleRole("footer");
/**
* A text paragraph
*
* @since 1.5
*/
public static final AccessibleRole PARAGRAPH =
new AccessibleRole("paragraph");
/**
* A ruler is an object used to measure distance
*
* @since 1.5
*/
public static final AccessibleRole RULER =
new AccessibleRole("ruler");
/**
* A role indicating the object acts as a formula for
* calculating a value. An example is a formula in
* a spreadsheet cell.
*
* @since 1.5
*/
static public final AccessibleRole EDITBAR =
new AccessibleRole("editbar");
/**
* A role indicating the object monitors the progress
* of some operation.
*
* @since 1.5
*/
static public final AccessibleRole PROGRESS_MONITOR =
new AccessibleRole("progressMonitor");
// The following are all under consideration for potential future use.
// public static final AccessibleRole APPLICATION
// = new AccessibleRole("application");
// public static final AccessibleRole BORDER
// = new AccessibleRole("border");
// public static final AccessibleRole CHECK_BOX_MENU_ITEM
// = new AccessibleRole("checkboxmenuitem");
// public static final AccessibleRole CHOICE
// = new AccessibleRole("choice");
// public static final AccessibleRole COLUMN
// = new AccessibleRole("column");
// public static final AccessibleRole CURSOR
// = new AccessibleRole("cursor");
// public static final AccessibleRole DOCUMENT
// = new AccessibleRole("document");
// public static final AccessibleRole IMAGE
// = new AccessibleRole("Image");
// public static final AccessibleRole INDICATOR
// = new AccessibleRole("indicator");
// public static final AccessibleRole RADIO_BUTTON_MENU_ITEM
// = new AccessibleRole("radiobuttonmenuitem");
// public static final AccessibleRole ROW
// = new AccessibleRole("row");
// public static final AccessibleRole TABLE_CELL
// = new AccessibleRole("tablecell");
// public static final AccessibleRole TREE_NODE
// = new AccessibleRole("treenode");
/**
* Creates a new AccessibleRole using the given locale independent key.
* This should not be a public method. Instead, it is used to create
* the constants in this file to make it a strongly typed enumeration.
* Subclasses of this class should enforce similar policy.
* <p>
* The key String should be a locale independent key for the role.
* It is not intended to be used as the actual String to display
* to the user. To get the localized string, use toDisplayString.
*
* @param key the locale independent name of the role.
* @see AccessibleBundle#toDisplayString
*/
protected AccessibleRole(String key) {
this.key = key;
}
}

View File

@@ -0,0 +1,114 @@
/*
* 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.accessibility;
/**
* This AccessibleSelection interface
* provides the standard mechanism for an assistive technology to determine
* what the current selected children are, as well as modify the selection set.
* Any object that has children that can be selected should support
* the AccessibleSelection interface. Applications can determine if an object supports the
* AccessibleSelection interface by first obtaining its AccessibleContext (see
* {@link Accessible}) and then calling the
* {@link AccessibleContext#getAccessibleSelection} method.
* If the return value is not null, the object supports this interface.
*
* @see Accessible
* @see Accessible#getAccessibleContext
* @see AccessibleContext
* @see AccessibleContext#getAccessibleSelection
*
* @author Peter Korn
* @author Hans Muller
* @author Willie Walker
*/
public interface AccessibleSelection {
/**
* Returns the number of Accessible children currently selected.
* If no children are selected, the return value will be 0.
*
* @return the number of items currently selected.
*/
public int getAccessibleSelectionCount();
/**
* Returns an Accessible representing the specified selected child
* of the object. If there isn't a selection, or there are
* fewer children selected than the integer passed in, the return
* value will be null.
* <p>Note that the index represents the i-th selected child, which
* is different from the i-th child.
*
* @param i the zero-based index of selected children
* @return the i-th selected child
* @see #getAccessibleSelectionCount
*/
public Accessible getAccessibleSelection(int i);
/**
* Determines if the current child of this object is selected.
*
* @return true if the current child of this object is selected; else false.
* @param i the zero-based index of the child in this Accessible object.
* @see AccessibleContext#getAccessibleChild
*/
public boolean isAccessibleChildSelected(int i);
/**
* Adds the specified Accessible child of the object to the object's
* selection. If the object supports multiple selections,
* the specified child is added to any existing selection, otherwise
* it replaces any existing selection in the object. If the
* specified child is already selected, this method has no effect.
*
* @param i the zero-based index of the child
* @see AccessibleContext#getAccessibleChild
*/
public void addAccessibleSelection(int i);
/**
* Removes the specified child of the object from the object's
* selection. If the specified item isn't currently selected, this
* method has no effect.
*
* @param i the zero-based index of the child
* @see AccessibleContext#getAccessibleChild
*/
public void removeAccessibleSelection(int i);
/**
* Clears the selection in the object, so that no children in the
* object are selected.
*/
public void clearAccessibleSelection();
/**
* Causes every child of the object to be selected
* if the object supports multiple selections.
*/
public void selectAllAccessibleSelection();
}

View File

@@ -0,0 +1,375 @@
/*
* Copyright (c) 1997, 2004, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact 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.accessibility;
import java.util.Vector;
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
/**
* <P>Class AccessibleState describes a component's particular state. The actual
* state of the component is defined as an AccessibleStateSet, which is a
* composed set of AccessibleStates.
* <p>The toDisplayString method allows you to obtain the localized string
* for a locale independent key from a predefined ResourceBundle for the
* keys defined in this class.
* <p>The constants in this class present a strongly typed enumeration
* of common object roles. A public constructor for this class has been
* purposely omitted and applications should use one of the constants
* from this class. If the constants in this class are not sufficient
* to describe the role of an object, a subclass should be generated
* from this class and it should provide constants in a similar manner.
*
* @author Willie Walker
* @author Peter Korn
*/
public class AccessibleState extends AccessibleBundle {
// If you add or remove anything from here, make sure you
// update AccessibleResourceBundle.java.
/**
* Indicates a window is currently the active window. This includes
* windows, dialogs, frames, etc. In addition, this state is used
* to indicate the currently active child of a component such as a
* list, table, or tree. For example, the active child of a list
* is the child that is drawn with a rectangle around it.
* @see AccessibleRole#WINDOW
* @see AccessibleRole#FRAME
* @see AccessibleRole#DIALOG
*/
public static final AccessibleState ACTIVE
= new AccessibleState("active");
/**
* Indicates this object is currently pressed. This is usually
* associated with buttons and indicates the user has pressed a
* mouse button while the pointer was over the button and has
* not yet released the mouse button.
* @see AccessibleRole#PUSH_BUTTON
*/
public static final AccessibleState PRESSED
= new AccessibleState("pressed");
/**
* Indicates that the object is armed. This is usually used on buttons
* that have been pressed but not yet released, and the mouse pointer
* is still over the button.
* @see AccessibleRole#PUSH_BUTTON
*/
public static final AccessibleState ARMED
= new AccessibleState("armed");
/**
* Indicates the current object is busy. This is usually used on objects
* such as progress bars, sliders, or scroll bars to indicate they are
* in a state of transition.
* @see AccessibleRole#PROGRESS_BAR
* @see AccessibleRole#SCROLL_BAR
* @see AccessibleRole#SLIDER
*/
public static final AccessibleState BUSY
= new AccessibleState("busy");
/**
* Indicates this object is currently checked. This is usually used on
* objects such as toggle buttons, radio buttons, and check boxes.
* @see AccessibleRole#TOGGLE_BUTTON
* @see AccessibleRole#RADIO_BUTTON
* @see AccessibleRole#CHECK_BOX
*/
public static final AccessibleState CHECKED
= new AccessibleState("checked");
/**
* Indicates the user can change the contents of this object. This
* is usually used primarily for objects that allow the user to
* enter text. Other objects, such as scroll bars and sliders,
* are automatically editable if they are enabled.
* @see #ENABLED
*/
public static final AccessibleState EDITABLE
= new AccessibleState("editable");
/**
* Indicates this object allows progressive disclosure of its children.
* This is usually used with hierarchical objects such as trees and
* is often paired with the EXPANDED or COLLAPSED states.
* @see #EXPANDED
* @see #COLLAPSED
* @see AccessibleRole#TREE
*/
public static final AccessibleState EXPANDABLE
= new AccessibleState("expandable");
/**
* Indicates this object is collapsed. This is usually paired with the
* EXPANDABLE state and is used on objects that provide progressive
* disclosure such as trees.
* @see #EXPANDABLE
* @see #EXPANDED
* @see AccessibleRole#TREE
*/
public static final AccessibleState COLLAPSED
= new AccessibleState("collapsed");
/**
* Indicates this object is expanded. This is usually paired with the
* EXPANDABLE state and is used on objects that provide progressive
* disclosure such as trees.
* @see #EXPANDABLE
* @see #COLLAPSED
* @see AccessibleRole#TREE
*/
public static final AccessibleState EXPANDED
= new AccessibleState("expanded");
/**
* Indicates this object is enabled. The absence of this state from an
* object's state set indicates this object is not enabled. An object
* that is not enabled cannot be manipulated by the user. In a graphical
* display, it is usually grayed out.
*/
public static final AccessibleState ENABLED
= new AccessibleState("enabled");
/**
* Indicates this object can accept keyboard focus, which means all
* events resulting from typing on the keyboard will normally be
* passed to it when it has focus.
* @see #FOCUSED
*/
public static final AccessibleState FOCUSABLE
= new AccessibleState("focusable");
/**
* Indicates this object currently has the keyboard focus.
* @see #FOCUSABLE
*/
public static final AccessibleState FOCUSED
= new AccessibleState("focused");
/**
* Indicates this object is minimized and is represented only by an
* icon. This is usually only associated with frames and internal
* frames.
* @see AccessibleRole#FRAME
* @see AccessibleRole#INTERNAL_FRAME
*/
public static final AccessibleState ICONIFIED
= new AccessibleState("iconified");
/**
* Indicates something must be done with this object before the
* user can interact with an object in a different window. This
* is usually associated only with dialogs.
* @see AccessibleRole#DIALOG
*/
public static final AccessibleState MODAL
= new AccessibleState("modal");
/**
* Indicates this object paints every pixel within its
* rectangular region. A non-opaque component paints only some of
* its pixels, allowing the pixels underneath it to "show through".
* A component that does not fully paint its pixels therefore
* provides a degree of transparency.
* @see Accessible#getAccessibleContext
* @see AccessibleContext#getAccessibleComponent
* @see AccessibleComponent#getBounds
*/
public static final AccessibleState OPAQUE
= new AccessibleState("opaque");
/**
* Indicates the size of this object is not fixed.
* @see Accessible#getAccessibleContext
* @see AccessibleContext#getAccessibleComponent
* @see AccessibleComponent#getSize
* @see AccessibleComponent#setSize
*/
public static final AccessibleState RESIZABLE
= new AccessibleState("resizable");
/**
* Indicates this object allows more than one of its children to
* be selected at the same time.
* @see Accessible#getAccessibleContext
* @see AccessibleContext#getAccessibleSelection
* @see AccessibleSelection
*/
public static final AccessibleState MULTISELECTABLE
= new AccessibleState("multiselectable");
/**
* Indicates this object is the child of an object that allows its
* children to be selected, and that this child is one of those
* children that can be selected.
* @see #SELECTED
* @see Accessible#getAccessibleContext
* @see AccessibleContext#getAccessibleSelection
* @see AccessibleSelection
*/
public static final AccessibleState SELECTABLE
= new AccessibleState("selectable");
/**
* Indicates this object is the child of an object that allows its
* children to be selected, and that this child is one of those
* children that has been selected.
* @see #SELECTABLE
* @see Accessible#getAccessibleContext
* @see AccessibleContext#getAccessibleSelection
* @see AccessibleSelection
*/
public static final AccessibleState SELECTED
= new AccessibleState("selected");
/**
* Indicates this object, the object's parent, the object's parent's
* parent, and so on, are all visible. Note that this does not
* necessarily mean the object is painted on the screen. It might
* be occluded by some other showing object.
* @see #VISIBLE
*/
public static final AccessibleState SHOWING
= new AccessibleState("showing");
/**
* Indicates this object is visible. Note: this means that the
* object intends to be visible; however, it may not in fact be
* showing on the screen because one of the objects that this object
* is contained by is not visible.
* @see #SHOWING
*/
public static final AccessibleState VISIBLE
= new AccessibleState("visible");
/**
* Indicates the orientation of this object is vertical. This is
* usually associated with objects such as scrollbars, sliders, and
* progress bars.
* @see #VERTICAL
* @see AccessibleRole#SCROLL_BAR
* @see AccessibleRole#SLIDER
* @see AccessibleRole#PROGRESS_BAR
*/
public static final AccessibleState VERTICAL
= new AccessibleState("vertical");
/**
* Indicates the orientation of this object is horizontal. This is
* usually associated with objects such as scrollbars, sliders, and
* progress bars.
* @see #HORIZONTAL
* @see AccessibleRole#SCROLL_BAR
* @see AccessibleRole#SLIDER
* @see AccessibleRole#PROGRESS_BAR
*/
public static final AccessibleState HORIZONTAL
= new AccessibleState("horizontal");
/**
* Indicates this (text) object can contain only a single line of text
*/
public static final AccessibleState SINGLE_LINE
= new AccessibleState("singleline");
/**
* Indicates this (text) object can contain multiple lines of text
*/
public static final AccessibleState MULTI_LINE
= new AccessibleState("multiline");
/**
* Indicates this object is transient. An assistive technology should
* not add a PropertyChange listener to an object with transient state,
* as that object will never generate any events. Transient objects
* are typically created to answer Java Accessibility method queries,
* but otherwise do not remain linked to the underlying object (for
* example, those objects underneath lists, tables, and trees in Swing,
* where only one actual UI Component does shared rendering duty for
* all of the data objects underneath the actual list/table/tree elements).
*
* @since 1.5
*
*/
public static final AccessibleState TRANSIENT
= new AccessibleState("transient");
/**
* Indicates this object is responsible for managing its
* subcomponents. This is typically used for trees and tables
* that have a large number of subcomponents and where the
* objects are created only when needed and otherwise remain virtual.
* The application should not manage the subcomponents directly.
*
* @since 1.5
*/
public static final AccessibleState MANAGES_DESCENDANTS
= new AccessibleState ("managesDescendants");
/**
* Indicates that the object state is indeterminate. An example
* is selected text that is partially bold and partially not
* bold. In this case the attributes associated with the selected
* text are indeterminate.
*
* @since 1.5
*/
public static final AccessibleState INDETERMINATE
= new AccessibleState ("indeterminate");
/**
* A state indicating that text is truncated by a bounding rectangle
* and that some of the text is not displayed on the screen. An example
* is text in a spreadsheet cell that is truncated by the bounds of
* the cell.
*
* @since 1.5
*/
static public final AccessibleState TRUNCATED
= new AccessibleState("truncated");
/**
* Creates a new AccessibleState using the given locale independent key.
* This should not be a public method. Instead, it is used to create
* the constants in this file to make it a strongly typed enumeration.
* Subclasses of this class should enforce similar policy.
* <p>
* The key String should be a locale independent key for the state.
* It is not intended to be used as the actual String to display
* to the user. To get the localized string, use toDisplayString.
*
* @param key the locale independent name of the state.
* @see AccessibleBundle#toDisplayString
*/
protected AccessibleState(String key) {
this.key = key;
}
}

View File

@@ -0,0 +1,199 @@
/*
* Copyright (c) 1997, 2004, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact 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.accessibility;
import java.util.Vector;
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
/**
* Class AccessibleStateSet determines a component's state set. The state set
* of a component is a set of AccessibleState objects and descriptions. E.G., The
* current overall state of the object, such as whether it is enabled,
* has focus, etc.
*
* @see AccessibleState
*
* @author Willie Walker
*/
public class AccessibleStateSet {
/**
* Each entry in the Vector represents an AccessibleState.
* @see #add
* @see #addAll
* @see #remove
* @see #contains
* @see #toArray
* @see #clear
*/
protected Vector<AccessibleState> states = null;
/**
* Creates a new empty state set.
*/
public AccessibleStateSet() {
states = null;
}
/**
* Creates a new state with the initial set of states contained in
* the array of states passed in. Duplicate entries are ignored.
*
* @param states an array of AccessibleState describing the state set.
*/
public AccessibleStateSet(AccessibleState[] states) {
if (states.length != 0) {
this.states = new Vector(states.length);
for (int i = 0; i < states.length; i++) {
if (!this.states.contains(states[i])) {
this.states.addElement(states[i]);
}
}
}
}
/**
* Adds a new state to the current state set if it is not already
* present. If the state is already in the state set, the state
* set is unchanged and the return value is false. Otherwise,
* the state is added to the state set and the return value is
* true.
* @param state the state to add to the state set
* @return true if state is added to the state set; false if the state set
* is unchanged
*/
public boolean add(AccessibleState state) {
// [[[ PENDING: WDW - the implementation of this does not need
// to always use a vector of states. It could be improved by
// caching the states as a bit set.]]]
if (states == null) {
states = new Vector();
}
if (!states.contains(state)) {
states.addElement(state);
return true;
} else {
return false;
}
}
/**
* Adds all of the states to the existing state set. Duplicate entries
* are ignored.
* @param states AccessibleState array describing the state set.
*/
public void addAll(AccessibleState[] states) {
if (states.length != 0) {
if (this.states == null) {
this.states = new Vector(states.length);
}
for (int i = 0; i < states.length; i++) {
if (!this.states.contains(states[i])) {
this.states.addElement(states[i]);
}
}
}
}
/**
* Removes a state from the current state set. If the state is not
* in the set, the state set will be unchanged and the return value
* will be false. If the state is in the state set, it will be removed
* from the set and the return value will be true.
*
* @param state the state to remove from the state set
* @return true if the state is in the state set; false if the state set
* will be unchanged
*/
public boolean remove(AccessibleState state) {
if (states == null) {
return false;
} else {
return states.removeElement(state);
}
}
/**
* Removes all the states from the current state set.
*/
public void clear() {
if (states != null) {
states.removeAllElements();
}
}
/**
* Checks if the current state is in the state set.
* @param state the state
* @return true if the state is in the state set; otherwise false
*/
public boolean contains(AccessibleState state) {
if (states == null) {
return false;
} else {
return states.contains(state);
}
}
/**
* Returns the current state set as an array of AccessibleState
* @return AccessibleState array containing the current state.
*/
public AccessibleState[] toArray() {
if (states == null) {
return new AccessibleState[0];
} else {
AccessibleState[] stateArray = new AccessibleState[states.size()];
for (int i = 0; i < stateArray.length; i++) {
stateArray[i] = (AccessibleState) states.elementAt(i);
}
return stateArray;
}
}
/**
* Creates a localized String representing all the states in the set
* using the default locale.
*
* @return comma separated localized String
* @see AccessibleBundle#toDisplayString
*/
public String toString() {
String ret = null;
if ((states != null) && (states.size() > 0)) {
ret = ((AccessibleState) (states.elementAt(0))).toDisplayString();
for (int i = 1; i < states.size(); i++) {
ret = ret + ","
+ ((AccessibleState) (states.elementAt(i))).
toDisplayString();
}
}
return ret;
}
}

View File

@@ -0,0 +1,65 @@
/*
* Copyright (c) 2003, 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.accessibility;
import java.io.InputStream;
import java.awt.datatransfer.DataFlavor;
/**
*
* The <code>AccessibleStreamable</code> interface should be implemented
* by the <code>AccessibleContext</code> of any component that presents the
* raw stream behind a component on the display screen. Examples of such
* components are HTML, bitmap images and MathML. An object that implements
* <code>AccessibleStreamable</code> provides two things: a list of MIME
* types supported by the object and a streaming interface for each MIME type to
* get the data.
*
* @author Lynn Monsanto
* @author Peter Korn
*
* @see javax.accessibility.AccessibleContext
* @since 1.5
*/
public interface AccessibleStreamable {
/**
* Returns an array of DataFlavor objects for the MIME types
* this object supports.
*
* @return an array of DataFlavor objects for the MIME types
* this object supports.
*/
DataFlavor[] getMimeTypes();
/**
* Returns an InputStream for a DataFlavor
*
* @param flavor the DataFlavor
* @return an ImputStream if an ImputStream for this DataFlavor exists.
* Otherwise, null is returned.
*/
InputStream getStream(DataFlavor flavor);
}

View File

@@ -0,0 +1,222 @@
/*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.accessibility;
/**
* Class AccessibleTable describes a user-interface component that
* presents data in a two-dimensional table format.
*
* @author Lynn Monsanto
* @since 1.3
*/
public interface AccessibleTable {
/**
* Returns the caption for the table.
*
* @return the caption for the table
*/
public Accessible getAccessibleCaption();
/**
* Sets the caption for the table.
*
* @param a the caption for the table
*/
public void setAccessibleCaption(Accessible a);
/**
* Returns the summary description of the table.
*
* @return the summary description of the table
*/
public Accessible getAccessibleSummary();
/**
* Sets the summary description of the table
*
* @param a the summary description of the table
*/
public void setAccessibleSummary(Accessible a);
/**
* Returns the number of rows in the table.
*
* @return the number of rows in the table
*/
public int getAccessibleRowCount();
/**
* Returns the number of columns in the table.
*
* @return the number of columns in the table
*/
public int getAccessibleColumnCount();
/**
* Returns the Accessible at a specified row and column
* in the table.
*
* @param r zero-based row of the table
* @param c zero-based column of the table
* @return the Accessible at the specified row and column
*/
public Accessible getAccessibleAt(int r, int c);
/**
* Returns the number of rows occupied by the Accessible at
* a specified row and column in the table.
*
* @param r zero-based row of the table
* @param c zero-based column of the table
* @return the number of rows occupied by the Accessible at a
* given specified (row, column)
*/
public int getAccessibleRowExtentAt(int r, int c);
/**
* Returns the number of columns occupied by the Accessible at
* a specified row and column in the table.
*
* @param r zero-based row of the table
* @param c zero-based column of the table
* @return the number of columns occupied by the Accessible at a
* given specified row and column
*/
public int getAccessibleColumnExtentAt(int r, int c);
/**
* Returns the row headers as an AccessibleTable.
*
* @return an AccessibleTable representing the row
* headers
*/
public AccessibleTable getAccessibleRowHeader();
/**
* Sets the row headers.
*
* @param table an AccessibleTable representing the
* row headers
*/
public void setAccessibleRowHeader(AccessibleTable table);
/**
* Returns the column headers as an AccessibleTable.
*
* @return an AccessibleTable representing the column
* headers
*/
public AccessibleTable getAccessibleColumnHeader();
/**
* Sets the column headers.
*
* @param table an AccessibleTable representing the
* column headers
*/
public void setAccessibleColumnHeader(AccessibleTable table);
/**
* Returns the description of the specified row in the table.
*
* @param r zero-based row of the table
* @return the description of the row
*/
public Accessible getAccessibleRowDescription(int r);
/**
* Sets the description text of the specified row of the table.
*
* @param r zero-based row of the table
* @param a the description of the row
*/
public void setAccessibleRowDescription(int r, Accessible a);
/**
* Returns the description text of the specified column in the table.
*
* @param c zero-based column of the table
* @return the text description of the column
*/
public Accessible getAccessibleColumnDescription(int c);
/**
* Sets the description text of the specified column in the table.
*
* @param c zero-based column of the table
* @param a the text description of the column
*/
public void setAccessibleColumnDescription(int c, Accessible a);
/**
* Returns a boolean value indicating whether the accessible at
* a specified row and column is selected.
*
* @param r zero-based row of the table
* @param c zero-based column of the table
* @return the boolean value true if the accessible at the
* row and column is selected. Otherwise, the boolean value
* false
*/
public boolean isAccessibleSelected(int r, int c);
/**
* Returns a boolean value indicating whether the specified row
* is selected.
*
* @param r zero-based row of the table
* @return the boolean value true if the specified row is selected.
* Otherwise, false.
*/
public boolean isAccessibleRowSelected(int r);
/**
* Returns a boolean value indicating whether the specified column
* is selected.
*
* @param c zero-based column of the table
* @return the boolean value true if the specified column is selected.
* Otherwise, false.
*/
public boolean isAccessibleColumnSelected(int c);
/**
* Returns the selected rows in a table.
*
* @return an array of selected rows where each element is a
* zero-based row of the table
*/
public int [] getSelectedAccessibleRows();
/**
* Returns the selected columns in a table.
*
* @return an array of selected columns where each element is a
* zero-based column of the table
*/
public int [] getSelectedAccessibleColumns();
}

View File

@@ -0,0 +1,105 @@
/*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.accessibility;
/**
* The AccessibleTableModelChange interface describes a change to
* the table model. The attributes of the model change can be
* obtained by the following methods:
* <ul>
* <li> public int getType()
* <li> public int getFirstRow();
* <li> public int getLastRow();
* <li> public int getFirstColumn();
* <li> public int getLastColumn();
* </ul>
* The model change type returned by getType() will be one of:
* <ul>
* <li> INSERT - one or more rows and/or columns have been inserted
* <li> UPDATE - some of the table data has changed
* <li> DELETE - one or more rows and/or columns have been deleted
* </ul>
* The affected area of the table can be determined by the other
* four methods which specify ranges of rows and columns
*
* @see Accessible
* @see Accessible#getAccessibleContext
* @see AccessibleContext
* @see AccessibleContext#getAccessibleTable
*
* @author Lynn Monsanto
* @since 1.3
*/
public interface AccessibleTableModelChange {
/**
* Identifies the insertion of new rows and/or columns.
*/
public static final int INSERT = 1;
/**
* Identifies a change to existing data.
*/
public static final int UPDATE = 0;
/**
* Identifies the deletion of rows and/or columns.
*/
public static final int DELETE = -1;
/**
* Returns the type of event.
* @return the type of event
* @see #INSERT
* @see #UPDATE
* @see #DELETE
*/
public int getType();
/**
* Returns the first row that changed.
* @return the first row that changed
*/
public int getFirstRow();
/**
* Returns the last row that changed.
* @return the last row that changed
*/
public int getLastRow();
/**
* Returns the first column that changed.
* @return the first column that changed
*/
public int getFirstColumn();
/**
* Returns the last column that changed.
* @return the last column that changed
*/
public int getLastColumn();
}

View File

@@ -0,0 +1,188 @@
/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.accessibility;
import java.util.*;
import java.awt.*;
import javax.swing.text.*;
/**
* <P>The AccessibleText interface should be implemented by all
* classes that present textual information on the display. This interface
* provides the standard mechanism for an assistive technology to access
* that text via its content, attributes, and spatial location.
* Applications can determine if an object supports the AccessibleText
* interface by first obtaining its AccessibleContext (see {@link Accessible})
* and then calling the {@link AccessibleContext#getAccessibleText} method of
* AccessibleContext. If the return value is not null, the object supports this
* interface.
*
* @see Accessible
* @see Accessible#getAccessibleContext
* @see AccessibleContext
* @see AccessibleContext#getAccessibleText
*
* @author Peter Korn
*/
public interface AccessibleText {
/**
* Constant used to indicate that the part of the text that should be
* retrieved is a character.
*
* @see #getAtIndex
* @see #getAfterIndex
* @see #getBeforeIndex
*/
public static final int CHARACTER = 1;
/**
* Constant used to indicate that the part of the text that should be
* retrieved is a word.
*
* @see #getAtIndex
* @see #getAfterIndex
* @see #getBeforeIndex
*/
public static final int WORD = 2;
/**
* Constant used to indicate that the part of the text that should be
* retrieved is a sentence.
*
* A sentence is a string of words which expresses an assertion,
* a question, a command, a wish, an exclamation, or the performance
* of an action. In English locales, the string usually begins with
* a capital letter and concludes with appropriate end punctuation;
* such as a period, question or exclamation mark. Other locales may
* use different capitalization and/or punctuation.
*
* @see #getAtIndex
* @see #getAfterIndex
* @see #getBeforeIndex
*/
public static final int SENTENCE = 3;
/**
* Given a point in local coordinates, return the zero-based index
* of the character under that Point. If the point is invalid,
* this method returns -1.
*
* @param p the Point in local coordinates
* @return the zero-based index of the character under Point p; if
* Point is invalid return -1.
*/
public int getIndexAtPoint(Point p);
/**
* Determines the bounding box of the character at the given
* index into the string. The bounds are returned in local
* coordinates. If the index is invalid an empty rectangle is returned.
*
* @param i the index into the String
* @return the screen coordinates of the character's bounding box,
* if index is invalid return an empty rectangle.
*/
public Rectangle getCharacterBounds(int i);
/**
* Returns the number of characters (valid indicies)
*
* @return the number of characters
*/
public int getCharCount();
/**
* Returns the zero-based offset of the caret.
*
* Note: That to the right of the caret will have the same index
* value as the offset (the caret is between two characters).
* @return the zero-based offset of the caret.
*/
public int getCaretPosition();
/**
* Returns the String at a given index.
*
* @param part the CHARACTER, WORD, or SENTENCE to retrieve
* @param index an index within the text
* @return the letter, word, or sentence
*/
public String getAtIndex(int part, int index);
/**
* Returns the String after a given index.
*
* @param part the CHARACTER, WORD, or SENTENCE to retrieve
* @param index an index within the text
* @return the letter, word, or sentence
*/
public String getAfterIndex(int part, int index);
/**
* Returns the String before a given index.
*
* @param part the CHARACTER, WORD, or SENTENCE to retrieve
* @param index an index within the text
* @return the letter, word, or sentence
*/
public String getBeforeIndex(int part, int index);
/**
* Returns the AttributeSet for a given character at a given index
*
* @param i the zero-based index into the text
* @return the AttributeSet of the character
*/
public AttributeSet getCharacterAttribute(int i);
/**
* Returns the start offset within the selected text.
* If there is no selection, but there is
* a caret, the start and end offsets will be the same.
*
* @return the index into the text of the start of the selection
*/
public int getSelectionStart();
/**
* Returns the end offset within the selected text.
* If there is no selection, but there is
* a caret, the start and end offsets will be the same.
*
* @return the index into the text of the end of the selection
*/
public int getSelectionEnd();
/**
* Returns the portion of the text that is selected.
*
* @return the String portion of the text that is selected
*/
public String getSelectedText();
}

View File

@@ -0,0 +1,76 @@
/*
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.accessibility;
/**
* <P>The AccessibleTextSequence provides information about
* a contiguous sequence of text.
*
* @see Accessible
* @see Accessible#getAccessibleContext
* @see AccessibleContext
* @see AccessibleContext#getAccessibleText
* @see AccessibleAttributeSequence
*
* @author Lynn Monsanto
*/
/**
* This class collects together key details of a span of text. It
* is used by implementors of the class <code>AccessibleExtendedText</code> in
* order to return the requested triplet of a <code>String</code>, and the
* start and end indicies/offsets into a larger body of text that the
* <code>String</code> comes from.
*
* @see javax.accessibility.AccessibleExtendedText
*/
public class AccessibleTextSequence {
/** The start index of the text sequence */
public int startIndex;
/** The end index of the text sequence */
public int endIndex;
/** The text */
public String text;
/**
* Constructs an <code>AccessibleTextSequence</code> with the given
* parameters.
*
* @param start the beginning index of the span of text
* @param end the ending index of the span of text
* @param txt the <code>String</code> shared by this text span
*
* @since 1.6
*/
public AccessibleTextSequence(int start, int end, String txt) {
startIndex = start;
endIndex = end;
text = txt;
}
};

View File

@@ -0,0 +1,93 @@
/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.accessibility;
/**
* The AccessibleValue interface should be supported by any object
* that supports a numerical value (e.g., a scroll bar). This interface
* provides the standard mechanism for an assistive technology to determine
* and set the numerical value as well as get the minimum and maximum values.
* Applications can determine
* if an object supports the AccessibleValue interface by first
* obtaining its AccessibleContext (see
* {@link Accessible}) and then calling the
* {@link AccessibleContext#getAccessibleValue} method.
* If the return value is not null, the object supports this interface.
*
* @see Accessible
* @see Accessible#getAccessibleContext
* @see AccessibleContext
* @see AccessibleContext#getAccessibleValue
*
* @author Peter Korn
* @author Hans Muller
* @author Willie Walker
*/
public interface AccessibleValue {
/**
* Get the value of this object as a Number. If the value has not been
* set, the return value will be null.
*
* @return value of the object
* @see #setCurrentAccessibleValue
*/
public Number getCurrentAccessibleValue();
/**
* Set the value of this object as a Number.
*
* @param n the number to use for the value
* @return True if the value was set; else False
* @see #getCurrentAccessibleValue
*/
public boolean setCurrentAccessibleValue(Number n);
// /**
// * Get the description of the value of this object.
// *
// * @return description of the value of the object
// */
// public String getAccessibleValueDescription();
/**
* Get the minimum value of this object as a Number.
*
* @return Minimum value of the object; null if this object does not
* have a minimum value
* @see #getMaximumAccessibleValue
*/
public Number getMinimumAccessibleValue();
/**
* Get the maximum value of this object as a Number.
*
* @return Maximum value of the object; null if this object does not
* have a maximum value
* @see #getMinimumAccessibleValue
*/
public Number getMaximumAccessibleValue();
}

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,235 @@
/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.activation;
import java.util.Map;
import java.util.WeakHashMap;
/**
* 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;
private static Map<ClassLoader,CommandMap> map =
new WeakHashMap<ClassLoader,CommandMap>();
/**
* 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 synchronized CommandMap getDefaultCommandMap() {
if (defaultCommandMap != null)
return defaultCommandMap;
// fetch per-thread-context-class-loader default
ClassLoader tccl = SecuritySupport.getContextClassLoader();
CommandMap def = map.get(tccl);
if (def == null) {
def = new MailcapCommandMap();
map.put(tccl, def);
}
return def;
}
/**
* 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 synchronized 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 (non-system) class loader (e.g.,
// the JAF classes were loaded with the applet classes).
if (CommandMap.class.getClassLoader() == null ||
CommandMap.class.getClassLoader() !=
commandMap.getClass().getClassLoader())
throw ex;
}
}
// remove any per-thread-context-class-loader CommandMap
map.remove(SecuritySupport.getContextClassLoader());
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,899 @@
/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package 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();
if (transferFlavors == emptyFlavors)
return transferFlavors;
else
return transferFlavors.clone();
}
/**
* 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,132 @@
/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.activation;
import java.io.File;
import java.util.Map;
import java.util.WeakHashMap;
/**
* 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;
private static Map<ClassLoader,FileTypeMap> map =
new WeakHashMap<ClassLoader,FileTypeMap>();
/**
* 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 fileTypeMap The FileTypeMap.
* @exception SecurityException if the caller doesn't have permission
* to change the default
*/
public static synchronized void setDefaultFileTypeMap(FileTypeMap fileTypeMap) {
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 (non-system) class loader (e.g.,
// the JAF classes were loaded with the applet classes).
if (FileTypeMap.class.getClassLoader() == null ||
FileTypeMap.class.getClassLoader() !=
fileTypeMap.getClass().getClassLoader())
throw ex;
}
}
// remove any per-thread-context-class-loader FileTypeMap
map.remove(SecuritySupport.getContextClassLoader());
defaultMap = fileTypeMap;
}
/**
* 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 synchronized FileTypeMap getDefaultFileTypeMap() {
if (defaultMap != null)
return defaultMap;
// fetch per-thread-context-class-loader default
ClassLoader tccl = SecuritySupport.getContextClassLoader();
FileTypeMap def = map.get(tccl);
if (def == null) {
def = new MimetypesFileTypeMap();
map.put(tccl, def);
}
return def;
}
}

View File

@@ -0,0 +1,693 @@
/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package 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.
*/
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");
mf = loadResource("/META-INF/mailcap.default");
if (mf != null)
dbv.add(mf);
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,328 @@
/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package 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.
*/
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");
mf = loadResource("/META-INF/mimetypes.default");
if (mf != null)
dbv.addElement(mf);
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,74 @@
/*
* Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact 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.activity;
/**
* This exception may be thrown on any method for which Activity context is
* accessed and indicates that ongoing work within the Activity is not
* possible. This may be because the Activity has been instructed to complete
* with CompletionStatusFailOnly or has ended as a result of a timeout. This
* exception will be propagated across ORB boundaries via an
* org.omg.CORBA.ACTIVITY_COMPLETED system exception. An application should
* handle this error by attempting to complete the Activity.
*/
public class ActivityCompletedException extends java.rmi.RemoteException
{
/**
* Constructs a new instance with null as its detail message.
*/
public ActivityCompletedException() { super(); }
/**
* Constructs a new instance with the specified detail message.
*
* @param message the detail message.
*/
public ActivityCompletedException(String message) {
super(message);
}
/**
* Constructs a new throwable with the specified cause.
*
* @param cause a chained exception of type
* <code>Throwable</code>.
*/
public ActivityCompletedException(Throwable cause) {
this("", cause);
}
/**
* Constructs a new throwable with the specified detail message and cause.
*
* @param message the detail message.
*
* @param cause a chained exception of type
* <code>Throwable</code>.
*/
public ActivityCompletedException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@@ -0,0 +1,72 @@
/*
* Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact 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.activity;
/**
* This exception is thrown by a container if Activity context is not received
* on a method for which Activity context is mandatory. This exception
* indicates a deployment or application configuration error. This exception
* will be propagated across ORB boundaries via an
* org.omg.CORBA.ACTIVITY_REQUIRED system exception.
*/
public class ActivityRequiredException extends java.rmi.RemoteException
{
/**
* Constructs a new instance with null as its detail message.
*/
public ActivityRequiredException() { super(); }
/**
* Constructs a new instance with the specified detail message.
*
* @param message the detail message.
*/
public ActivityRequiredException(String message) {
super(message);
}
/**
* Constructs a new throwable with the specified cause.
*
* @param cause a chained exception of type
* <code>Throwable</code>.
*/
public ActivityRequiredException(Throwable cause) {
this("", cause);
}
/**
* Constructs a new throwable with the specified detail message and cause.
*
* @param message the detail message.
*
* @param cause a chained exception of type
* <code>Throwable</code>.
*/
public ActivityRequiredException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@@ -0,0 +1,76 @@
/*
* Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact 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.activity;
/**
* This exception may be thrown on any method for which Activity context
* is accessed and indicates that the attempted invocation or the Activity
* context associated with the attempted invocation is incompatible with
* the Activity's current state. It may also be thrown by a container if
* Activity context is received on a method for which Activity context is
* forbidden. This exception will be propagated across J2EE Activity Service
* ORB boundaries via an org.omg.CORBA.INVALID_ACTIVITY system exception.
* An application should handle this error by attempting to complete the
* Activity.
*/
public class InvalidActivityException extends java.rmi.RemoteException
{
/**
* Constructs a new instance with null as its detail message.
*/
public InvalidActivityException() { super(); }
/**
* Constructs a new instance with the specified detail message.
*
* @param message the detail message.
*/
public InvalidActivityException(String message) {
super(message);
}
/**
* Constructs a new throwable with the specified cause.
*
* @param cause a chained exception of type
* <code>Throwable</code>.
*/
public InvalidActivityException(Throwable cause) {
this("", cause);
}
/**
* Constructs a new throwable with the specified detail message and cause.
*
* @param message the detail message.
*
* @param cause a chained exception of type
* <code>Throwable</code>.
*/
public InvalidActivityException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@@ -0,0 +1,71 @@
/*
* Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.annotation;
import java.lang.annotation.*;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.*;
/**
* The Generated annotation is used to mark source code that has been generated.
* It can also be used to differentiate user written code from generated code
* in a single file. When used, the value element must have the name of the
* code generator. The recommended convention is to use the fully qualified
* name of the code generator in the value field .
* <p>For example: com.company.package.classname.
* The date element is used to indicate the date the source was generated.
* The date element must follow the ISO 8601 standard. For example the date
* element would have the following value 2001-07-04T12:08:56.235-0700
* which represents 2001-07-04 12:08:56 local time in the U.S. Pacific
* Time time zone.</p>
* <p>The comment element is a place holder for any comments that the code
* generator may want to include in the generated code.</p>
*
* @since Common Annotations 1.0
*/
@Documented
@Retention(SOURCE)
@Target({PACKAGE, TYPE, ANNOTATION_TYPE, METHOD, CONSTRUCTOR, FIELD,
LOCAL_VARIABLE, PARAMETER})
public @interface Generated {
/**
* The value element MUST have the name of the code generator.
* The recommended convention is to use the fully qualified name of the
* code generator. For example: com.acme.generator.CodeGen.
*/
String[] value();
/**
* Date when the source was generated.
*/
String date() default "";
/**
* A place holder for any comments that the code generator may want to
* include in the generated code.
*/
String comments() default "";
}

View File

@@ -0,0 +1,81 @@
/*
* Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.annotation;
import java.lang.annotation.*;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.*;
/**
* The PostConstruct annotation is used on a method that needs to be executed
* after dependency injection is done to perform any initialization. This
* method MUST be invoked before the class is put into service. This
* annotation MUST be supported on all classes that support dependency
* injection. The method annotated with PostConstruct MUST be invoked even
* if the class does not request any resources to be injected. Only one
* method can be annotated with this annotation. The method on which the
* PostConstruct annotation is applied MUST fulfill all of the following
* criteria:
* <p>
* <ul>
* <li>The method MUST NOT have any parameters except in the case of
* interceptors in which case it takes an InvocationContext object as
* defined by the Interceptors specification.</li>
* <li>The method defined on an interceptor class MUST HAVE one of the
* following signatures:
* <p>
* void &#060;METHOD&#062;(InvocationContext)
* <p>
* Object &#060;METHOD&#062;(InvocationContext) throws Exception
* <p>
* <i>Note: A PostConstruct interceptor method must not throw application
* exceptions, but it may be declared to throw checked exceptions including
* the java.lang.Exception if the same interceptor method interposes on
* business or timeout methods in addition to lifecycle events. If a
* PostConstruct interceptor method returns a value, it is ignored by
* the container.</i>
* </li>
* <li>The method defined on a non-interceptor class MUST HAVE the
* following signature:
* <p>
* void &#060;METHOD&#062;()
* </li>
* <li>The method on which PostConstruct is applied MAY be public, protected,
* package private or private.</li>
* <li>The method MUST NOT be static except for the application client.</li>
* <li>The method MAY be final.</li>
* <li>If the method throws an unchecked exception the class MUST NOT be put into
* service except in the case of EJBs where the EJB can handle exceptions and
* even recover from them.</li></ul>
* @since Common Annotations 1.0
* @see javax.annotation.PreDestroy
* @see javax.annotation.Resource
*/
@Documented
@Retention (RUNTIME)
@Target(METHOD)
public @interface PostConstruct {
}

View File

@@ -0,0 +1,82 @@
/*
* Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.annotation;
import java.lang.annotation.*;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.*;
/**
* The PreDestroy annotation is used on methods as a callback notification to
* signal that the instance is in the process of being removed by the
* container. The method annotated with PreDestroy is typically used to
* release resources that it has been holding. This annotation MUST be
* supported by all container managed objects that support PostConstruct
* except the application client container in Java EE 5. The method on which
* the PreDestroy annotation is applied MUST fulfill all of the following
* criteria:
* <p>
* <ul>
* <li>The method MUST NOT have any parameters except in the case of
* interceptors in which case it takes an InvocationContext object as
* defined by the Interceptors specification.</li>
* <li>The method defined on an interceptor class MUST HAVE one of the
* following signatures:
* <p>
* void &#060;METHOD&#062;(InvocationContext)
* <p>
* Object &#060;METHOD&#062;(InvocationContext) throws Exception
* <p>
* <i>Note: A PreDestroy interceptor method must not throw application
* exceptions, but it may be declared to throw checked exceptions including
* the java.lang.Exception if the same interceptor method interposes on
* business or timeout methods in addition to lifecycle events. If a
* PreDestroy interceptor method returns a value, it is ignored by
* the container.</i>
* </li>
* <li>The method defined on a non-interceptor class MUST HAVE the
* following signature:
* <p>
* void &#060;METHOD&#062;()
* </li>
* <li>The method on which PreDestroy is applied MAY be public, protected,
* package private or private.</li>
* <li>The method MUST NOT be static.</li>
* <li>The method MAY be final.</li>
* <li>If the method throws an unchecked exception it is ignored except in the
* case of EJBs where the EJB can handle exceptions.</li>
* </ul>
*
* @see javax.annotation.PostConstruct
* @see javax.annotation.Resource
* @since Common Annotations 1.0
*/
@Documented
@Retention (RUNTIME)
@Target(METHOD)
public @interface PreDestroy {
}

View File

@@ -0,0 +1,132 @@
/*
* Copyright (c) 2005, 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 javax.annotation;
import java.lang.annotation.*;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.*;
/**
* The Resource annotation marks a resource that is needed
* by the application. This annotation may be applied to an
* application component class, or to fields or methods of the
* component class. When the annotation is applied to a
* field or method, the container will inject an instance
* of the requested resource into the application component
* when the component is initialized. If the annotation is
* applied to the component class, the annotation declares a
* resource that the application will look up at runtime. <p>
*
* Even though this annotation is not marked Inherited, deployment
* tools are required to examine all superclasses of any component
* class to discover all uses of this annotation in all superclasses.
* All such annotation instances specify resources that are needed
* by the application component. Note that this annotation may
* appear on private fields and methods of superclasses; the container
* is required to perform injection in these cases as well.
*
* @since Common Annotations 1.0
*/
@Target({TYPE, FIELD, METHOD})
@Retention(RUNTIME)
public @interface Resource {
/**
* The JNDI name of the resource. For field annotations,
* the default is the field name. For method annotations,
* the default is the JavaBeans property name corresponding
* to the method. For class annotations, there is no default
* and this must be specified.
*/
String name() default "";
/**
* The name of the resource that the reference points to. It can
* link to any compatible resource using the global JNDI names.
*
* @since Common Annotations 1.1
*/
String lookup() default "";
/**
* The Java type of the resource. For field annotations,
* the default is the type of the field. For method annotations,
* the default is the type of the JavaBeans property.
* For class annotations, there is no default and this must be
* specified.
*/
Class<?> type() default java.lang.Object.class;
/**
* The two possible authentication types for a resource.
*/
enum AuthenticationType {
CONTAINER,
APPLICATION
}
/**
* The authentication type to use for this resource.
* This may be specified for resources representing a
* connection factory of any supported type, and must
* not be specified for resources of other types.
*/
AuthenticationType authenticationType() default AuthenticationType.CONTAINER;
/**
* Indicates whether this resource can be shared between
* this component and other components.
* This may be specified for resources representing a
* connection factory of any supported type, and must
* not be specified for resources of other types.
*/
boolean shareable() default true;
/**
* A product specific name that this resource should be mapped to.
* The name of this resource, as defined by the <code>name</code>
* element or defaulted, is a name that is local to the application
* component using the resource. (It's a name in the JNDI
* <code>java:comp/env</code> namespace.) Many application servers
* provide a way to map these local names to names of resources
* known to the application server. This mapped name is often a
* <i>global</i> JNDI name, but may be a name of any form. <p>
*
* Application servers are not required to support any particular
* form or type of mapped name, nor the ability to use mapped names.
* The mapped name is product-dependent and often installation-dependent.
* No use of a mapped name is portable.
*/
String mappedName() default "";
/**
* Description of this resource. The description is expected
* to be in the default language of the system on which the
* application is deployed. The description can be presented
* to the Deployer to help in choosing the correct resource.
*/
String description() default "";
}

View File

@@ -0,0 +1,46 @@
/*
* Copyright (c) 2005, 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 javax.annotation;
import java.lang.annotation.*;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.*;
/**
* This class is used to allow multiple resources declarations.
*
* @see javax.annotation.Resource
* @since Common Annotations 1.0
*/
@Documented
@Retention(RUNTIME)
@Target(TYPE)
public @interface Resources {
/**
* Array used for multiple resource declarations.
*/
Resource[] value();
}

View File

@@ -0,0 +1,195 @@
/*
* Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.annotation.processing;
import java.util.Set;
import java.util.HashSet;
import java.util.Collections;
import java.util.Objects;
import javax.lang.model.element.*;
import javax.lang.model.SourceVersion;
import javax.tools.Diagnostic;
/**
* An abstract annotation processor designed to be a convenient
* superclass for most concrete annotation processors. This class
* examines annotation values to compute the {@linkplain
* #getSupportedOptions options}, {@linkplain
* #getSupportedAnnotationTypes annotation types}, and {@linkplain
* #getSupportedSourceVersion source version} supported by its
* subtypes.
*
* <p>The getter methods may {@linkplain Messager#printMessage issue
* warnings} about noteworthy conditions using the facilities available
* after the processor has been {@linkplain #isInitialized
* initialized}.
*
* <p>Subclasses are free to override the implementation and
* specification of any of the methods in this class as long as the
* general {@link javax.annotation.processing.Processor Processor}
* contract for that method is obeyed.
*
* @author Joseph D. Darcy
* @author Scott Seligman
* @author Peter von der Ah&eacute;
* @since 1.6
*/
public abstract class AbstractProcessor implements Processor {
/**
* Processing environment providing by the tool framework.
*/
protected ProcessingEnvironment processingEnv;
private boolean initialized = false;
/**
* Constructor for subclasses to call.
*/
protected AbstractProcessor() {}
/**
* If the processor class is annotated with {@link
* SupportedOptions}, return an unmodifiable set with the same set
* of strings as the annotation. If the class is not so
* annotated, an empty set is returned.
*
* @return the options recognized by this processor, or an empty
* set if none
*/
public Set<String> getSupportedOptions() {
SupportedOptions so = this.getClass().getAnnotation(SupportedOptions.class);
if (so == null)
return Collections.emptySet();
else
return arrayToSet(so.value());
}
/**
* If the processor class is annotated with {@link
* SupportedAnnotationTypes}, return an unmodifiable set with the
* same set of strings as the annotation. If the class is not so
* annotated, an empty set is returned.
*
* @return the names of the annotation types supported by this
* processor, or an empty set if none
*/
public Set<String> getSupportedAnnotationTypes() {
SupportedAnnotationTypes sat = this.getClass().getAnnotation(SupportedAnnotationTypes.class);
if (sat == null) {
if (isInitialized())
processingEnv.getMessager().printMessage(Diagnostic.Kind.WARNING,
"No SupportedAnnotationTypes annotation " +
"found on " + this.getClass().getName() +
", returning an empty set.");
return Collections.emptySet();
}
else
return arrayToSet(sat.value());
}
/**
* If the processor class is annotated with {@link
* SupportedSourceVersion}, return the source version in the
* annotation. If the class is not so annotated, {@link
* SourceVersion#RELEASE_6} is returned.
*
* @return the latest source version supported by this processor
*/
public SourceVersion getSupportedSourceVersion() {
SupportedSourceVersion ssv = this.getClass().getAnnotation(SupportedSourceVersion.class);
SourceVersion sv = null;
if (ssv == null) {
sv = SourceVersion.RELEASE_6;
if (isInitialized())
processingEnv.getMessager().printMessage(Diagnostic.Kind.WARNING,
"No SupportedSourceVersion annotation " +
"found on " + this.getClass().getName() +
", returning " + sv + ".");
} else
sv = ssv.value();
return sv;
}
/**
* Initializes the processor with the processing environment by
* setting the {@code processingEnv} field to the value of the
* {@code processingEnv} argument. An {@code
* IllegalStateException} will be thrown if this method is called
* more than once on the same object.
*
* @param processingEnv environment to access facilities the tool framework
* provides to the processor
* @throws IllegalStateException if this method is called more than once.
*/
public synchronized void init(ProcessingEnvironment processingEnv) {
if (initialized)
throw new IllegalStateException("Cannot call init more than once.");
Objects.requireNonNull(processingEnv, "Tool provided null ProcessingEnvironment");
this.processingEnv = processingEnv;
initialized = true;
}
/**
* {@inheritDoc}
*/
public abstract boolean process(Set<? extends TypeElement> annotations,
RoundEnvironment roundEnv);
/**
* Returns an empty iterable of completions.
*
* @param element {@inheritDoc}
* @param annotation {@inheritDoc}
* @param member {@inheritDoc}
* @param userText {@inheritDoc}
*/
public Iterable<? extends Completion> getCompletions(Element element,
AnnotationMirror annotation,
ExecutableElement member,
String userText) {
return Collections.emptyList();
}
/**
* Returns {@code true} if this object has been {@linkplain #init
* initialized}, {@code false} otherwise.
*
* @return {@code true} if this object has been initialized,
* {@code false} otherwise.
*/
protected synchronized boolean isInitialized() {
return initialized;
}
private static Set<String> arrayToSet(String[] array) {
assert array != null;
Set<String> set = new HashSet<String>(array.length);
for (String s : array)
set.add(s);
return Collections.unmodifiableSet(set);
}
}

View File

@@ -0,0 +1,51 @@
/*
* Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.annotation.processing;
/**
* A suggested {@linkplain Processor#getCompletions <em>completion</em>} for an
* annotation. A completion is text meant to be inserted into a
* program as part of an annotation.
*
* @author Joseph D. Darcy
* @author Scott Seligman
* @author Peter von der Ah&eacute;
* @since 1.6
*/
public interface Completion {
/**
* Returns the text of the suggested completion.
* @return the text of the suggested completion.
*/
String getValue();
/**
* Returns an informative message about the completion.
* @return an informative message about the completion.
*/
String getMessage();
}

View File

@@ -0,0 +1,87 @@
/*
* Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.annotation.processing;
/**
* Utility class for assembling {@link Completion} objects.
*
* @author Joseph D. Darcy
* @author Scott Seligman
* @author Peter von der Ah&eacute;
* @since 1.6
*/
public class Completions {
// No instances for you.
private Completions() {}
private static class SimpleCompletion implements Completion {
private String value;
private String message;
SimpleCompletion(String value, String message) {
if (value == null || message == null)
throw new NullPointerException("Null completion strings not accepted.");
this.value = value;
this.message = message;
}
public String getValue() {
return value;
}
public String getMessage() {
return message;
}
@Override
public String toString() {
return "[\"" + value + "\", \"" + message + "\"]";
}
// Default equals and hashCode are fine.
}
/**
* Returns a completion of the value and message.
*
* @param value the text of the completion
* @param message a message about the completion
* @return a completion of the provided value and message
*/
public static Completion of(String value, String message) {
return new SimpleCompletion(value, message);
}
/**
* Returns a completion of the value and an empty message
*
* @param value the text of the completion
* @return a completion of the value and an empty message
*/
public static Completion of(String value) {
return new SimpleCompletion(value, "");
}
}

View File

@@ -0,0 +1,263 @@
/*
* Copyright (c) 2005, 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.annotation.processing;
import javax.tools.JavaFileManager;
import javax.tools.*;
import javax.lang.model.element.Element;
import java.io.IOException;
/**
* This interface supports the creation of new files by an annotation
* processor. Files created in this way will be known to the
* annotation processing tool implementing this interface, better
* enabling the tool to manage them. Source and class files so
* created will be {@linkplain RoundEnvironment#getRootElements
* considered for processing} by the tool in a subsequent {@linkplain
* RoundEnvironment round of processing} after the {@code close}
* method has been called on the {@code Writer} or {@code
* OutputStream} used to write the contents of the file.
*
* Three kinds of files are distinguished: source files, class files,
* and auxiliary resource files.
*
* <p> There are two distinguished supported locations (subtrees
* within the logical file system) where newly created files are
* placed: one for {@linkplain
* javax.tools.StandardLocation#SOURCE_OUTPUT new source files}, and
* one for {@linkplain javax.tools.StandardLocation#CLASS_OUTPUT new
* class files}. (These might be specified on a tool's command line,
* for example, using flags such as {@code -s} and {@code -d}.) The
* actual locations for new source files and new class files may or
* may not be distinct on a particular run of the tool. Resource
* files may be created in either location. The methods for reading
* and writing resources take a relative name argument. A relative
* name is a non-null, non-empty sequence of path segments separated
* by {@code '/'}; {@code '.'} and {@code '..'} are invalid path
* segments. A valid relative name must match the
* &quot;path-rootless&quot; rule of <a
* href="http://www.ietf.org/rfc/rfc3986.txt">RFC 3986</a>, section
* 3.3.
*
* <p>The file creation methods take a variable number of arguments to
* allow the <em>originating elements</em> to be provided as hints to
* the tool infrastructure to better manage dependencies. The
* originating elements are the types or packages (representing {@code
* package-info} files) which caused an annotation processor to
* attempt to create a new file. For example, if an annotation
* processor tries to create a source file, {@code
* GeneratedFromUserSource}, in response to processing
*
* <blockquote><pre>
* &#64;Generate
* public class UserSource {}
* </pre></blockquote>
*
* the type element for {@code UserSource} should be passed as part of
* the creation method call as in:
*
* <blockquote><pre>
* filer.createSourceFile("GeneratedFromUserSource",
* eltUtils.getTypeElement("UserSource"));
* </pre></blockquote>
*
* If there are no originating elements, none need to be passed. This
* information may be used in an incremental environment to determine
* the need to rerun processors or remove generated files.
* Non-incremental environments may ignore the originating element
* information.
*
* <p> During each run of an annotation processing tool, a file with a
* given pathname may be created only once. If that file already
* exists before the first attempt to create it, the old contents will
* be deleted. Any subsequent attempt to create the same file during
* a run will throw a {@link FilerException}, as will attempting to
* create both a class file and source file for the same type name or
* same package name. The {@linkplain Processor initial inputs} to
* the tool are considered to be created by the zeroth round;
* therefore, attempting to create a source or class file
* corresponding to one of those inputs will result in a {@link
* FilerException}.
*
* <p> In general, processors must not knowingly attempt to overwrite
* existing files that were not generated by some processor. A {@code
* Filer} may reject attempts to open a file corresponding to an
* existing type, like {@code java.lang.Object}. Likewise, the
* invoker of the annotation processing tool must not knowingly
* configure the tool such that the discovered processors will attempt
* to overwrite existing files that were not generated.
*
* <p> Processors can indicate a source or class file is generated by
* including an {@link javax.annotation.Generated @Generated}
* annotation.
*
* <p> Note that some of the effect of overwriting a file can be
* achieved by using a <i>decorator</i>-style pattern. Instead of
* modifying a class directly, the class is designed so that either
* its superclass is generated by annotation processing or subclasses
* of the class are generated by annotation processing. If the
* subclasses are generated, the parent class may be designed to use
* factories instead of public constructors so that only subclass
* instances would be presented to clients of the parent class.
*
* @author Joseph D. Darcy
* @author Scott Seligman
* @author Peter von der Ah&eacute;
* @since 1.6
*/
public interface Filer {
/**
* Creates a new source file and returns an object to allow
* writing to it. The file's name and path (relative to the
* {@linkplain StandardLocation#SOURCE_OUTPUT root output location
* for source files}) are based on the type to be declared in that
* file. If more than one type is being declared, the name of the
* principal top-level type (the public one, for example) should
* be used. A source file can also be created to hold information
* about a package, including package annotations. To create a
* source file for a named package, have {@code name} be the
* package's name followed by {@code ".package-info"}; to create a
* source file for an unnamed package, use {@code "package-info"}.
*
* <p> Note that to use a particular {@linkplain
* java.nio.charset.Charset charset} to encode the contents of the
* file, an {@code OutputStreamWriter} with the chosen charset can
* be created from the {@code OutputStream} from the returned
* object. If the {@code Writer} from the returned object is
* directly used for writing, its charset is determined by the
* implementation. An annotation processing tool may have an
* {@code -encoding} flag or analogous option for specifying this;
* otherwise, it will typically be the platform's default
* encoding.
*
* <p>To avoid subsequent errors, the contents of the source file
* should be compatible with the {@linkplain
* ProcessingEnvironment#getSourceVersion source version} being used
* for this run.
*
* @param name canonical (fully qualified) name of the principal type
* being declared in this file or a package name followed by
* {@code ".package-info"} for a package information file
* @param originatingElements type or package elements causally
* associated with the creation of this file, may be elided or
* {@code null}
* @return a {@code JavaFileObject} to write the new source file
* @throws FilerException if the same pathname has already been
* created, the same type has already been created, or the name is
* not valid for a type
* @throws IOException if the file cannot be created
*/
JavaFileObject createSourceFile(CharSequence name,
Element... originatingElements) throws IOException;
/**
* Creates a new class file, and returns an object to allow
* writing to it. The file's name and path (relative to the
* {@linkplain StandardLocation#CLASS_OUTPUT root output location
* for class files}) are based on the name of the type being
* written. A class file can also be created to hold information
* about a package, including package annotations. To create a
* class file for a named package, have {@code name} be the
* package's name followed by {@code ".package-info"}; creating a
* class file for an unnamed package is not supported.
*
* <p>To avoid subsequent errors, the contents of the class file
* should be compatible with the {@linkplain
* ProcessingEnvironment#getSourceVersion source version} being used
* for this run.
*
* @param name binary name of the type being written or a package name followed by
* {@code ".package-info"} for a package information file
* @param originatingElements type or package elements causally
* associated with the creation of this file, may be elided or
* {@code null}
* @return a {@code JavaFileObject} to write the new class file
* @throws FilerException if the same pathname has already been
* created, the same type has already been created, or the name is
* not valid for a type
* @throws IOException if the file cannot be created
*/
JavaFileObject createClassFile(CharSequence name,
Element... originatingElements) throws IOException;
/**
* Creates a new auxiliary resource file for writing and returns a
* file object for it. The file may be located along with the
* newly created source files, newly created binary files, or
* other supported location. The locations {@link
* StandardLocation#CLASS_OUTPUT CLASS_OUTPUT} and {@link
* StandardLocation#SOURCE_OUTPUT SOURCE_OUTPUT} must be
* supported. The resource may be named relative to some package
* (as are source and class files), and from there by a relative
* pathname. In a loose sense, the full pathname of the new file
* will be the concatenation of {@code location}, {@code pkg}, and
* {@code relativeName}.
*
* <p>Files created via this method are not registered for
* annotation processing, even if the full pathname of the file
* would correspond to the full pathname of a new source file
* or new class file.
*
* @param location location of the new file
* @param pkg package relative to which the file should be named,
* or the empty string if none
* @param relativeName final pathname components of the file
* @param originatingElements type or package elements causally
* associated with the creation of this file, may be elided or
* {@code null}
* @return a {@code FileObject} to write the new resource
* @throws IOException if the file cannot be created
* @throws FilerException if the same pathname has already been
* created
* @throws IllegalArgumentException for an unsupported location
* @throws IllegalArgumentException if {@code relativeName} is not relative
*/
FileObject createResource(JavaFileManager.Location location,
CharSequence pkg,
CharSequence relativeName,
Element... originatingElements) throws IOException;
/**
* Returns an object for reading an existing resource. The
* locations {@link StandardLocation#CLASS_OUTPUT CLASS_OUTPUT}
* and {@link StandardLocation#SOURCE_OUTPUT SOURCE_OUTPUT} must
* be supported.
*
* @param location location of the file
* @param pkg package relative to which the file should be searched,
* or the empty string if none
* @param relativeName final pathname components of the file
* @return an object to read the file
* @throws FilerException if the same pathname has already been
* opened for writing
* @throws IOException if the file cannot be opened
* @throws IllegalArgumentException for an unsupported location
* @throws IllegalArgumentException if {@code relativeName} is not relative
*/
FileObject getResource(JavaFileManager.Location location,
CharSequence pkg,
CharSequence relativeName) throws IOException;
}

View File

@@ -0,0 +1,52 @@
/*
* Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.annotation.processing;
import java.io.IOException;
/**
* Indicates a {@link Filer} detected an attempt to open a file that
* would violate the guarantees provided by the {@code Filer}. Those
* guarantees include not creating the same file more than once, not
* creating multiple files corresponding to the same type, and not
* creating files for types with invalid names.
*
* @author Joseph D. Darcy
* @author Scott Seligman
* @author Peter von der Ah&eacute;
* @since 1.6
*/
public class FilerException extends IOException {
static final long serialVersionUID = 8426423106453163293L;
/**
* Constructs an exception with the specified detail message.
* @param s the detail message, which should include the name of
* the file attempting to be opened; may be {@code null}
*/
public FilerException(String s) {
super(s);
}
}

View File

@@ -0,0 +1,101 @@
/*
* Copyright (c) 2005, 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.annotation.processing;
import javax.annotation.*;
import javax.tools.Diagnostic;
import javax.lang.model.element.*;
/**
* A {@code Messager} provides the way for an annotation processor to
* report error messages, warnings, and other notices. Elements,
* annotations, and annotation values can be passed to provide a
* location hint for the message. However, such location hints may be
* unavailable or only approximate.
*
* <p>Printing a message with an {@linkplain
* javax.tools.Diagnostic.Kind#ERROR error kind} will {@linkplain
* RoundEnvironment#errorRaised raise an error}.
*
* <p>Note that the messages &quot;printed&quot; by methods in this
* interface may or may not appear as textual output to a location
* like {@link System#out} or {@link System#err}. Implementations may
* choose to present this information in a different fashion, such as
* messages in a window.
*
* @author Joseph D. Darcy
* @author Scott Seligman
* @author Peter von der Ah&eacute;
* @see ProcessingEnvironment#getLocale
* @since 1.6
*/
public interface Messager {
/**
* Prints a message of the specified kind.
*
* @param kind the kind of message
* @param msg the message, or an empty string if none
*/
void printMessage(Diagnostic.Kind kind, CharSequence msg);
/**
* Prints a message of the specified kind at the location of the
* element.
*
* @param kind the kind of message
* @param msg the message, or an empty string if none
* @param e the element to use as a position hint
*/
void printMessage(Diagnostic.Kind kind, CharSequence msg, Element e);
/**
* Prints a message of the specified kind at the location of the
* annotation mirror of the annotated element.
*
* @param kind the kind of message
* @param msg the message, or an empty string if none
* @param e the annotated element
* @param a the annotation to use as a position hint
*/
void printMessage(Diagnostic.Kind kind, CharSequence msg, Element e, AnnotationMirror a);
/**
* Prints a message of the specified kind at the location of the
* annotation value inside the annotation mirror of the annotated
* element.
*
* @param kind the kind of message
* @param msg the message, or an empty string if none
* @param e the annotated element
* @param a the annotation containing the annotation value
* @param v the annotation value to use as a position hint
*/
void printMessage(Diagnostic.Kind kind,
CharSequence msg,
Element e,
AnnotationMirror a,
AnnotationValue v);
}

View File

@@ -0,0 +1,134 @@
/*
* Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.annotation.processing;
import java.util.Map;
import java.util.Locale;
import javax.lang.model.SourceVersion;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;
/**
* An annotation processing tool framework will {@linkplain
* Processor#init provide an annotation processor with an object
* implementing this interface} so the processor can use facilities
* provided by the framework to write new files, report error
* messages, and find other utilities.
*
* <p>Third parties may wish to provide value-add wrappers around the
* facility objects from this interface, for example a {@code Filer}
* extension that allows multiple processors to coordinate writing out
* a single source file. To enable this, for processors running in a
* context where their side effects via the API could be visible to
* each other, the tool infrastructure must provide corresponding
* facility objects that are {@code .equals}, {@code Filer}s that are
* {@code .equals}, and so on. In addition, the tool invocation must
* be able to be configured such that from the perspective of the
* running annotation processors, at least the chosen subset of helper
* classes are viewed as being loaded by the same class loader.
* (Since the facility objects manage shared state, the implementation
* of a wrapper class must know whether or not the same base facility
* object has been wrapped before.)
*
* @author Joseph D. Darcy
* @author Scott Seligman
* @author Peter von der Ah&eacute;
* @since 1.6
*/
public interface ProcessingEnvironment {
/**
* Returns the processor-specific options passed to the annotation
* processing tool. Options are returned in the form of a map from
* option name to option value. For an option with no value, the
* corresponding value in the map is {@code null}.
*
* <p>See documentation of the particular tool infrastructure
* being used for details on how to pass in processor-specific
* options. For example, a command-line implementation may
* distinguish processor-specific options by prefixing them with a
* known string like {@code "-A"}; other tool implementations may
* follow different conventions or provide alternative mechanisms.
* A given implementation may also provide implementation-specific
* ways of finding options passed to the tool in addition to the
* processor-specific options.
*
* @return the processor-specific options passed to the tool
*/
Map<String,String> getOptions();
/**
* Returns the messager used to report errors, warnings, and other
* notices.
*
* @return the messager
*/
Messager getMessager();
/**
* Returns the filer used to create new source, class, or auxiliary
* files.
*
* @return the filer
*/
Filer getFiler();
/**
* Returns an implementation of some utility methods for
* operating on elements
*
* @return element utilities
*/
Elements getElementUtils();
/**
* Returns an implementation of some utility methods for
* operating on types.
*
* @return type utilities
*/
Types getTypeUtils();
/**
* Returns the source version that any generated {@linkplain
* Filer#createSourceFile source} and {@linkplain
* Filer#createClassFile class} files should conform to.
*
* @return the source version to which generated source and class
* files should conform to
* @see Processor#getSupportedSourceVersion
*/
SourceVersion getSourceVersion();
/**
* Returns the current locale or {@code null} if no locale is in
* effect. The locale can be be used to provide localized
* {@linkplain Messager messages}.
*
* @return the current locale or {@code null} if no locale is in
* effect
*/
Locale getLocale();
}

View File

@@ -0,0 +1,441 @@
/*
* Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.annotation.processing;
import java.util.Set;
import javax.lang.model.util.Elements;
import javax.lang.model.AnnotatedConstruct;
import javax.lang.model.element.*;
import javax.lang.model.SourceVersion;
/**
* The interface for an annotation processor.
*
* <p>Annotation processing happens in a sequence of {@linkplain
* javax.annotation.processing.RoundEnvironment rounds}. On each
* round, a processor may be asked to {@linkplain #process process} a
* subset of the annotations found on the source and class files
* produced by a prior round. The inputs to the first round of
* processing are the initial inputs to a run of the tool; these
* initial inputs can be regarded as the output of a virtual zeroth
* round of processing. If a processor was asked to process on a
* given round, it will be asked to process on subsequent rounds,
* including the last round, even if there are no annotations for it
* to process. The tool infrastructure may also ask a processor to
* process files generated implicitly by the tool's operation.
*
* <p> Each implementation of a {@code Processor} must provide a
* public no-argument constructor to be used by tools to instantiate
* the processor. The tool infrastructure will interact with classes
* implementing this interface as follows:
*
* <ol>
*
* <li>If an existing {@code Processor} object is not being used, to
* create an instance of a processor the tool calls the no-arg
* constructor of the processor class.
*
* <li>Next, the tool calls the {@link #init init} method with
* an appropriate {@code ProcessingEnvironment}.
*
* <li>Afterwards, the tool calls {@link #getSupportedAnnotationTypes
* getSupportedAnnotationTypes}, {@link #getSupportedOptions
* getSupportedOptions}, and {@link #getSupportedSourceVersion
* getSupportedSourceVersion}. These methods are only called once per
* run, not on each round.
*
* <li>As appropriate, the tool calls the {@link #process process}
* method on the {@code Processor} object; a new {@code Processor}
* object is <em>not</em> created for each round.
*
* </ol>
*
* If a processor object is created and used without the above
* protocol being followed, then the processor's behavior is not
* defined by this interface specification.
*
* <p> The tool uses a <i>discovery process</i> to find annotation
* processors and decide whether or not they should be run. By
* configuring the tool, the set of potential processors can be
* controlled. For example, for a {@link javax.tools.JavaCompiler
* JavaCompiler} the list of candidate processors to run can be
* {@linkplain javax.tools.JavaCompiler.CompilationTask#setProcessors
* set directly} or controlled by a {@linkplain
* javax.tools.StandardLocation#ANNOTATION_PROCESSOR_PATH search path}
* used for a {@linkplain java.util.ServiceLoader service-style}
* lookup. Other tool implementations may have different
* configuration mechanisms, such as command line options; for
* details, refer to the particular tool's documentation. Which
* processors the tool asks to {@linkplain #process run} is a function
* of the types of the annotations <em>{@linkplain AnnotatedConstruct present}</em>
* on the {@linkplain
* RoundEnvironment#getRootElements root elements}, what {@linkplain
* #getSupportedAnnotationTypes annotation types a processor
* supports}, and whether or not a processor {@linkplain #process
* claims the annotation types it processes}. A processor will be asked to
* process a subset of the annotation types it supports, possibly an
* empty set.
*
* For a given round, the tool computes the set of annotation types
* that are present on the elements enclosed within the root elements.
* If there is at least one annotation type present, then as
* processors claim annotation types, they are removed from the set of
* unmatched annotation types. When the set is empty or no more
* processors are available, the round has run to completion. If
* there are no annotation types present, annotation processing still
* occurs but only <i>universal processors</i> which support
* processing all annotation types, {@code "*"}, can claim the (empty)
* set of annotation types.
*
* <p>An annotation type is considered present if there is at least
* one annotation of that type present on an element enclosed within
* the root elements of a round. For this purpose, a type parameter is
* considered to be enclosed by its {@linkplain
* TypeParameterElement#getGenericElement generic
* element}. Annotations on {@linkplain
* java.lang.annotation.ElementType#TYPE_USE type uses}, as opposed to
* annotations on elements, are ignored when computing whether or not
* an annotation type is present.
*
* <p>An annotation is present if it meets the definition of being
* present given in {@link AnnotatedConstruct}. In brief, an
* annotation is considered present for the purposes of discovery if
* it is directly present or present via inheritance. An annotation is
* <em>not</em> considered present by virtue of being wrapped by a
* container annotation. Operationally, this is equivalent to an
* annotation being present on an element if and only if it would be
* included in the results of {@link
* Elements#getAllAnnotationMirrors(Element)} called on that element. Since
* annotations inside container annotations are not considered
* present, to properly process {@linkplain
* java.lang.annotation.Repeatable repeatable annotation types},
* processors are advised to include both the repeatable annotation
* type and its containing annotation type in the set of {@linkplain
* #getSupportedAnnotationTypes() supported annotation types} of a
* processor.
*
* <p>Note that if a processor supports {@code "*"} and returns {@code
* true}, all annotations are claimed. Therefore, a universal
* processor being used to, for example, implement additional validity
* checks should return {@code false} so as to not prevent other such
* checkers from being able to run.
*
* <p>If a processor throws an uncaught exception, the tool may cease
* other active annotation processors. If a processor raises an
* error, the current round will run to completion and the subsequent
* round will indicate an {@linkplain RoundEnvironment#errorRaised
* error was raised}. Since annotation processors are run in a
* cooperative environment, a processor should throw an uncaught
* exception only in situations where no error recovery or reporting
* is feasible.
*
* <p>The tool environment is not required to support annotation
* processors that access environmental resources, either {@linkplain
* RoundEnvironment per round} or {@linkplain ProcessingEnvironment
* cross-round}, in a multi-threaded fashion.
*
* <p>If the methods that return configuration information about the
* annotation processor return {@code null}, return other invalid
* input, or throw an exception, the tool infrastructure must treat
* this as an error condition.
*
* <p>To be robust when running in different tool implementations, an
* annotation processor should have the following properties:
*
* <ol>
*
* <li>The result of processing a given input is not a function of the presence or absence
* of other inputs (orthogonality).
*
* <li>Processing the same input produces the same output (consistency).
*
* <li>Processing input <i>A</i> followed by processing input <i>B</i>
* is equivalent to processing <i>B</i> then <i>A</i>
* (commutativity)
*
* <li>Processing an input does not rely on the presence of the output
* of other annotation processors (independence)
*
* </ol>
*
* <p>The {@link Filer} interface discusses restrictions on how
* processors can operate on files.
*
* <p>Note that implementors of this interface may find it convenient
* to extend {@link AbstractProcessor} rather than implementing this
* interface directly.
*
* @author Joseph D. Darcy
* @author Scott Seligman
* @author Peter von der Ah&eacute;
* @since 1.6
*/
public interface Processor {
/**
* Returns the options recognized by this processor. An
* implementation of the processing tool must provide a way to
* pass processor-specific options distinctly from options passed
* to the tool itself, see {@link ProcessingEnvironment#getOptions
* getOptions}.
*
* <p>Each string returned in the set must be a period separated
* sequence of {@linkplain
* javax.lang.model.SourceVersion#isIdentifier identifiers}:
*
* <blockquote>
* <dl>
* <dt><i>SupportedOptionString:</i>
* <dd><i>Identifiers</i>
*
* <dt><i>Identifiers:</i>
* <dd> <i>Identifier</i>
* <dd> <i>Identifier</i> {@code .} <i>Identifiers</i>
*
* <dt><i>Identifier:</i>
* <dd>Syntactic identifier, including keywords and literals
* </dl>
* </blockquote>
*
* <p> A tool might use this information to determine if any
* options provided by a user are unrecognized by any processor,
* in which case it may wish to report a warning.
*
* @return the options recognized by this processor or an
* empty collection if none
* @see javax.annotation.processing.SupportedOptions
*/
Set<String> getSupportedOptions();
/**
* Returns the names of the annotation types supported by this
* processor. An element of the result may be the canonical
* (fully qualified) name of a supported annotation type.
* Alternately it may be of the form &quot;<tt><i>name</i>.*</tt>&quot;
* representing the set of all annotation types with canonical
* names beginning with &quot;<tt><i>name.</i></tt>&quot;. Finally, {@code
* "*"} by itself represents the set of all annotation types,
* including the empty set. Note that a processor should not
* claim {@code "*"} unless it is actually processing all files;
* claiming unnecessary annotations may cause a performance
* slowdown in some environments.
*
* <p>Each string returned in the set must be accepted by the
* following grammar:
*
* <blockquote>
* <dl>
* <dt><i>SupportedAnnotationTypeString:</i>
* <dd><i>TypeName</i> <i>DotStar</i><sub><i>opt</i></sub>
* <dd><tt>*</tt>
*
* <dt><i>DotStar:</i>
* <dd><tt>.</tt> <tt>*</tt>
* </dl>
* </blockquote>
*
* where <i>TypeName</i> is as defined in
* <cite>The Java&trade; Language Specification</cite>.
*
* @return the names of the annotation types supported by this processor
* @see javax.annotation.processing.SupportedAnnotationTypes
* @jls 3.8 Identifiers
* @jls 6.5.5 Meaning of Type Names
*/
Set<String> getSupportedAnnotationTypes();
/**
* Returns the latest source version supported by this annotation
* processor.
*
* @return the latest source version supported by this annotation
* processor.
* @see javax.annotation.processing.SupportedSourceVersion
* @see ProcessingEnvironment#getSourceVersion
*/
SourceVersion getSupportedSourceVersion();
/**
* Initializes the processor with the processing environment.
*
* @param processingEnv environment for facilities the tool framework
* provides to the processor
*/
void init(ProcessingEnvironment processingEnv);
/**
* Processes a set of annotation types on type elements
* originating from the prior round and returns whether or not
* these annotation types are claimed by this processor. If {@code
* true} is returned, the annotation types are claimed and subsequent
* processors will not be asked to process them; if {@code false}
* is returned, the annotation types are unclaimed and subsequent
* processors may be asked to process them. A processor may
* always return the same boolean value or may vary the result
* based on chosen criteria.
*
* <p>The input set will be empty if the processor supports {@code
* "*"} and the root elements have no annotations. A {@code
* Processor} must gracefully handle an empty set of annotations.
*
* @param annotations the annotation types requested to be processed
* @param roundEnv environment for information about the current and prior round
* @return whether or not the set of annotation types are claimed by this processor
*/
boolean process(Set<? extends TypeElement> annotations,
RoundEnvironment roundEnv);
/**
* Returns to the tool infrastructure an iterable of suggested
* completions to an annotation. Since completions are being asked
* for, the information provided about the annotation may be
* incomplete, as if for a source code fragment. A processor may
* return an empty iterable. Annotation processors should focus
* their efforts on providing completions for annotation members
* with additional validity constraints known to the processor, for
* example an {@code int} member whose value should lie between 1
* and 10 or a string member that should be recognized by a known
* grammar, such as a regular expression or a URL.
*
* <p>Since incomplete programs are being modeled, some of the
* parameters may only have partial information or may be {@code
* null}. At least one of {@code element} and {@code userText}
* must be non-{@code null}. If {@code element} is non-{@code
* null}, {@code annotation} and {@code member} may be {@code
* null}. Processors may not throw a {@code NullPointerException}
* if some parameters are {@code null}; if a processor has no
* completions to offer based on the provided information, an
* empty iterable can be returned. The processor may also return
* a single completion with an empty value string and a message
* describing why there are no completions.
*
* <p>Completions are informative and may reflect additional
* validity checks performed by annotation processors. For
* example, consider the simple annotation:
*
* <blockquote>
* <pre>
* &#064;MersennePrime {
* int value();
* }
* </pre>
* </blockquote>
*
* (A Mersenne prime is prime number of the form
* 2<sup><i>n</i></sup> - 1.) Given an {@code AnnotationMirror}
* for this annotation type, a list of all such primes in the
* {@code int} range could be returned without examining any other
* arguments to {@code getCompletions}:
*
* <blockquote>
* <pre>
* import static javax.annotation.processing.Completions.*;
* ...
* return Arrays.asList({@link Completions#of(String) of}(&quot;3&quot;),
* of(&quot;7&quot;),
* of(&quot;31&quot;),
* of(&quot;127&quot;),
* of(&quot;8191&quot;),
* of(&quot;131071&quot;),
* of(&quot;524287&quot;),
* of(&quot;2147483647&quot;));
* </pre>
* </blockquote>
*
* A more informative set of completions would include the number
* of each prime:
*
* <blockquote>
* <pre>
* return Arrays.asList({@link Completions#of(String, String) of}(&quot;3&quot;, &quot;M2&quot;),
* of(&quot;7&quot;, &quot;M3&quot;),
* of(&quot;31&quot;, &quot;M5&quot;),
* of(&quot;127&quot;, &quot;M7&quot;),
* of(&quot;8191&quot;, &quot;M13&quot;),
* of(&quot;131071&quot;, &quot;M17&quot;),
* of(&quot;524287&quot;, &quot;M19&quot;),
* of(&quot;2147483647&quot;, &quot;M31&quot;));
* </pre>
* </blockquote>
*
* However, if the {@code userText} is available, it can be checked
* to see if only a subset of the Mersenne primes are valid. For
* example, if the user has typed
*
* <blockquote>
* <code>
* &#064;MersennePrime(1
* </code>
* </blockquote>
*
* the value of {@code userText} will be {@code "1"}; and only
* two of the primes are possible completions:
*
* <blockquote>
* <pre>
* return Arrays.asList(of(&quot;127&quot;, &quot;M7&quot;),
* of(&quot;131071&quot;, &quot;M17&quot;));
* </pre>
* </blockquote>
*
* Sometimes no valid completion is possible. For example, there
* is no in-range Mersenne prime starting with 9:
*
* <blockquote>
* <code>
* &#064;MersennePrime(9
* </code>
* </blockquote>
*
* An appropriate response in this case is to either return an
* empty list of completions,
*
* <blockquote>
* <pre>
* return Collections.emptyList();
* </pre>
* </blockquote>
*
* or a single empty completion with a helpful message
*
* <blockquote>
* <pre>
* return Arrays.asList(of(&quot;&quot;, &quot;No in-range Mersenne primes start with 9&quot;));
* </pre>
* </blockquote>
*
* @param element the element being annotated
* @param annotation the (perhaps partial) annotation being
* applied to the element
* @param member the annotation member to return possible completions for
* @param userText source code text to be completed
*
* @return suggested completions to the annotation
*/
Iterable<? extends Completion> getCompletions(Element element,
AnnotationMirror annotation,
ExecutableElement member,
String userText);
}

View File

@@ -0,0 +1,113 @@
/*
* Copyright (c) 2005, 2007, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.annotation.processing;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import java.util.Set;
import java.lang.annotation.Annotation;
/**
* An annotation processing tool framework will {@linkplain
* Processor#process provide an annotation processor with an object
* implementing this interface} so that the processor can query for
* information about a round of annotation processing.
*
* @author Joseph D. Darcy
* @author Scott Seligman
* @author Peter von der Ah&eacute;
* @since 1.6
*/
public interface RoundEnvironment {
/**
* Returns {@code true} if types generated by this round will not
* be subject to a subsequent round of annotation processing;
* returns {@code false} otherwise.
*
* @return {@code true} if types generated by this round will not
* be subject to a subsequent round of annotation processing;
* returns {@code false} otherwise
*/
boolean processingOver();
/**
* Returns {@code true} if an error was raised in the prior round
* of processing; returns {@code false} otherwise.
*
* @return {@code true} if an error was raised in the prior round
* of processing; returns {@code false} otherwise
*/
boolean errorRaised();
/**
* Returns the root elements for annotation processing generated
* by the prior round.
*
* @return the root elements for annotation processing generated
* by the prior round, or an empty set if there were none
*/
Set<? extends Element> getRootElements();
/**
* Returns the elements annotated with the given annotation type.
* The annotation may appear directly or be inherited. Only
* package elements and type elements <i>included</i> in this
* round of annotation processing, or declarations of members,
* constructors, parameters, or type parameters declared within
* those, are returned. Included type elements are {@linkplain
* #getRootElements root types} and any member types nested within
* them. Elements in a package are not considered included simply
* because a {@code package-info} file for that package was
* created.
*
* @param a annotation type being requested
* @return the elements annotated with the given annotation type,
* or an empty set if there are none
* @throws IllegalArgumentException if the argument does not
* represent an annotation type
*/
Set<? extends Element> getElementsAnnotatedWith(TypeElement a);
/**
* Returns the elements annotated with the given annotation type.
* The annotation may appear directly or be inherited. Only
* package elements and type elements <i>included</i> in this
* round of annotation processing, or declarations of members,
* constructors, parameters, or type parameters declared within
* those, are returned. Included type elements are {@linkplain
* #getRootElements root types} and any member types nested within
* them. Elements in a package are not considered included simply
* because a {@code package-info} file for that package was
* created.
*
* @param a annotation type being requested
* @return the elements annotated with the given annotation type,
* or an empty set if there are none
* @throws IllegalArgumentException if the argument does not
* represent an annotation type
*/
Set<? extends Element> getElementsAnnotatedWith(Class<? extends Annotation> a);
}

View File

@@ -0,0 +1,55 @@
/*
* Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.annotation.processing;
import java.lang.annotation.*;
import static java.lang.annotation.RetentionPolicy.*;
import static java.lang.annotation.ElementType.*;
/**
* An annotation used to indicate what annotation types an annotation
* processor supports. The {@link
* Processor#getSupportedAnnotationTypes} method can construct its
* result from the value of this annotation, as done by {@link
* AbstractProcessor#getSupportedAnnotationTypes}. Only {@linkplain
* Processor#getSupportedAnnotationTypes strings conforming to the
* grammar} should be used as values.
*
* @author Joseph D. Darcy
* @author Scott Seligman
* @author Peter von der Ah&eacute;
* @since 1.6
*/
@Documented
@Target(TYPE)
@Retention(RUNTIME)
public @interface SupportedAnnotationTypes {
/**
* Returns the names of the supported annotation types.
* @return the names of the supported annotation types
*/
String [] value();
}

View File

@@ -0,0 +1,54 @@
/*
* Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.annotation.processing;
import java.lang.annotation.*;
import static java.lang.annotation.RetentionPolicy.*;
import static java.lang.annotation.ElementType.*;
/**
* An annotation used to indicate what options an annotation processor
* supports. The {@link Processor#getSupportedOptions} method can
* construct its result from the value of this annotation, as done by
* {@link AbstractProcessor#getSupportedOptions}. Only {@linkplain
* Processor#getSupportedOptions strings conforming to the
* grammar} should be used as values.
*
* @author Joseph D. Darcy
* @author Scott Seligman
* @author Peter von der Ah&eacute;
* @since 1.6
*/
@Documented
@Target(TYPE)
@Retention(RUNTIME)
public @interface SupportedOptions {
/**
* Returns the supported options.
* @return the supported options
*/
String [] value();
}

View File

@@ -0,0 +1,55 @@
/*
* Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.annotation.processing;
import java.lang.annotation.*;
import static java.lang.annotation.RetentionPolicy.*;
import static java.lang.annotation.ElementType.*;
import javax.lang.model.SourceVersion;
/**
* An annotation used to indicate the latest source version an
* annotation processor supports. The {@link
* Processor#getSupportedSourceVersion} method can construct its
* result from the value of this annotation, as done by {@link
* AbstractProcessor#getSupportedSourceVersion}.
*
* @author Joseph D. Darcy
* @author Scott Seligman
* @author Peter von der Ah&eacute;
* @since 1.6
*/
@Documented
@Target(TYPE)
@Retention(RUNTIME)
public @interface SupportedSourceVersion {
/**
* Returns the latest supported source version.
* @return the latest supported source version
*/
SourceVersion value();
}

View File

@@ -0,0 +1,43 @@
/*
* Copyright (c) 2005, 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.
*/
/**
* Facilities for declaring annotation processors and for
* allowing annotation processors to communicate with an annotation processing
* tool environment.
*
* <p> Unless otherwise specified in a particular implementation, the
* collections returned by methods in this package should be expected
* to be unmodifiable by the caller and unsafe for concurrent access.
*
* <p> Unless otherwise specified, methods in this package will throw
* a {@code NullPointerException} if given a {@code null} argument.
*
* @author Joseph D. Darcy
* @author Scott Seligman
* @author Peter von der Ah&eacute;
* @since 1.6
*/
package javax.annotation.processing;

View File

@@ -0,0 +1,55 @@
/*
* Copyright (c) 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 javax.crypto;
/**
* This exception is thrown when a {@link Cipher} operating in
* an AEAD mode (such as GCM/CCM) is unable to verify the supplied
* authentication tag.
*
* @since 1.7
*/
public class AEADBadTagException extends BadPaddingException {
private static final long serialVersionUID = -488059093241685509L;
/**
* Constructs a AEADBadTagException with no detail message.
*/
public AEADBadTagException() {
super();
}
/**
* Constructs a AEADBadTagException with the specified
* detail message.
*
* @param msg the detail message.
*/
public AEADBadTagException(String msg) {
super(msg);
}
}

View File

@@ -0,0 +1,60 @@
/*
* Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.crypto;
import java.security.GeneralSecurityException;
/**
* This exception is thrown when a particular padding mechanism is
* expected for the input data but the data is not padded properly.
*
* @author Gigi Ankney
* @since 1.4
*/
public class BadPaddingException extends GeneralSecurityException {
private static final long serialVersionUID = -5315033893984728443L;
/**
* Constructs a BadPaddingException with no detail
* message. A detail message is a String that describes this
* particular exception.
*/
public BadPaddingException() {
super();
}
/**
* Constructs a BadPaddingException with the specified
* detail message.
*
* @param msg the detail message.
*/
public BadPaddingException(String msg) {
super(msg);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,353 @@
/*
* Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact 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.crypto;
import java.io.InputStream;
import java.io.FilterInputStream;
import java.io.IOException;
import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
/**
* A CipherInputStream is composed of an InputStream and a Cipher so
* that read() methods return data that are read in from the
* underlying InputStream but have been additionally processed by the
* Cipher. The Cipher must be fully initialized before being used by
* a CipherInputStream.
*
* <p> For example, if the Cipher is initialized for decryption, the
* CipherInputStream will attempt to read in data and decrypt them,
* before returning the decrypted data.
*
* <p> This class adheres strictly to the semantics, especially the
* failure semantics, of its ancestor classes
* java.io.FilterInputStream and java.io.InputStream. This class has
* exactly those methods specified in its ancestor classes, and
* overrides them all. Moreover, this class catches all exceptions
* that are not thrown by its ancestor classes. In particular, the
* <code>skip</code> method skips, and the <code>available</code>
* method counts only data that have been processed by the encapsulated Cipher.
* This class may catch BadPaddingException and other exceptions thrown by
* failed integrity checks during decryption. These exceptions are not
* re-thrown, so the client may not be informed that integrity checks
* failed. Because of this behavior, this class may not be suitable
* for use with decryption in an authenticated mode of operation (e.g. GCM).
* Applications that require authenticated encryption can use the Cipher API
* directly as an alternative to using this class.
*
* <p> It is crucial for a programmer using this class not to use
* methods that are not defined or overriden in this class (such as a
* new method or constructor that is later added to one of the super
* classes), because the design and implementation of those methods
* are unlikely to have considered security impact with regard to
* CipherInputStream.
*
* @author Li Gong
* @see java.io.InputStream
* @see java.io.FilterInputStream
* @see javax.crypto.Cipher
* @see javax.crypto.CipherOutputStream
*
* @since 1.4
*/
public class CipherInputStream extends FilterInputStream {
// the cipher engine to use to process stream data
private Cipher cipher;
// the underlying input stream
private InputStream input;
/* the buffer holding data that have been read in from the
underlying stream, but have not been processed by the cipher
engine. the size 512 bytes is somewhat randomly chosen */
private byte[] ibuffer = new byte[512];
// having reached the end of the underlying input stream
private boolean done = false;
/* the buffer holding data that have been processed by the cipher
engine, but have not been read out */
private byte[] obuffer;
// the offset pointing to the next "new" byte
private int ostart = 0;
// the offset pointing to the last "new" byte
private int ofinish = 0;
// stream status
private boolean closed = false;
/**
* private convenience function.
*
* Entry condition: ostart = ofinish
*
* Exit condition: ostart <= ofinish
*
* return (ofinish-ostart) (we have this many bytes for you)
* return 0 (no data now, but could have more later)
* return -1 (absolutely no more data)
*
* Note: Exceptions are only thrown after the stream is completely read.
* For AEAD ciphers a read() of any length will internally cause the
* whole stream to be read fully and verify the authentication tag before
* returning decrypted data or exceptions.
*/
private int getMoreData() throws IOException {
if (done) return -1;
int readin = input.read(ibuffer);
if (readin == -1) {
done = true;
try {
obuffer = cipher.doFinal();
} catch (IllegalBlockSizeException | BadPaddingException e) {
obuffer = null;
throw new IOException(e);
}
if (obuffer == null)
return -1;
else {
ostart = 0;
ofinish = obuffer.length;
return ofinish;
}
}
try {
obuffer = cipher.update(ibuffer, 0, readin);
} catch (IllegalStateException e) {
obuffer = null;
throw e;
}
ostart = 0;
if (obuffer == null)
ofinish = 0;
else ofinish = obuffer.length;
return ofinish;
}
/**
* Constructs a CipherInputStream from an InputStream and a
* Cipher.
* <br>Note: if the specified input stream or cipher is
* null, a NullPointerException may be thrown later when
* they are used.
* @param is the to-be-processed input stream
* @param c an initialized Cipher object
*/
public CipherInputStream(InputStream is, Cipher c) {
super(is);
input = is;
cipher = c;
}
/**
* Constructs a CipherInputStream from an InputStream without
* specifying a Cipher. This has the effect of constructing a
* CipherInputStream using a NullCipher.
* <br>Note: if the specified input stream is null, a
* NullPointerException may be thrown later when it is used.
* @param is the to-be-processed input stream
*/
protected CipherInputStream(InputStream is) {
super(is);
input = is;
cipher = new NullCipher();
}
/**
* Reads the next byte of data from this input stream. The value
* byte is returned as an <code>int</code> in the range
* <code>0</code> to <code>255</code>. If no byte is available
* because the end of the stream has been reached, the value
* <code>-1</code> is returned. This method blocks until input data
* is available, the end of the stream is detected, or an exception
* is thrown.
* <p>
*
* @return the next byte of data, or <code>-1</code> if the end of the
* stream is reached.
* @exception IOException if an I/O error occurs.
* @since JCE1.2
*/
public int read() throws IOException {
if (ostart >= ofinish) {
// we loop for new data as the spec says we are blocking
int i = 0;
while (i == 0) i = getMoreData();
if (i == -1) return -1;
}
return ((int) obuffer[ostart++] & 0xff);
};
/**
* Reads up to <code>b.length</code> bytes of data from this input
* stream into an array of bytes.
* <p>
* The <code>read</code> method of <code>InputStream</code> calls
* the <code>read</code> method of three arguments with the arguments
* <code>b</code>, <code>0</code>, and <code>b.length</code>.
*
* @param b the buffer into which the data is read.
* @return the total number of bytes read into the buffer, or
* <code>-1</code> is there is no more data because the end of
* the stream has been reached.
* @exception IOException if an I/O error occurs.
* @see java.io.InputStream#read(byte[], int, int)
* @since JCE1.2
*/
public int read(byte b[]) throws IOException {
return read(b, 0, b.length);
}
/**
* Reads up to <code>len</code> bytes of data from this input stream
* into an array of bytes. This method blocks until some input is
* available. If the first argument is <code>null,</code> up to
* <code>len</code> bytes are read and discarded.
*
* @param b the buffer into which the data is read.
* @param off the start offset in the destination array
* <code>buf</code>
* @param len the maximum number of bytes read.
* @return the total number of bytes read into the buffer, or
* <code>-1</code> if there is no more data because the end of
* the stream has been reached.
* @exception IOException if an I/O error occurs.
* @see java.io.InputStream#read()
* @since JCE1.2
*/
public int read(byte b[], int off, int len) throws IOException {
if (ostart >= ofinish) {
// we loop for new data as the spec says we are blocking
int i = 0;
while (i == 0) i = getMoreData();
if (i == -1) return -1;
}
if (len <= 0) {
return 0;
}
int available = ofinish - ostart;
if (len < available) available = len;
if (b != null) {
System.arraycopy(obuffer, ostart, b, off, available);
}
ostart = ostart + available;
return available;
}
/**
* Skips <code>n</code> bytes of input from the bytes that can be read
* from this input stream without blocking.
*
* <p>Fewer bytes than requested might be skipped.
* The actual number of bytes skipped is equal to <code>n</code> or
* the result of a call to
* {@link #available() available},
* whichever is smaller.
* If <code>n</code> is less than zero, no bytes are skipped.
*
* <p>The actual number of bytes skipped is returned.
*
* @param n the number of bytes to be skipped.
* @return the actual number of bytes skipped.
* @exception IOException if an I/O error occurs.
* @since JCE1.2
*/
public long skip(long n) throws IOException {
int available = ofinish - ostart;
if (n > available) {
n = available;
}
if (n < 0) {
return 0;
}
ostart += n;
return n;
}
/**
* Returns the number of bytes that can be read from this input
* stream without blocking. The <code>available</code> method of
* <code>InputStream</code> returns <code>0</code>. This method
* <B>should</B> be overridden by subclasses.
*
* @return the number of bytes that can be read from this input stream
* without blocking.
* @exception IOException if an I/O error occurs.
* @since JCE1.2
*/
public int available() throws IOException {
return (ofinish - ostart);
}
/**
* Closes this input stream and releases any system resources
* associated with the stream.
* <p>
* The <code>close</code> method of <code>CipherInputStream</code>
* calls the <code>close</code> method of its underlying input
* stream.
*
* @exception IOException if an I/O error occurs.
* @since JCE1.2
*/
public void close() throws IOException {
if (closed) {
return;
}
closed = true;
input.close();
// Throw away the unprocessed data and throw no crypto exceptions.
// AEAD ciphers are fully readed before closing. Any authentication
// exceptions would occur while reading.
if (!done) {
try {
cipher.doFinal();
}
catch (BadPaddingException | IllegalBlockSizeException ex) {
// Catch exceptions as the rest of the stream is unused.
}
}
ostart = 0;
ofinish = 0;
}
/**
* Tests if this input stream supports the <code>mark</code>
* and <code>reset</code> methods, which it does not.
*
* @return <code>false</code>, since this class does not support the
* <code>mark</code> and <code>reset</code> methods.
* @see java.io.InputStream#mark(int)
* @see java.io.InputStream#reset()
* @since JCE1.2
*/
public boolean markSupported() {
return false;
}
}

View File

@@ -0,0 +1,227 @@
/*
* Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact 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.crypto;
import java.io.*;
/**
* A CipherOutputStream is composed of an OutputStream and a Cipher so
* that write() methods first process the data before writing them out
* to the underlying OutputStream. The cipher must be fully
* initialized before being used by a CipherOutputStream.
*
* <p> For example, if the cipher is initialized for encryption, the
* CipherOutputStream will attempt to encrypt data before writing out the
* encrypted data.
*
* <p> This class adheres strictly to the semantics, especially the
* failure semantics, of its ancestor classes
* java.io.OutputStream and java.io.FilterOutputStream. This class
* has exactly those methods specified in its ancestor classes, and
* overrides them all. Moreover, this class catches all exceptions
* that are not thrown by its ancestor classes. In particular, this
* class catches BadPaddingException and other exceptions thrown by
* failed integrity checks during decryption. These exceptions are not
* re-thrown, so the client will not be informed that integrity checks
* failed. Because of this behavior, this class may not be suitable
* for use with decryption in an authenticated mode of operation (e.g. GCM)
* if the application requires explicit notification when authentication
* fails. Such an application can use the Cipher API directly as an
* alternative to using this class.
*
* <p> It is crucial for a programmer using this class not to use
* methods that are not defined or overriden in this class (such as a
* new method or constructor that is later added to one of the super
* classes), because the design and implementation of those methods
* are unlikely to have considered security impact with regard to
* CipherOutputStream.
*
* @author Li Gong
* @see java.io.OutputStream
* @see java.io.FilterOutputStream
* @see javax.crypto.Cipher
* @see javax.crypto.CipherInputStream
*
* @since 1.4
*/
public class CipherOutputStream extends FilterOutputStream {
// the cipher engine to use to process stream data
private Cipher cipher;
// the underlying output stream
private OutputStream output;
/* the buffer holding one byte of incoming data */
private byte[] ibuffer = new byte[1];
// the buffer holding data ready to be written out
private byte[] obuffer;
// stream status
private boolean closed = false;
/**
*
* Constructs a CipherOutputStream from an OutputStream and a
* Cipher.
* <br>Note: if the specified output stream or cipher is
* null, a NullPointerException may be thrown later when
* they are used.
*
* @param os the OutputStream object
* @param c an initialized Cipher object
*/
public CipherOutputStream(OutputStream os, Cipher c) {
super(os);
output = os;
cipher = c;
};
/**
* Constructs a CipherOutputStream from an OutputStream without
* specifying a Cipher. This has the effect of constructing a
* CipherOutputStream using a NullCipher.
* <br>Note: if the specified output stream is null, a
* NullPointerException may be thrown later when it is used.
*
* @param os the OutputStream object
*/
protected CipherOutputStream(OutputStream os) {
super(os);
output = os;
cipher = new NullCipher();
}
/**
* Writes the specified byte to this output stream.
*
* @param b the <code>byte</code>.
* @exception IOException if an I/O error occurs.
* @since JCE1.2
*/
public void write(int b) throws IOException {
ibuffer[0] = (byte) b;
obuffer = cipher.update(ibuffer, 0, 1);
if (obuffer != null) {
output.write(obuffer);
obuffer = null;
}
};
/**
* Writes <code>b.length</code> bytes from the specified byte array
* to this output stream.
* <p>
* The <code>write</code> method of
* <code>CipherOutputStream</code> calls the <code>write</code>
* method of three arguments with the three arguments
* <code>b</code>, <code>0</code>, and <code>b.length</code>.
*
* @param b the data.
* @exception NullPointerException if <code>b</code> is null.
* @exception IOException if an I/O error occurs.
* @see javax.crypto.CipherOutputStream#write(byte[], int, int)
* @since JCE1.2
*/
public void write(byte b[]) throws IOException {
write(b, 0, b.length);
}
/**
* Writes <code>len</code> bytes from the specified byte array
* starting at offset <code>off</code> to this output stream.
*
* @param b the data.
* @param off the start offset in the data.
* @param len the number of bytes to write.
* @exception IOException if an I/O error occurs.
* @since JCE1.2
*/
public void write(byte b[], int off, int len) throws IOException {
obuffer = cipher.update(b, off, len);
if (obuffer != null) {
output.write(obuffer);
obuffer = null;
}
}
/**
* Flushes this output stream by forcing any buffered output bytes
* that have already been processed by the encapsulated cipher object
* to be written out.
*
* <p>Any bytes buffered by the encapsulated cipher
* and waiting to be processed by it will not be written out. For example,
* if the encapsulated cipher is a block cipher, and the total number of
* bytes written using one of the <code>write</code> methods is less than
* the cipher's block size, no bytes will be written out.
*
* @exception IOException if an I/O error occurs.
* @since JCE1.2
*/
public void flush() throws IOException {
if (obuffer != null) {
output.write(obuffer);
obuffer = null;
}
output.flush();
}
/**
* Closes this output stream and releases any system resources
* associated with this stream.
* <p>
* This method invokes the <code>doFinal</code> method of the encapsulated
* cipher object, which causes any bytes buffered by the encapsulated
* cipher to be processed. The result is written out by calling the
* <code>flush</code> method of this output stream.
* <p>
* This method resets the encapsulated cipher object to its initial state
* and calls the <code>close</code> method of the underlying output
* stream.
*
* @exception IOException if an I/O error occurs.
* @since JCE1.2
*/
public void close() throws IOException {
if (closed) {
return;
}
closed = true;
try {
obuffer = cipher.doFinal();
} catch (IllegalBlockSizeException | BadPaddingException e) {
obuffer = null;
}
try {
flush();
} catch (IOException ignored) {}
out.close();
}
}

View File

@@ -0,0 +1,991 @@
/*
* Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact 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.crypto;
import java.util.StringTokenizer;
import java.util.NoSuchElementException;
import java.security.AlgorithmParameters;
import java.security.Provider;
import java.security.Key;
import java.security.SecureRandom;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.InvalidKeyException;
import java.security.InvalidAlgorithmParameterException;
import java.security.ProviderException;
import java.security.spec.AlgorithmParameterSpec;
import java.nio.ByteBuffer;
/**
* This class defines the <i>Service Provider Interface</i> (<b>SPI</b>)
* for the <code>Cipher</code> class.
* All the abstract methods in this class must be implemented by each
* cryptographic service provider who wishes to supply the implementation
* of a particular cipher algorithm.
*
* <p>In order to create an instance of <code>Cipher</code>, which
* encapsulates an instance of this <code>CipherSpi</code> class, an
* application calls one of the
* {@link Cipher#getInstance(java.lang.String) getInstance}
* factory methods of the
* {@link Cipher Cipher} engine class and specifies the requested
* <i>transformation</i>.
* Optionally, the application may also specify the name of a provider.
*
* <p>A <i>transformation</i> is a string that describes the operation (or
* set of operations) to be performed on the given input, to produce some
* output. A transformation always includes the name of a cryptographic
* algorithm (e.g., <i>AES</i>), and may be followed by a feedback mode and
* padding scheme.
*
* <p> A transformation is of the form:
*
* <ul>
* <li>"<i>algorithm/mode/padding</i>" or
*
* <li>"<i>algorithm</i>"
* </ul>
*
* <P> (in the latter case,
* provider-specific default values for the mode and padding scheme are used).
* For example, the following is a valid transformation:
*
* <pre>
* Cipher c = Cipher.getInstance("<i>AES/CBC/PKCS5Padding</i>");
* </pre>
*
* <p>A provider may supply a separate class for each combination
* of <i>algorithm/mode/padding</i>, or may decide to provide more generic
* classes representing sub-transformations corresponding to
* <i>algorithm</i> or <i>algorithm/mode</i> or <i>algorithm//padding</i>
* (note the double slashes),
* in which case the requested mode and/or padding are set automatically by
* the <code>getInstance</code> methods of <code>Cipher</code>, which invoke
* the {@link #engineSetMode(java.lang.String) engineSetMode} and
* {@link #engineSetPadding(java.lang.String) engineSetPadding}
* methods of the provider's subclass of <code>CipherSpi</code>.
*
* <p>A <code>Cipher</code> property in a provider master class may have one of
* the following formats:
*
* <ul>
*
* <li>
* <pre>
* // provider's subclass of "CipherSpi" implements "algName" with
* // pluggable mode and padding
* <code>Cipher.</code><i>algName</i>
* </pre>
*
* <li>
* <pre>
* // provider's subclass of "CipherSpi" implements "algName" in the
* // specified "mode", with pluggable padding
* <code>Cipher.</code><i>algName/mode</i>
* </pre>
*
* <li>
* <pre>
* // provider's subclass of "CipherSpi" implements "algName" with the
* // specified "padding", with pluggable mode
* <code>Cipher.</code><i>algName//padding</i>
* </pre>
*
* <li>
* <pre>
* // provider's subclass of "CipherSpi" implements "algName" with the
* // specified "mode" and "padding"
* <code>Cipher.</code><i>algName/mode/padding</i>
* </pre>
*
* </ul>
*
* <p>For example, a provider may supply a subclass of <code>CipherSpi</code>
* that implements <i>AES/ECB/PKCS5Padding</i>, one that implements
* <i>AES/CBC/PKCS5Padding</i>, one that implements
* <i>AES/CFB/PKCS5Padding</i>, and yet another one that implements
* <i>AES/OFB/PKCS5Padding</i>. That provider would have the following
* <code>Cipher</code> properties in its master class:
*
* <ul>
*
* <li>
* <pre>
* <code>Cipher.</code><i>AES/ECB/PKCS5Padding</i>
* </pre>
*
* <li>
* <pre>
* <code>Cipher.</code><i>AES/CBC/PKCS5Padding</i>
* </pre>
*
* <li>
* <pre>
* <code>Cipher.</code><i>AES/CFB/PKCS5Padding</i>
* </pre>
*
* <li>
* <pre>
* <code>Cipher.</code><i>AES/OFB/PKCS5Padding</i>
* </pre>
*
* </ul>
*
* <p>Another provider may implement a class for each of the above modes
* (i.e., one class for <i>ECB</i>, one for <i>CBC</i>, one for <i>CFB</i>,
* and one for <i>OFB</i>), one class for <i>PKCS5Padding</i>,
* and a generic <i>AES</i> class that subclasses from <code>CipherSpi</code>.
* That provider would have the following
* <code>Cipher</code> properties in its master class:
*
* <ul>
*
* <li>
* <pre>
* <code>Cipher.</code><i>AES</i>
* </pre>
*
* </ul>
*
* <p>The <code>getInstance</code> factory method of the <code>Cipher</code>
* engine class follows these rules in order to instantiate a provider's
* implementation of <code>CipherSpi</code> for a
* transformation of the form "<i>algorithm</i>":
*
* <ol>
* <li>
* Check if the provider has registered a subclass of <code>CipherSpi</code>
* for the specified "<i>algorithm</i>".
* <p>If the answer is YES, instantiate this
* class, for whose mode and padding scheme default values (as supplied by
* the provider) are used.
* <p>If the answer is NO, throw a <code>NoSuchAlgorithmException</code>
* exception.
* </ol>
*
* <p>The <code>getInstance</code> factory method of the <code>Cipher</code>
* engine class follows these rules in order to instantiate a provider's
* implementation of <code>CipherSpi</code> for a
* transformation of the form "<i>algorithm/mode/padding</i>":
*
* <ol>
* <li>
* Check if the provider has registered a subclass of <code>CipherSpi</code>
* for the specified "<i>algorithm/mode/padding</i>" transformation.
* <p>If the answer is YES, instantiate it.
* <p>If the answer is NO, go to the next step.
* <li>
* Check if the provider has registered a subclass of <code>CipherSpi</code>
* for the sub-transformation "<i>algorithm/mode</i>".
* <p>If the answer is YES, instantiate it, and call
* <code>engineSetPadding(<i>padding</i>)</code> on the new instance.
* <p>If the answer is NO, go to the next step.
* <li>
* Check if the provider has registered a subclass of <code>CipherSpi</code>
* for the sub-transformation "<i>algorithm//padding</i>" (note the double
* slashes).
* <p>If the answer is YES, instantiate it, and call
* <code>engineSetMode(<i>mode</i>)</code> on the new instance.
* <p>If the answer is NO, go to the next step.
* <li>
* Check if the provider has registered a subclass of <code>CipherSpi</code>
* for the sub-transformation "<i>algorithm</i>".
* <p>If the answer is YES, instantiate it, and call
* <code>engineSetMode(<i>mode</i>)</code> and
* <code>engineSetPadding(<i>padding</i>)</code> on the new instance.
* <p>If the answer is NO, throw a <code>NoSuchAlgorithmException</code>
* exception.
* </ol>
*
* @author Jan Luehe
* @see KeyGenerator
* @see SecretKey
* @since 1.4
*/
public abstract class CipherSpi {
/**
* Sets the mode of this cipher.
*
* @param mode the cipher mode
*
* @exception NoSuchAlgorithmException if the requested cipher mode does
* not exist
*/
protected abstract void engineSetMode(String mode)
throws NoSuchAlgorithmException;
/**
* Sets the padding mechanism of this cipher.
*
* @param padding the padding mechanism
*
* @exception NoSuchPaddingException if the requested padding mechanism
* does not exist
*/
protected abstract void engineSetPadding(String padding)
throws NoSuchPaddingException;
/**
* Returns the block size (in bytes).
*
* @return the block size (in bytes), or 0 if the underlying algorithm is
* not a block cipher
*/
protected abstract int engineGetBlockSize();
/**
* Returns the length in bytes that an output buffer would
* need to be in order to hold the result of the next <code>update</code>
* or <code>doFinal</code> operation, given the input length
* <code>inputLen</code> (in bytes).
*
* <p>This call takes into account any unprocessed (buffered) data from a
* previous <code>update</code> call, padding, and AEAD tagging.
*
* <p>The actual output length of the next <code>update</code> or
* <code>doFinal</code> call may be smaller than the length returned by
* this method.
*
* @param inputLen the input length (in bytes)
*
* @return the required output buffer size (in bytes)
*/
protected abstract int engineGetOutputSize(int inputLen);
/**
* Returns the initialization vector (IV) in a new buffer.
*
* <p> This is useful in the context of password-based encryption or
* decryption, where the IV is derived from a user-provided passphrase.
*
* @return the initialization vector in a new buffer, or null if the
* underlying algorithm does not use an IV, or if the IV has not yet
* been set.
*/
protected abstract byte[] engineGetIV();
/**
* Returns the parameters used with this cipher.
*
* <p>The returned parameters may be the same that were used to initialize
* this cipher, or may contain a combination of default and random
* parameter values used by the underlying cipher implementation if this
* cipher requires algorithm parameters but was not initialized with any.
*
* @return the parameters used with this cipher, or null if this cipher
* does not use any parameters.
*/
protected abstract AlgorithmParameters engineGetParameters();
/**
* Initializes this cipher with a key and a source
* of randomness.
*
* <p>The cipher is initialized for one of the following four operations:
* encryption, decryption, key wrapping or key unwrapping, depending on
* the value of <code>opmode</code>.
*
* <p>If this cipher requires any algorithm parameters that cannot be
* derived from the given <code>key</code>, the underlying cipher
* implementation is supposed to generate the required parameters itself
* (using provider-specific default or random values) if it is being
* initialized for encryption or key wrapping, and raise an
* <code>InvalidKeyException</code> if it is being
* initialized for decryption or key unwrapping.
* The generated parameters can be retrieved using
* {@link #engineGetParameters() engineGetParameters} or
* {@link #engineGetIV() engineGetIV} (if the parameter is an IV).
*
* <p>If this cipher requires algorithm parameters that cannot be
* derived from the input parameters, and there are no reasonable
* provider-specific default values, initialization will
* necessarily fail.
*
* <p>If this cipher (including its underlying feedback or padding scheme)
* requires any random bytes (e.g., for parameter generation), it will get
* them from <code>random</code>.
*
* <p>Note that when a Cipher object is initialized, it loses all
* previously-acquired state. In other words, initializing a Cipher is
* equivalent to creating a new instance of that Cipher and initializing
* it.
*
* @param opmode the operation mode of this cipher (this is one of
* the following:
* <code>ENCRYPT_MODE</code>, <code>DECRYPT_MODE</code>,
* <code>WRAP_MODE</code> or <code>UNWRAP_MODE</code>)
* @param key the encryption key
* @param random the source of randomness
*
* @exception InvalidKeyException if the given key is inappropriate for
* initializing this cipher, or requires
* algorithm parameters that cannot be
* determined from the given key.
* @throws UnsupportedOperationException if {@code opmode} is
* {@code WRAP_MODE} or {@code UNWRAP_MODE} is not implemented
* by the cipher.
*/
protected abstract void engineInit(int opmode, Key key,
SecureRandom random)
throws InvalidKeyException;
/**
* Initializes this cipher with a key, a set of
* algorithm parameters, and a source of randomness.
*
* <p>The cipher is initialized for one of the following four operations:
* encryption, decryption, key wrapping or key unwrapping, depending on
* the value of <code>opmode</code>.
*
* <p>If this cipher requires any algorithm parameters and
* <code>params</code> is null, the underlying cipher implementation is
* supposed to generate the required parameters itself (using
* provider-specific default or random values) if it is being
* initialized for encryption or key wrapping, and raise an
* <code>InvalidAlgorithmParameterException</code> if it is being
* initialized for decryption or key unwrapping.
* The generated parameters can be retrieved using
* {@link #engineGetParameters() engineGetParameters} or
* {@link #engineGetIV() engineGetIV} (if the parameter is an IV).
*
* <p>If this cipher requires algorithm parameters that cannot be
* derived from the input parameters, and there are no reasonable
* provider-specific default values, initialization will
* necessarily fail.
*
* <p>If this cipher (including its underlying feedback or padding scheme)
* requires any random bytes (e.g., for parameter generation), it will get
* them from <code>random</code>.
*
* <p>Note that when a Cipher object is initialized, it loses all
* previously-acquired state. In other words, initializing a Cipher is
* equivalent to creating a new instance of that Cipher and initializing
* it.
*
* @param opmode the operation mode of this cipher (this is one of
* the following:
* <code>ENCRYPT_MODE</code>, <code>DECRYPT_MODE</code>,
* <code>WRAP_MODE</code> or <code>UNWRAP_MODE</code>)
* @param key the encryption key
* @param params the algorithm parameters
* @param random the source of randomness
*
* @exception InvalidKeyException if the given key is inappropriate for
* initializing this cipher
* @exception InvalidAlgorithmParameterException if the given algorithm
* parameters are inappropriate for this cipher,
* or if this cipher requires
* algorithm parameters and <code>params</code> is null.
* @throws UnsupportedOperationException if {@code opmode} is
* {@code WRAP_MODE} or {@code UNWRAP_MODE} is not implemented
* by the cipher.
*/
protected abstract void engineInit(int opmode, Key key,
AlgorithmParameterSpec params,
SecureRandom random)
throws InvalidKeyException, InvalidAlgorithmParameterException;
/**
* Initializes this cipher with a key, a set of
* algorithm parameters, and a source of randomness.
*
* <p>The cipher is initialized for one of the following four operations:
* encryption, decryption, key wrapping or key unwrapping, depending on
* the value of <code>opmode</code>.
*
* <p>If this cipher requires any algorithm parameters and
* <code>params</code> is null, the underlying cipher implementation is
* supposed to generate the required parameters itself (using
* provider-specific default or random values) if it is being
* initialized for encryption or key wrapping, and raise an
* <code>InvalidAlgorithmParameterException</code> if it is being
* initialized for decryption or key unwrapping.
* The generated parameters can be retrieved using
* {@link #engineGetParameters() engineGetParameters} or
* {@link #engineGetIV() engineGetIV} (if the parameter is an IV).
*
* <p>If this cipher requires algorithm parameters that cannot be
* derived from the input parameters, and there are no reasonable
* provider-specific default values, initialization will
* necessarily fail.
*
* <p>If this cipher (including its underlying feedback or padding scheme)
* requires any random bytes (e.g., for parameter generation), it will get
* them from <code>random</code>.
*
* <p>Note that when a Cipher object is initialized, it loses all
* previously-acquired state. In other words, initializing a Cipher is
* equivalent to creating a new instance of that Cipher and initializing
* it.
*
* @param opmode the operation mode of this cipher (this is one of
* the following:
* <code>ENCRYPT_MODE</code>, <code>DECRYPT_MODE</code>,
* <code>WRAP_MODE</code> or <code>UNWRAP_MODE</code>)
* @param key the encryption key
* @param params the algorithm parameters
* @param random the source of randomness
*
* @exception InvalidKeyException if the given key is inappropriate for
* initializing this cipher
* @exception InvalidAlgorithmParameterException if the given algorithm
* parameters are inappropriate for this cipher,
* or if this cipher requires
* algorithm parameters and <code>params</code> is null.
* @throws UnsupportedOperationException if {@code opmode} is
* {@code WRAP_MODE} or {@code UNWRAP_MODE} is not implemented
* by the cipher.
*/
protected abstract void engineInit(int opmode, Key key,
AlgorithmParameters params,
SecureRandom random)
throws InvalidKeyException, InvalidAlgorithmParameterException;
/**
* Continues a multiple-part encryption or decryption operation
* (depending on how this cipher was initialized), processing another data
* part.
*
* <p>The first <code>inputLen</code> bytes in the <code>input</code>
* buffer, starting at <code>inputOffset</code> inclusive, are processed,
* and the result is stored in a new buffer.
*
* @param input the input buffer
* @param inputOffset the offset in <code>input</code> where the input
* starts
* @param inputLen the input length
*
* @return the new buffer with the result, or null if the underlying
* cipher is a block cipher and the input data is too short to result in a
* new block.
*/
protected abstract byte[] engineUpdate(byte[] input, int inputOffset,
int inputLen);
/**
* Continues a multiple-part encryption or decryption operation
* (depending on how this cipher was initialized), processing another data
* part.
*
* <p>The first <code>inputLen</code> bytes in the <code>input</code>
* buffer, starting at <code>inputOffset</code> inclusive, are processed,
* and the result is stored in the <code>output</code> buffer, starting at
* <code>outputOffset</code> inclusive.
*
* <p>If the <code>output</code> buffer is too small to hold the result,
* a <code>ShortBufferException</code> is thrown.
*
* @param input the input buffer
* @param inputOffset the offset in <code>input</code> where the input
* starts
* @param inputLen the input length
* @param output the buffer for the result
* @param outputOffset the offset in <code>output</code> where the result
* is stored
*
* @return the number of bytes stored in <code>output</code>
*
* @exception ShortBufferException if the given output buffer is too small
* to hold the result
*/
protected abstract int engineUpdate(byte[] input, int inputOffset,
int inputLen, byte[] output,
int outputOffset)
throws ShortBufferException;
/**
* Continues a multiple-part encryption or decryption operation
* (depending on how this cipher was initialized), processing another data
* part.
*
* <p>All <code>input.remaining()</code> bytes starting at
* <code>input.position()</code> are processed. The result is stored
* in the output buffer.
* Upon return, the input buffer's position will be equal
* to its limit; its limit will not have changed. The output buffer's
* position will have advanced by n, where n is the value returned
* by this method; the output buffer's limit will not have changed.
*
* <p>If <code>output.remaining()</code> bytes are insufficient to
* hold the result, a <code>ShortBufferException</code> is thrown.
*
* <p>Subclasses should consider overriding this method if they can
* process ByteBuffers more efficiently than byte arrays.
*
* @param input the input ByteBuffer
* @param output the output ByteByffer
*
* @return the number of bytes stored in <code>output</code>
*
* @exception ShortBufferException if there is insufficient space in the
* output buffer
*
* @throws NullPointerException if either parameter is <CODE>null</CODE>
* @since 1.5
*/
protected int engineUpdate(ByteBuffer input, ByteBuffer output)
throws ShortBufferException {
try {
return bufferCrypt(input, output, true);
} catch (IllegalBlockSizeException e) {
// never thrown for engineUpdate()
throw new ProviderException("Internal error in update()");
} catch (BadPaddingException e) {
// never thrown for engineUpdate()
throw new ProviderException("Internal error in update()");
}
}
/**
* Encrypts or decrypts data in a single-part operation,
* or finishes a multiple-part operation.
* The data is encrypted or decrypted, depending on how this cipher was
* initialized.
*
* <p>The first <code>inputLen</code> bytes in the <code>input</code>
* buffer, starting at <code>inputOffset</code> inclusive, and any input
* bytes that may have been buffered during a previous <code>update</code>
* operation, are processed, with padding (if requested) being applied.
* If an AEAD mode such as GCM/CCM is being used, the authentication
* tag is appended in the case of encryption, or verified in the
* case of decryption.
* The result is stored in a new buffer.
*
* <p>Upon finishing, this method resets this cipher object to the state
* it was in when previously initialized via a call to
* <code>engineInit</code>.
* That is, the object is reset and available to encrypt or decrypt
* (depending on the operation mode that was specified in the call to
* <code>engineInit</code>) more data.
*
* <p>Note: if any exception is thrown, this cipher object may need to
* be reset before it can be used again.
*
* @param input the input buffer
* @param inputOffset the offset in <code>input</code> where the input
* starts
* @param inputLen the input length
*
* @return the new buffer with the result
*
* @exception IllegalBlockSizeException if this cipher is a block cipher,
* no padding has been requested (only in encryption mode), and the total
* input length of the data processed by this cipher is not a multiple of
* block size; or if this encryption algorithm is unable to
* process the input data provided.
* @exception BadPaddingException if this cipher is in decryption mode,
* and (un)padding has been requested, but the decrypted data is not
* bounded by the appropriate padding bytes
* @exception AEADBadTagException if this cipher is decrypting in an
* AEAD mode (such as GCM/CCM), and the received authentication tag
* does not match the calculated value
*/
protected abstract byte[] engineDoFinal(byte[] input, int inputOffset,
int inputLen)
throws IllegalBlockSizeException, BadPaddingException;
/**
* Encrypts or decrypts data in a single-part operation,
* or finishes a multiple-part operation.
* The data is encrypted or decrypted, depending on how this cipher was
* initialized.
*
* <p>The first <code>inputLen</code> bytes in the <code>input</code>
* buffer, starting at <code>inputOffset</code> inclusive, and any input
* bytes that may have been buffered during a previous <code>update</code>
* operation, are processed, with padding (if requested) being applied.
* If an AEAD mode such as GCM/CCM is being used, the authentication
* tag is appended in the case of encryption, or verified in the
* case of decryption.
* The result is stored in the <code>output</code> buffer, starting at
* <code>outputOffset</code> inclusive.
*
* <p>If the <code>output</code> buffer is too small to hold the result,
* a <code>ShortBufferException</code> is thrown.
*
* <p>Upon finishing, this method resets this cipher object to the state
* it was in when previously initialized via a call to
* <code>engineInit</code>.
* That is, the object is reset and available to encrypt or decrypt
* (depending on the operation mode that was specified in the call to
* <code>engineInit</code>) more data.
*
* <p>Note: if any exception is thrown, this cipher object may need to
* be reset before it can be used again.
*
* @param input the input buffer
* @param inputOffset the offset in <code>input</code> where the input
* starts
* @param inputLen the input length
* @param output the buffer for the result
* @param outputOffset the offset in <code>output</code> where the result
* is stored
*
* @return the number of bytes stored in <code>output</code>
*
* @exception IllegalBlockSizeException if this cipher is a block cipher,
* no padding has been requested (only in encryption mode), and the total
* input length of the data processed by this cipher is not a multiple of
* block size; or if this encryption algorithm is unable to
* process the input data provided.
* @exception ShortBufferException if the given output buffer is too small
* to hold the result
* @exception BadPaddingException if this cipher is in decryption mode,
* and (un)padding has been requested, but the decrypted data is not
* bounded by the appropriate padding bytes
* @exception AEADBadTagException if this cipher is decrypting in an
* AEAD mode (such as GCM/CCM), and the received authentication tag
* does not match the calculated value
*/
protected abstract int engineDoFinal(byte[] input, int inputOffset,
int inputLen, byte[] output,
int outputOffset)
throws ShortBufferException, IllegalBlockSizeException,
BadPaddingException;
/**
* Encrypts or decrypts data in a single-part operation,
* or finishes a multiple-part operation.
* The data is encrypted or decrypted, depending on how this cipher was
* initialized.
*
* <p>All <code>input.remaining()</code> bytes starting at
* <code>input.position()</code> are processed.
* If an AEAD mode such as GCM/CCM is being used, the authentication
* tag is appended in the case of encryption, or verified in the
* case of decryption.
* The result is stored in the output buffer.
* Upon return, the input buffer's position will be equal
* to its limit; its limit will not have changed. The output buffer's
* position will have advanced by n, where n is the value returned
* by this method; the output buffer's limit will not have changed.
*
* <p>If <code>output.remaining()</code> bytes are insufficient to
* hold the result, a <code>ShortBufferException</code> is thrown.
*
* <p>Upon finishing, this method resets this cipher object to the state
* it was in when previously initialized via a call to
* <code>engineInit</code>.
* That is, the object is reset and available to encrypt or decrypt
* (depending on the operation mode that was specified in the call to
* <code>engineInit</code>) more data.
*
* <p>Note: if any exception is thrown, this cipher object may need to
* be reset before it can be used again.
*
* <p>Subclasses should consider overriding this method if they can
* process ByteBuffers more efficiently than byte arrays.
*
* @param input the input ByteBuffer
* @param output the output ByteByffer
*
* @return the number of bytes stored in <code>output</code>
*
* @exception IllegalBlockSizeException if this cipher is a block cipher,
* no padding has been requested (only in encryption mode), and the total
* input length of the data processed by this cipher is not a multiple of
* block size; or if this encryption algorithm is unable to
* process the input data provided.
* @exception ShortBufferException if there is insufficient space in the
* output buffer
* @exception BadPaddingException if this cipher is in decryption mode,
* and (un)padding has been requested, but the decrypted data is not
* bounded by the appropriate padding bytes
* @exception AEADBadTagException if this cipher is decrypting in an
* AEAD mode (such as GCM/CCM), and the received authentication tag
* does not match the calculated value
*
* @throws NullPointerException if either parameter is <CODE>null</CODE>
* @since 1.5
*/
protected int engineDoFinal(ByteBuffer input, ByteBuffer output)
throws ShortBufferException, IllegalBlockSizeException,
BadPaddingException {
return bufferCrypt(input, output, false);
}
// copied from sun.security.jca.JCAUtil
// will be changed to reference that method once that code has been
// integrated and promoted
static int getTempArraySize(int totalSize) {
return Math.min(4096, totalSize);
}
/**
* Implementation for encryption using ByteBuffers. Used for both
* engineUpdate() and engineDoFinal().
*/
private int bufferCrypt(ByteBuffer input, ByteBuffer output,
boolean isUpdate) throws ShortBufferException,
IllegalBlockSizeException, BadPaddingException {
if ((input == null) || (output == null)) {
throw new NullPointerException
("Input and output buffers must not be null");
}
int inPos = input.position();
int inLimit = input.limit();
int inLen = inLimit - inPos;
if (isUpdate && (inLen == 0)) {
return 0;
}
int outLenNeeded = engineGetOutputSize(inLen);
if (output.remaining() < outLenNeeded) {
throw new ShortBufferException("Need at least " + outLenNeeded
+ " bytes of space in output buffer");
}
boolean a1 = input.hasArray();
boolean a2 = output.hasArray();
int total = 0;
byte[] inArray, outArray;
if (a2) { // output has an accessible byte[]
outArray = output.array();
int outPos = output.position();
int outOfs = output.arrayOffset() + outPos;
if (a1) { // input also has an accessible byte[]
inArray = input.array();
int inOfs = input.arrayOffset() + inPos;
if (isUpdate) {
total = engineUpdate(inArray, inOfs, inLen, outArray, outOfs);
} else {
total = engineDoFinal(inArray, inOfs, inLen, outArray, outOfs);
}
input.position(inLimit);
} else { // input does not have accessible byte[]
inArray = new byte[getTempArraySize(inLen)];
do {
int chunk = Math.min(inLen, inArray.length);
if (chunk > 0) {
input.get(inArray, 0, chunk);
}
int n;
if (isUpdate || (inLen > chunk)) {
n = engineUpdate(inArray, 0, chunk, outArray, outOfs);
} else {
n = engineDoFinal(inArray, 0, chunk, outArray, outOfs);
}
total += n;
outOfs += n;
inLen -= chunk;
} while (inLen > 0);
}
output.position(outPos + total);
} else { // output does not have an accessible byte[]
if (a1) { // but input has an accessible byte[]
inArray = input.array();
int inOfs = input.arrayOffset() + inPos;
if (isUpdate) {
outArray = engineUpdate(inArray, inOfs, inLen);
} else {
outArray = engineDoFinal(inArray, inOfs, inLen);
}
input.position(inLimit);
if (outArray != null && outArray.length != 0) {
output.put(outArray);
total = outArray.length;
}
} else { // input also does not have an accessible byte[]
inArray = new byte[getTempArraySize(inLen)];
do {
int chunk = Math.min(inLen, inArray.length);
if (chunk > 0) {
input.get(inArray, 0, chunk);
}
int n;
if (isUpdate || (inLen > chunk)) {
outArray = engineUpdate(inArray, 0, chunk);
} else {
outArray = engineDoFinal(inArray, 0, chunk);
}
if (outArray != null && outArray.length != 0) {
output.put(outArray);
total += outArray.length;
}
inLen -= chunk;
} while (inLen > 0);
}
}
return total;
}
/**
* Wrap a key.
*
* <p>This concrete method has been added to this previously-defined
* abstract class. (For backwards compatibility, it cannot be abstract.)
* It may be overridden by a provider to wrap a key.
* Such an override is expected to throw an IllegalBlockSizeException or
* InvalidKeyException (under the specified circumstances),
* if the given key cannot be wrapped.
* If this method is not overridden, it always throws an
* UnsupportedOperationException.
*
* @param key the key to be wrapped.
*
* @return the wrapped key.
*
* @exception IllegalBlockSizeException if this cipher is a block cipher,
* no padding has been requested, and the length of the encoding of the
* key to be wrapped is not a multiple of the block size.
*
* @exception InvalidKeyException if it is impossible or unsafe to
* wrap the key with this cipher (e.g., a hardware protected key is
* being passed to a software-only cipher).
*
* @throws UnsupportedOperationException if this method is not supported.
*/
protected byte[] engineWrap(Key key)
throws IllegalBlockSizeException, InvalidKeyException
{
throw new UnsupportedOperationException();
}
/**
* Unwrap a previously wrapped key.
*
* <p>This concrete method has been added to this previously-defined
* abstract class. (For backwards compatibility, it cannot be abstract.)
* It may be overridden by a provider to unwrap a previously wrapped key.
* Such an override is expected to throw an InvalidKeyException if
* the given wrapped key cannot be unwrapped.
* If this method is not overridden, it always throws an
* UnsupportedOperationException.
*
* @param wrappedKey the key to be unwrapped.
*
* @param wrappedKeyAlgorithm the algorithm associated with the wrapped
* key.
*
* @param wrappedKeyType the type of the wrapped key. This is one of
* <code>SECRET_KEY</code>, <code>PRIVATE_KEY</code>, or
* <code>PUBLIC_KEY</code>.
*
* @return the unwrapped key.
*
* @exception NoSuchAlgorithmException if no installed providers
* can create keys of type <code>wrappedKeyType</code> for the
* <code>wrappedKeyAlgorithm</code>.
*
* @exception InvalidKeyException if <code>wrappedKey</code> does not
* represent a wrapped key of type <code>wrappedKeyType</code> for
* the <code>wrappedKeyAlgorithm</code>.
*
* @throws UnsupportedOperationException if this method is not supported.
*/
protected Key engineUnwrap(byte[] wrappedKey,
String wrappedKeyAlgorithm,
int wrappedKeyType)
throws InvalidKeyException, NoSuchAlgorithmException
{
throw new UnsupportedOperationException();
}
/**
* Returns the key size of the given key object in bits.
* <p>This concrete method has been added to this previously-defined
* abstract class. It throws an <code>UnsupportedOperationException</code>
* if it is not overridden by the provider.
*
* @param key the key object.
*
* @return the key size of the given key object.
*
* @exception InvalidKeyException if <code>key</code> is invalid.
*/
protected int engineGetKeySize(Key key)
throws InvalidKeyException
{
throw new UnsupportedOperationException();
}
/**
* Continues a multi-part update of the Additional Authentication
* Data (AAD), using a subset of the provided buffer.
* <p>
* Calls to this method provide AAD to the cipher when operating in
* modes such as AEAD (GCM/CCM). If this cipher is operating in
* either GCM or CCM mode, all AAD must be supplied before beginning
* operations on the ciphertext (via the {@code update} and {@code
* doFinal} methods).
*
* @param src the buffer containing the AAD
* @param offset the offset in {@code src} where the AAD input starts
* @param len the number of AAD bytes
*
* @throws IllegalStateException if this cipher is in a wrong state
* (e.g., has not been initialized), does not accept AAD, or if
* operating in either GCM or CCM mode and one of the {@code update}
* methods has already been called for the active
* encryption/decryption operation
* @throws UnsupportedOperationException if this method
* has not been overridden by an implementation
*
* @since 1.7
*/
protected void engineUpdateAAD(byte[] src, int offset, int len) {
throw new UnsupportedOperationException(
"The underlying Cipher implementation "
+ "does not support this method");
}
/**
* Continues a multi-part update of the Additional Authentication
* Data (AAD).
* <p>
* Calls to this method provide AAD to the cipher when operating in
* modes such as AEAD (GCM/CCM). If this cipher is operating in
* either GCM or CCM mode, all AAD must be supplied before beginning
* operations on the ciphertext (via the {@code update} and {@code
* doFinal} methods).
* <p>
* All {@code src.remaining()} bytes starting at
* {@code src.position()} are processed.
* Upon return, the input buffer's position will be equal
* to its limit; its limit will not have changed.
*
* @param src the buffer containing the AAD
*
* @throws IllegalStateException if this cipher is in a wrong state
* (e.g., has not been initialized), does not accept AAD, or if
* operating in either GCM or CCM mode and one of the {@code update}
* methods has already been called for the active
* encryption/decryption operation
* @throws UnsupportedOperationException if this method
* has not been overridden by an implementation
*
* @since 1.7
*/
protected void engineUpdateAAD(ByteBuffer src) {
throw new UnsupportedOperationException(
"The underlying Cipher implementation "
+ "does not support this method");
}
}

View File

@@ -0,0 +1,177 @@
/*
* Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.crypto;
import java.security.*;
import java.util.Enumeration;
import java.util.Vector;
/**
* The CryptoAllPermission is a permission that implies
* any other crypto permissions.
* <p>
*
* @see java.security.Permission
* @see java.security.AllPermission
*
* @author Sharon Liu
* @since 1.4
*/
final class CryptoAllPermission extends CryptoPermission {
private static final long serialVersionUID = -5066513634293192112L;
// This class is similar to java.security.AllPermission.
static final String ALG_NAME = "CryptoAllPermission";
static final CryptoAllPermission INSTANCE =
new CryptoAllPermission();
private CryptoAllPermission() {
super(ALG_NAME);
}
/**
* Checks if the specified permission is implied by
* this object.
*
* @param p the permission to check against.
*
* @return true if the specified permission is an
* instance of CryptoPermission.
*/
public boolean implies(Permission p) {
return (p instanceof CryptoPermission);
}
/**
* Checks two CryptoAllPermission objects for equality.
* Two CryptoAllPermission objects are always equal.
*
* @param obj the object to test for equality with this object.
*
* @return true if <i>obj</i> is a CryptoAllPermission object.
*/
public boolean equals(Object obj) {
return (obj == INSTANCE);
}
/**
*
* Returns the hash code value for this object.
*
* @return a hash code value for this object.
*/
public int hashCode() {
return 1;
}
/**
* Returns a new PermissionCollection object for storing
* CryptoAllPermission objects.
* <p>
*
* @return a new PermissionCollection object suitable for
* storing CryptoAllPermissions.
*/
public PermissionCollection newPermissionCollection() {
return new CryptoAllPermissionCollection();
}
}
/**
* A CryptoAllPermissionCollection stores a collection
* of CryptoAllPermission permissions.
*
* @see java.security.Permission
* @see java.security.Permissions
* @see javax.crypto.CryptoPermission
*
* @author Sharon Liu
*/
final class CryptoAllPermissionCollection extends PermissionCollection
implements java.io.Serializable
{
private static final long serialVersionUID = 7450076868380144072L;
// true if a CryptoAllPermission has been added
private boolean all_allowed;
/**
* Create an empty CryptoAllPermissions object.
*/
CryptoAllPermissionCollection() {
all_allowed = false;
}
/**
* Adds a permission to the CryptoAllPermissions.
*
* @param permission the Permission object to add.
*
* @exception SecurityException - if this CryptoAllPermissionCollection
* object has been marked readonly
*/
public void add(Permission permission) {
if (isReadOnly())
throw new SecurityException("attempt to add a Permission to " +
"a readonly PermissionCollection");
if (permission != CryptoAllPermission.INSTANCE)
return;
all_allowed = true;
}
/**
* Check and see if this set of permissions implies the permissions
* expressed in "permission".
*
* @param permission the Permission object to compare
*
* @return true if the given permission is implied by this
* CryptoAllPermissionCollection.
*/
public boolean implies(Permission permission) {
if (!(permission instanceof CryptoPermission)) {
return false;
}
return all_allowed;
}
/**
* Returns an enumeration of all the CryptoAllPermission
* objects in the container.
*
* @return an enumeration of all the CryptoAllPermission objects.
*/
public Enumeration<Permission> elements() {
Vector<Permission> v = new Vector<>(1);
if (all_allowed) v.add(CryptoAllPermission.INSTANCE);
return v.elements();
}
}

View File

@@ -0,0 +1,543 @@
/*
* Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.crypto;
import java.security.*;
import java.security.spec.AlgorithmParameterSpec;
import java.io.Serializable;
import java.util.Enumeration;
import java.util.Vector;
import javax.crypto.spec.*;
/**
* The CryptoPermission class extends the
* java.security.Permission class. A
* CryptoPermission object is used to represent
* the ability of an application/applet to use certain
* algorithms with certain key sizes and other
* restrictions in certain environments. <p>
*
* @see java.security.Permission
*
* @author Jan Luehe
* @author Sharon Liu
* @since 1.4
*/
class CryptoPermission extends java.security.Permission {
private static final long serialVersionUID = 8987399626114087514L;
private String alg;
private int maxKeySize = Integer.MAX_VALUE; // no restriction on maxKeySize
private String exemptionMechanism = null;
private AlgorithmParameterSpec algParamSpec = null;
private boolean checkParam = false; // no restriction on param
static final String ALG_NAME_WILDCARD = "*";
/**
* Constructor that takes an algorithm name.
*
* This constructor implies that the given algorithm can be
* used without any restrictions.
*
* @param alg the algorithm name.
*/
CryptoPermission(String alg) {
super(null);
this.alg = alg;
}
/**
* Constructor that takes an algorithm name and a maximum
* key size.
*
* This constructor implies that the given algorithm can be
* used with a key size up to <code>maxKeySize</code>.
*
* @param alg the algorithm name.
*
* @param maxKeySize the maximum allowable key size,
* specified in number of bits.
*/
CryptoPermission(String alg, int maxKeySize) {
super(null);
this.alg = alg;
this.maxKeySize = maxKeySize;
}
/**
* Constructor that takes an algorithm name, a maximum
* key size, and an AlgorithmParameterSpec object.
*
* This constructor implies that the given algorithm can be
* used with a key size up to <code>maxKeySize</code>, and
* algorithm
* parameters up to the limits set in <code>algParamSpec</code>.
*
* @param alg the algorithm name.
*
* @param maxKeySize the maximum allowable key size,
* specified in number of bits.
*
* @param algParamSpec the limits for allowable algorithm
* parameters.
*/
CryptoPermission(String alg,
int maxKeySize,
AlgorithmParameterSpec algParamSpec) {
super(null);
this.alg = alg;
this.maxKeySize = maxKeySize;
this.checkParam = true;
this.algParamSpec = algParamSpec;
}
/**
* Constructor that takes an algorithm name and the name of
* an exemption mechanism.
*
* This constructor implies that the given algorithm can be
* used without any key size or algorithm parameter restrictions
* provided that the specified exemption mechanism is enforced.
*
* @param alg the algorithm name.
*
* @param exemptionMechanism the name of the exemption mechanism.
*/
CryptoPermission(String alg,
String exemptionMechanism) {
super(null);
this.alg = alg;
this.exemptionMechanism = exemptionMechanism;
}
/**
* Constructor that takes an algorithm name, a maximum key
* size, and the name of an exemption mechanism.
*
* This constructor implies that the given algorithm can be
* used with a key size up to <code>maxKeySize</code>
* provided that the
* specified exemption mechanism is enforced.
*
* @param alg the algorithm name.
* @param maxKeySize the maximum allowable key size,
* specified in number of bits.
* @param exemptionMechanism the name of the exemption
* mechanism.
*/
CryptoPermission(String alg,
int maxKeySize,
String exemptionMechanism) {
super(null);
this.alg = alg;
this.exemptionMechanism = exemptionMechanism;
this.maxKeySize = maxKeySize;
}
/**
* Constructor that takes an algorithm name, a maximum key
* size, the name of an exemption mechanism, and an
* AlgorithmParameterSpec object.
*
* This constructor implies that the given algorithm can be
* used with a key size up to <code>maxKeySize</code>
* and algorithm
* parameters up to the limits set in <code>algParamSpec</code>
* provided that
* the specified exemption mechanism is enforced.
*
* @param alg the algorithm name.
* @param maxKeySize the maximum allowable key size,
* specified in number of bits.
* @param algParamSpec the limit for allowable algorithm
* parameter spec.
* @param exemptionMechanism the name of the exemption
* mechanism.
*/
CryptoPermission(String alg,
int maxKeySize,
AlgorithmParameterSpec algParamSpec,
String exemptionMechanism) {
super(null);
this.alg = alg;
this.exemptionMechanism = exemptionMechanism;
this.maxKeySize = maxKeySize;
this.checkParam = true;
this.algParamSpec = algParamSpec;
}
/**
* Checks if the specified permission is "implied" by
* this object.
* <p>
* More specifically, this method returns true if:<p>
* <ul>
* <li> <i>p</i> is an instance of CryptoPermission, and<p>
* <li> <i>p</i>'s algorithm name equals or (in the case of wildcards)
* is implied by this permission's algorithm name, and<p>
* <li> <i>p</i>'s maximum allowable key size is less or
* equal to this permission's maximum allowable key size, and<p>
* <li> <i>p</i>'s algorithm parameter spec equals or is
* implied by this permission's algorithm parameter spec, and<p>
* <li> <i>p</i>'s exemptionMechanism equals or
* is implied by this permission's
* exemptionMechanism (a <code>null</code> exemption mechanism
* implies any other exemption mechanism).
* </ul>
*
* @param p the permission to check against.
*
* @return true if the specified permission is equal to or
* implied by this permission, false otherwise.
*/
public boolean implies(Permission p) {
if (!(p instanceof CryptoPermission))
return false;
CryptoPermission cp = (CryptoPermission)p;
if ((!alg.equalsIgnoreCase(cp.alg)) &&
(!alg.equalsIgnoreCase(ALG_NAME_WILDCARD))) {
return false;
}
// alg is the same as cp's alg or
// alg is a wildcard.
if (cp.maxKeySize <= this.maxKeySize) {
// check algParamSpec.
if (!impliesParameterSpec(cp.checkParam, cp.algParamSpec)) {
return false;
}
// check exemptionMechanism.
if (impliesExemptionMechanism(cp.exemptionMechanism)) {
return true;
}
}
return false;
}
/**
* Checks two CryptoPermission objects for equality. Checks that
* <code>obj</code> is a CryptoPermission, and has the same
* algorithm name,
* exemption mechanism name, maximum allowable key size and
* algorithm parameter spec
* as this object.
* <P>
* @param obj the object to test for equality with this object.
* @return true if <code>obj</code> is equal to this object.
*/
public boolean equals(Object obj) {
if (obj == this)
return true;
if (!(obj instanceof CryptoPermission))
return false;
CryptoPermission that = (CryptoPermission) obj;
if (!(alg.equalsIgnoreCase(that.alg)) ||
(maxKeySize != that.maxKeySize)) {
return false;
}
if (this.checkParam != that.checkParam) {
return false;
}
return (equalObjects(this.exemptionMechanism,
that.exemptionMechanism) &&
equalObjects(this.algParamSpec,
that.algParamSpec));
}
/**
* Returns the hash code value for this object.
*
* @return a hash code value for this object.
*/
public int hashCode() {
int retval = alg.hashCode();
retval ^= maxKeySize;
if (exemptionMechanism != null) {
retval ^= exemptionMechanism.hashCode();
}
if (checkParam) retval ^= 100;
if (algParamSpec != null) {
retval ^= algParamSpec.hashCode();
}
return retval;
}
/**
* There is no action defined for a CryptoPermission
* onject.
*/
public String getActions()
{
return null;
}
/**
* Returns a new PermissionCollection object for storing
* CryptoPermission objects.
*
* @return a new PermissionCollection object suitable for storing
* CryptoPermissions.
*/
public PermissionCollection newPermissionCollection() {
return new CryptoPermissionCollection();
}
/**
* Returns the algorithm name associated with
* this CryptoPermission object.
*/
final String getAlgorithm() {
return alg;
}
/**
* Returns the exemption mechanism name
* associated with this CryptoPermission
* object.
*/
final String getExemptionMechanism() {
return exemptionMechanism;
}
/**
* Returns the maximum allowable key size associated
* with this CryptoPermission object.
*/
final int getMaxKeySize() {
return maxKeySize;
}
/**
* Returns true if there is a limitation on the
* AlgorithmParameterSpec associated with this
* CryptoPermission object and false if otherwise.
*/
final boolean getCheckParam() {
return checkParam;
}
/**
* Returns the AlgorithmParameterSpec
* associated with this CryptoPermission
* object.
*/
final AlgorithmParameterSpec getAlgorithmParameterSpec() {
return algParamSpec;
}
/**
* Returns a string describing this CryptoPermission. The convention is to
* specify the class name, the algorithm name, the maximum allowable
* key size, and the name of the exemption mechanism, in the following
* format: '("ClassName" "algorithm" "keysize" "exemption_mechanism")'.
*
* @return information about this CryptoPermission.
*/
public String toString() {
StringBuilder buf = new StringBuilder(100);
buf.append("(CryptoPermission " + alg + " " + maxKeySize);
if (algParamSpec != null) {
if (algParamSpec instanceof RC2ParameterSpec) {
buf.append(" , effective " +
((RC2ParameterSpec)algParamSpec).getEffectiveKeyBits());
} else if (algParamSpec instanceof RC5ParameterSpec) {
buf.append(" , rounds " +
((RC5ParameterSpec)algParamSpec).getRounds());
}
}
if (exemptionMechanism != null) { // OPTIONAL
buf.append(" " + exemptionMechanism);
}
buf.append(")");
return buf.toString();
}
private boolean impliesExemptionMechanism(String exemptionMechanism) {
if (this.exemptionMechanism == null) {
return true;
}
if (exemptionMechanism == null) {
return false;
}
if (this.exemptionMechanism.equals(exemptionMechanism)) {
return true;
}
return false;
}
private boolean impliesParameterSpec(boolean checkParam,
AlgorithmParameterSpec algParamSpec) {
if ((this.checkParam) && checkParam) {
if (algParamSpec == null) {
return true;
} else if (this.algParamSpec == null) {
return false;
}
if (this.algParamSpec.getClass() != algParamSpec.getClass()) {
return false;
}
if (algParamSpec instanceof RC2ParameterSpec) {
if (((RC2ParameterSpec)algParamSpec).getEffectiveKeyBits() <=
((RC2ParameterSpec)
(this.algParamSpec)).getEffectiveKeyBits()) {
return true;
}
}
if (algParamSpec instanceof RC5ParameterSpec) {
if (((RC5ParameterSpec)algParamSpec).getRounds() <=
((RC5ParameterSpec)this.algParamSpec).getRounds()) {
return true;
}
}
if (algParamSpec instanceof PBEParameterSpec) {
if (((PBEParameterSpec)algParamSpec).getIterationCount() <=
((PBEParameterSpec)this.algParamSpec).getIterationCount()) {
return true;
}
}
// For classes we don't know, the following
// may be the best try.
if (this.algParamSpec.equals(algParamSpec)) {
return true;
}
return false;
} else if (this.checkParam) {
return false;
} else {
return true;
}
}
private boolean equalObjects(Object obj1, Object obj2) {
if (obj1 == null) {
return (obj2 == null ? true : false);
}
return obj1.equals(obj2);
}
}
/**
* A CryptoPermissionCollection stores a set of CryptoPermission
* permissions.
*
* @see java.security.Permission
* @see java.security.Permissions
* @see java.security.PermissionCollection
*
* @author Sharon Liu
*/
final class CryptoPermissionCollection extends PermissionCollection
implements Serializable
{
private static final long serialVersionUID = -511215555898802763L;
private Vector<Permission> permissions;
/**
* Creates an empty CryptoPermissionCollection
* object.
*/
CryptoPermissionCollection() {
permissions = new Vector<Permission>(3);
}
/**
* Adds a permission to the CryptoPermissionCollection.
*
* @param permission the Permission object to add.
*
* @exception SecurityException - if this CryptoPermissionCollection
* object has been marked <i>readOnly</i>.
*/
public void add(Permission permission) {
if (isReadOnly())
throw new SecurityException("attempt to add a Permission " +
"to a readonly PermissionCollection");
if (!(permission instanceof CryptoPermission))
return;
permissions.addElement(permission);
}
/**
* Check and see if this CryptoPermission object implies
* the given Permission object.
*
* @param permission the Permission object to compare
*
* @return true if the given permission is implied by this
* CryptoPermissionCollection, false if not.
*/
public boolean implies(Permission permission) {
if (!(permission instanceof CryptoPermission))
return false;
CryptoPermission cp = (CryptoPermission)permission;
Enumeration<Permission> e = permissions.elements();
while (e.hasMoreElements()) {
CryptoPermission x = (CryptoPermission) e.nextElement();
if (x.implies(cp)) {
return true;
}
}
return false;
}
/**
* Returns an enumeration of all the CryptoPermission objects
* in the container.
*
* @return an enumeration of all the CryptoPermission objects.
*/
public Enumeration<Permission> elements() {
return permissions.elements();
}
}

View File

@@ -0,0 +1,504 @@
/*
* Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.crypto;
import java.security.*;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;
import java.util.NoSuchElementException;
import java.util.concurrent.ConcurrentHashMap;
import java.io.Serializable;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.BufferedReader;
import java.io.ObjectStreamField;
import java.io.ObjectInputStream;
import java.io.ObjectInputStream.GetField;
import java.io.ObjectOutputStream;
import java.io.ObjectOutputStream.PutField;
import java.io.IOException;
/**
* This class contains CryptoPermission objects, organized into
* PermissionCollections according to algorithm names.
*
* <p>When the <code>add</code> method is called to add a
* CryptoPermission, the CryptoPermission is stored in the
* appropriate PermissionCollection. If no such
* collection exists yet, the algorithm name associated with
* the CryptoPermission object is
* determined and the <code>newPermissionCollection</code> method
* is called on the CryptoPermission or CryptoAllPermission class to
* create the PermissionCollection and add it to the Permissions object.
*
* @see javax.crypto.CryptoPermission
* @see java.security.PermissionCollection
* @see java.security.Permissions
*
* @author Sharon Liu
* @since 1.4
*/
final class CryptoPermissions extends PermissionCollection
implements Serializable {
private static final long serialVersionUID = 4946547168093391015L;
/**
* @serialField perms java.util.Hashtable
*/
private static final ObjectStreamField[] serialPersistentFields = {
new ObjectStreamField("perms", Hashtable.class),
};
// Switched from Hashtable to ConcurrentHashMap to improve scalability.
// To maintain serialization compatibility, this field is made transient
// and custom readObject/writeObject methods are used.
private transient ConcurrentHashMap<String,PermissionCollection> perms;
/**
* Creates a new CryptoPermissions object containing
* no CryptoPermissionCollections.
*/
CryptoPermissions() {
perms = new ConcurrentHashMap<>(7);
}
/**
* Populates the crypto policy from the specified
* InputStream into this CryptoPermissions object.
*
* @param in the InputStream to load from.
*
* @exception SecurityException if cannot load
* successfully.
*/
void load(InputStream in)
throws IOException, CryptoPolicyParser.ParsingException {
CryptoPolicyParser parser = new CryptoPolicyParser();
parser.read(new BufferedReader(new InputStreamReader(in, "UTF-8")));
CryptoPermission[] parsingResult = parser.getPermissions();
for (int i = 0; i < parsingResult.length; i++) {
this.add(parsingResult[i]);
}
}
/**
* Returns true if this CryptoPermissions object doesn't
* contain any CryptoPermission objects; otherwise, returns
* false.
*/
boolean isEmpty() {
return perms.isEmpty();
}
/**
* Adds a permission object to the PermissionCollection for the
* algorithm returned by
* <code>(CryptoPermission)permission.getAlgorithm()</code>.
*
* This method creates
* a new PermissionCollection object (and adds the permission to it)
* if an appropriate collection does not yet exist. <p>
*
* @param permission the Permission object to add.
*
* @exception SecurityException if this CryptoPermissions object is
* marked as readonly.
*
* @see isReadOnly
*/
public void add(Permission permission) {
if (isReadOnly())
throw new SecurityException("Attempt to add a Permission " +
"to a readonly CryptoPermissions " +
"object");
if (!(permission instanceof CryptoPermission))
return;
CryptoPermission cryptoPerm = (CryptoPermission)permission;
PermissionCollection pc =
getPermissionCollection(cryptoPerm);
pc.add(cryptoPerm);
String alg = cryptoPerm.getAlgorithm();
perms.putIfAbsent(alg, pc);
}
/**
* Checks if this object's PermissionCollection for permissons
* of the specified permission's algorithm implies the specified
* permission. Returns true if the checking succeeded.
*
* @param permission the Permission object to check.
*
* @return true if "permission" is implied by the permissions
* in the PermissionCollection it belongs to, false if not.
*
*/
public boolean implies(Permission permission) {
if (!(permission instanceof CryptoPermission)) {
return false;
}
CryptoPermission cryptoPerm = (CryptoPermission)permission;
PermissionCollection pc =
getPermissionCollection(cryptoPerm.getAlgorithm());
return pc.implies(cryptoPerm);
}
/**
* Returns an enumeration of all the Permission objects in all the
* PermissionCollections in this CryptoPermissions object.
*
* @return an enumeration of all the Permissions.
*/
public Enumeration<Permission> elements() {
// go through each Permissions in the hash table
// and call their elements() function.
return new PermissionsEnumerator(perms.elements());
}
/**
* Returns a CryptoPermissions object which
* represents the minimum of the specified
* CryptoPermissions object and this
* CryptoPermissions object.
*
* @param other the CryptoPermission
* object to compare with this object.
*/
CryptoPermissions getMinimum(CryptoPermissions other) {
if (other == null) {
return null;
}
if (this.perms.containsKey(CryptoAllPermission.ALG_NAME)) {
return other;
}
if (other.perms.containsKey(CryptoAllPermission.ALG_NAME)) {
return this;
}
CryptoPermissions ret = new CryptoPermissions();
PermissionCollection thatWildcard =
other.perms.get(CryptoPermission.ALG_NAME_WILDCARD);
int maxKeySize = 0;
if (thatWildcard != null) {
maxKeySize = ((CryptoPermission)
thatWildcard.elements().nextElement()).getMaxKeySize();
}
// For each algorithm in this CryptoPermissions,
// find out if there is anything we should add into
// ret.
Enumeration<String> thisKeys = this.perms.keys();
while (thisKeys.hasMoreElements()) {
String alg = thisKeys.nextElement();
PermissionCollection thisPc = this.perms.get(alg);
PermissionCollection thatPc = other.perms.get(alg);
CryptoPermission[] partialResult;
if (thatPc == null) {
if (thatWildcard == null) {
// The other CryptoPermissions
// doesn't allow this given
// algorithm at all. Just skip this
// algorithm.
continue;
}
partialResult = getMinimum(maxKeySize, thisPc);
} else {
partialResult = getMinimum(thisPc, thatPc);
}
for (int i = 0; i < partialResult.length; i++) {
ret.add(partialResult[i]);
}
}
PermissionCollection thisWildcard =
this.perms.get(CryptoPermission.ALG_NAME_WILDCARD);
// If this CryptoPermissions doesn't
// have a wildcard, we are done.
if (thisWildcard == null) {
return ret;
}
// Deal with the algorithms only appear
// in the other CryptoPermissions.
maxKeySize =
((CryptoPermission)
thisWildcard.elements().nextElement()).getMaxKeySize();
Enumeration<String> thatKeys = other.perms.keys();
while (thatKeys.hasMoreElements()) {
String alg = thatKeys.nextElement();
if (this.perms.containsKey(alg)) {
continue;
}
PermissionCollection thatPc = other.perms.get(alg);
CryptoPermission[] partialResult;
partialResult = getMinimum(maxKeySize, thatPc);
for (int i = 0; i < partialResult.length; i++) {
ret.add(partialResult[i]);
}
}
return ret;
}
/**
* Get the minimum of the two given PermissionCollection
* <code>thisPc</code> and <code>thatPc</code>.
*
* @param thisPc the first given PermissionColloection
* object.
*
* @param thatPc the second given PermissionCollection
* object.
*/
private CryptoPermission[] getMinimum(PermissionCollection thisPc,
PermissionCollection thatPc) {
Vector<CryptoPermission> permVector = new Vector<>(2);
Enumeration<Permission> thisPcPermissions = thisPc.elements();
// For each CryptoPermission in
// thisPc object, do the following:
// 1) if this CryptoPermission is implied
// by thatPc, this CryptoPermission
// should be returned, and we can
// move on to check the next
// CryptoPermission in thisPc.
// 2) otherwise, we should return
// all CryptoPermissions in thatPc
// which
// are implied by this CryptoPermission.
// Then we can move on to the
// next CryptoPermission in thisPc.
while (thisPcPermissions.hasMoreElements()) {
CryptoPermission thisCp =
(CryptoPermission)thisPcPermissions.nextElement();
Enumeration<Permission> thatPcPermissions = thatPc.elements();
while (thatPcPermissions.hasMoreElements()) {
CryptoPermission thatCp =
(CryptoPermission)thatPcPermissions.nextElement();
if (thatCp.implies(thisCp)) {
permVector.addElement(thisCp);
break;
}
if (thisCp.implies(thatCp)) {
permVector.addElement(thatCp);
}
}
}
CryptoPermission[] ret = new CryptoPermission[permVector.size()];
permVector.copyInto(ret);
return ret;
}
/**
* Returns all the CryptoPermission objects in the given
* PermissionCollection object
* whose maximum keysize no greater than <code>maxKeySize</code>.
* For all CryptoPermission objects with a maximum keysize greater
* than <code>maxKeySize</code>, this method constructs a
* corresponding CryptoPermission object whose maximum keysize is
* set to <code>maxKeySize</code>, and includes that in the result.
*
* @param maxKeySize the given maximum key size.
*
* @param pc the given PermissionCollection object.
*/
private CryptoPermission[] getMinimum(int maxKeySize,
PermissionCollection pc) {
Vector<CryptoPermission> permVector = new Vector<>(1);
Enumeration<Permission> enum_ = pc.elements();
while (enum_.hasMoreElements()) {
CryptoPermission cp =
(CryptoPermission)enum_.nextElement();
if (cp.getMaxKeySize() <= maxKeySize) {
permVector.addElement(cp);
} else {
if (cp.getCheckParam()) {
permVector.addElement(
new CryptoPermission(cp.getAlgorithm(),
maxKeySize,
cp.getAlgorithmParameterSpec(),
cp.getExemptionMechanism()));
} else {
permVector.addElement(
new CryptoPermission(cp.getAlgorithm(),
maxKeySize,
cp.getExemptionMechanism()));
}
}
}
CryptoPermission[] ret = new CryptoPermission[permVector.size()];
permVector.copyInto(ret);
return ret;
}
/**
* Returns the PermissionCollection for the
* specified algorithm. Returns null if there
* isn't such a PermissionCollection.
*
* @param alg the algorithm name.
*/
PermissionCollection getPermissionCollection(String alg) {
// If this CryptoPermissions includes CryptoAllPermission,
// we should return CryptoAllPermission.
PermissionCollection pc = perms.get(CryptoAllPermission.ALG_NAME);
if (pc == null) {
pc = perms.get(alg);
// If there isn't a PermissionCollection for
// the given algorithm,we should return the
// PermissionCollection for the wildcard
// if there is one.
if (pc == null) {
pc = perms.get(CryptoPermission.ALG_NAME_WILDCARD);
}
}
return pc;
}
/**
* Returns the PermissionCollection for the algorithm
* associated with the specified CryptoPermission
* object. Creates such a PermissionCollection
* if such a PermissionCollection does not
* exist yet.
*
* @param cryptoPerm the CryptoPermission object.
*/
private PermissionCollection getPermissionCollection(
CryptoPermission cryptoPerm) {
String alg = cryptoPerm.getAlgorithm();
PermissionCollection pc = perms.get(alg);
if (pc == null) {
pc = cryptoPerm.newPermissionCollection();
}
return pc;
}
private void readObject(ObjectInputStream s)
throws IOException, ClassNotFoundException {
ObjectInputStream.GetField fields = s.readFields();
@SuppressWarnings("unchecked")
Hashtable<String,PermissionCollection> permTable =
(Hashtable<String,PermissionCollection>)
(fields.get("perms", null));
if (permTable != null) {
perms = new ConcurrentHashMap<>(permTable);
} else {
perms = new ConcurrentHashMap<>();
}
}
private void writeObject(ObjectOutputStream s) throws IOException {
Hashtable<String,PermissionCollection> permTable =
new Hashtable<>(perms);
ObjectOutputStream.PutField fields = s.putFields();
fields.put("perms", permTable);
s.writeFields();
}
}
final class PermissionsEnumerator implements Enumeration<Permission> {
// all the perms
private Enumeration<PermissionCollection> perms;
// the current set
private Enumeration<Permission> permset;
PermissionsEnumerator(Enumeration<PermissionCollection> e) {
perms = e;
permset = getNextEnumWithMore();
}
public synchronized boolean hasMoreElements() {
// if we enter with permissionimpl null, we know
// there are no more left.
if (permset == null)
return false;
// try to see if there are any left in the current one
if (permset.hasMoreElements())
return true;
// get the next one that has something in it...
permset = getNextEnumWithMore();
// if it is null, we are done!
return (permset != null);
}
public synchronized Permission nextElement() {
// hasMoreElements will update permset to the next permset
// with something in it...
if (hasMoreElements()) {
return permset.nextElement();
} else {
throw new NoSuchElementException("PermissionsEnumerator");
}
}
private Enumeration<Permission> getNextEnumWithMore() {
while (perms.hasMoreElements()) {
PermissionCollection pc = perms.nextElement();
Enumeration<Permission> next = pc.elements();
if (next.hasMoreElements())
return next;
}
return null;
}
}

View File

@@ -0,0 +1,706 @@
/*
* Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.crypto;
import java.io.*;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;
import static java.util.Locale.ENGLISH;
import java.security.GeneralSecurityException;
import java.security.spec.AlgorithmParameterSpec;
import java.lang.reflect.*;
/**
* JCE has two pairs of jurisdiction policy files: one represents U.S. export
* laws, and the other represents the local laws of the country where the
* JCE will be used.
*
* The jurisdiction policy file has the same syntax as JDK policy files except
* that JCE has new permission classes called javax.crypto.CryptoPermission
* and javax.crypto.CryptoAllPermission.
*
* The format of a permission entry in the jurisdiction policy file is:
*
* permission <crypto permission class name>[, <algorithm name>
* [[, <exemption mechanism name>][, <maxKeySize>
* [, <AlgrithomParameterSpec class name>, <parameters
* for constructing an AlgrithomParameterSpec object>]]]];
*
* @author Sharon Liu
*
* @see java.security.Permissions
* @see java.security.spec.AlgorithmParameterSpec
* @see javax.crypto.CryptoPermission
* @see javax.crypto.CryptoAllPermission
* @see javax.crypto.CryptoPermissions
* @since 1.4
*/
final class CryptoPolicyParser {
private Vector<GrantEntry> grantEntries;
// Convenience variables for parsing
private StreamTokenizer st;
private int lookahead;
/**
* Creates a CryptoPolicyParser object.
*/
CryptoPolicyParser() {
grantEntries = new Vector<GrantEntry>();
}
/**
* Reads a policy configuration using a Reader object. <p>
*
* @param policy the policy Reader object.
*
* @exception ParsingException if the policy configuration
* contains a syntax error.
*
* @exception IOException if an error occurs while reading
* the policy configuration.
*/
void read(Reader policy)
throws ParsingException, IOException
{
if (!(policy instanceof BufferedReader)) {
policy = new BufferedReader(policy);
}
/*
* Configure the stream tokenizer:
* Recognize strings between "..."
* Don't convert words to lowercase
* Recognize both C-style and C++-style comments
* Treat end-of-line as white space, not as a token
*/
st = new StreamTokenizer(policy);
st.resetSyntax();
st.wordChars('a', 'z');
st.wordChars('A', 'Z');
st.wordChars('.', '.');
st.wordChars('0', '9');
st.wordChars('_', '_');
st.wordChars('$', '$');
st.wordChars(128 + 32, 255);
st.whitespaceChars(0, ' ');
st.commentChar('/');
st.quoteChar('\'');
st.quoteChar('"');
st.lowerCaseMode(false);
st.ordinaryChar('/');
st.slashSlashComments(true);
st.slashStarComments(true);
st.parseNumbers();
/*
* The crypto jurisdiction policy must be consistent. The
* following hashtable is used for checking consistency.
*/
Hashtable<String, Vector<String>> processedPermissions = null;
/*
* The main parsing loop. The loop is executed once for each entry
* in the policy file. The entries are delimited by semicolons. Once
* we've read in the information for an entry, go ahead and try to
* add it to the grantEntries.
*/
lookahead = st.nextToken();
while (lookahead != StreamTokenizer.TT_EOF) {
if (peek("grant")) {
GrantEntry ge = parseGrantEntry(processedPermissions);
if (ge != null)
grantEntries.addElement(ge);
} else {
throw new ParsingException(st.lineno(), "expected grant " +
"statement");
}
match(";");
}
}
/**
* parse a Grant entry
*/
private GrantEntry parseGrantEntry(
Hashtable<String, Vector<String>> processedPermissions)
throws ParsingException, IOException
{
GrantEntry e = new GrantEntry();
match("grant");
match("{");
while(!peek("}")) {
if (peek("Permission")) {
CryptoPermissionEntry pe =
parsePermissionEntry(processedPermissions);
e.add(pe);
match(";");
} else {
throw new
ParsingException(st.lineno(), "expected permission entry");
}
}
match("}");
return e;
}
/**
* parse a CryptoPermission entry
*/
private CryptoPermissionEntry parsePermissionEntry(
Hashtable<String, Vector<String>> processedPermissions)
throws ParsingException, IOException
{
CryptoPermissionEntry e = new CryptoPermissionEntry();
match("Permission");
e.cryptoPermission = match("permission type");
if (e.cryptoPermission.equals("javax.crypto.CryptoAllPermission")) {
// Done with the CryptoAllPermission entry.
e.alg = CryptoAllPermission.ALG_NAME;
e.maxKeySize = Integer.MAX_VALUE;
return e;
}
// Should see the algorithm name.
if (peek("\"")) {
// Algorithm name - always convert to upper case after parsing.
e.alg = match("quoted string").toUpperCase(ENGLISH);
} else {
// The algorithm name can be a wildcard.
if (peek("*")) {
match("*");
e.alg = CryptoPermission.ALG_NAME_WILDCARD;
} else {
throw new ParsingException(st.lineno(),
"Missing the algorithm name");
}
}
peekAndMatch(",");
// May see the exemption mechanism name.
if (peek("\"")) {
// Exemption mechanism name - convert to upper case too.
e.exemptionMechanism = match("quoted string").toUpperCase(ENGLISH);
}
peekAndMatch(",");
// Check whether this entry is consistent with other permission entries
// that have been read.
if (!isConsistent(e.alg, e.exemptionMechanism, processedPermissions)) {
throw new ParsingException(st.lineno(), "Inconsistent policy");
}
// Should see the maxKeySize if not at the end of this entry yet.
if (peek("number")) {
e.maxKeySize = match();
} else {
if (peek("*")) {
match("*");
e.maxKeySize = Integer.MAX_VALUE;
} else {
if (!peek(";")) {
throw new ParsingException(st.lineno(),
"Missing the maximum " +
"allowable key size");
} else {
// At the end of this permission entry
e.maxKeySize = Integer.MAX_VALUE;
}
}
}
peekAndMatch(",");
// May see an AlgorithmParameterSpec class name.
if (peek("\"")) {
// AlgorithmParameterSpec class name.
String algParamSpecClassName = match("quoted string");
Vector<Integer> paramsV = new Vector<>(1);
while (peek(",")) {
match(",");
if (peek("number")) {
paramsV.addElement(new Integer(match()));
} else {
if (peek("*")) {
match("*");
paramsV.addElement(new Integer(Integer.MAX_VALUE));
} else {
throw new ParsingException(st.lineno(),
"Expecting an integer");
}
}
}
Integer[] params = new Integer[paramsV.size()];
paramsV.copyInto(params);
e.checkParam = true;
e.algParamSpec = getInstance(algParamSpecClassName, params);
}
return e;
}
private static final AlgorithmParameterSpec getInstance(String type,
Integer[] params)
throws ParsingException
{
AlgorithmParameterSpec ret = null;
try {
Class<?> apsClass = Class.forName(type);
Class<?>[] paramClasses = new Class<?>[params.length];
for (int i = 0; i < params.length; i++) {
paramClasses[i] = int.class;
}
Constructor<?> c = apsClass.getConstructor(paramClasses);
ret = (AlgorithmParameterSpec) c.newInstance((Object[]) params);
} catch (Exception e) {
throw new ParsingException("Cannot call the constructor of " +
type + e);
}
return ret;
}
private boolean peekAndMatch(String expect)
throws ParsingException, IOException
{
if (peek(expect)) {
match(expect);
return true;
}
return false;
}
private boolean peek(String expect) {
boolean found = false;
switch (lookahead) {
case StreamTokenizer.TT_WORD:
if (expect.equalsIgnoreCase(st.sval))
found = true;
break;
case StreamTokenizer.TT_NUMBER:
if (expect.equalsIgnoreCase("number")) {
found = true;
}
break;
case ',':
if (expect.equals(","))
found = true;
break;
case '{':
if (expect.equals("{"))
found = true;
break;
case '}':
if (expect.equals("}"))
found = true;
break;
case '"':
if (expect.equals("\""))
found = true;
break;
case '*':
if (expect.equals("*"))
found = true;
break;
case ';':
if (expect.equals(";"))
found = true;
break;
default:
break;
}
return found;
}
/**
* Excepts to match a non-negative number.
*/
private int match()
throws ParsingException, IOException
{
int value = -1;
int lineno = st.lineno();
String sValue = null;
switch (lookahead) {
case StreamTokenizer.TT_NUMBER:
value = (int)st.nval;
if (value < 0) {
sValue = String.valueOf(st.nval);
}
lookahead = st.nextToken();
break;
default:
sValue = st.sval;
break;
}
if (value <= 0) {
throw new ParsingException(lineno, "a non-negative number",
sValue);
}
return value;
}
private String match(String expect)
throws ParsingException, IOException
{
String value = null;
switch (lookahead) {
case StreamTokenizer.TT_NUMBER:
throw new ParsingException(st.lineno(), expect,
"number "+String.valueOf(st.nval));
case StreamTokenizer.TT_EOF:
throw new ParsingException("expected "+expect+", read end of file");
case StreamTokenizer.TT_WORD:
if (expect.equalsIgnoreCase(st.sval)) {
lookahead = st.nextToken();
}
else if (expect.equalsIgnoreCase("permission type")) {
value = st.sval;
lookahead = st.nextToken();
}
else
throw new ParsingException(st.lineno(), expect, st.sval);
break;
case '"':
if (expect.equalsIgnoreCase("quoted string")) {
value = st.sval;
lookahead = st.nextToken();
} else if (expect.equalsIgnoreCase("permission type")) {
value = st.sval;
lookahead = st.nextToken();
}
else
throw new ParsingException(st.lineno(), expect, st.sval);
break;
case ',':
if (expect.equals(","))
lookahead = st.nextToken();
else
throw new ParsingException(st.lineno(), expect, ",");
break;
case '{':
if (expect.equals("{"))
lookahead = st.nextToken();
else
throw new ParsingException(st.lineno(), expect, "{");
break;
case '}':
if (expect.equals("}"))
lookahead = st.nextToken();
else
throw new ParsingException(st.lineno(), expect, "}");
break;
case ';':
if (expect.equals(";"))
lookahead = st.nextToken();
else
throw new ParsingException(st.lineno(), expect, ";");
break;
case '*':
if (expect.equals("*"))
lookahead = st.nextToken();
else
throw new ParsingException(st.lineno(), expect, "*");
break;
default:
throw new ParsingException(st.lineno(), expect,
new String(new char[] {(char)lookahead}));
}
return value;
}
CryptoPermission[] getPermissions() {
Vector<CryptoPermission> result = new Vector<>();
Enumeration<GrantEntry> grantEnum = grantEntries.elements();
while (grantEnum.hasMoreElements()) {
GrantEntry ge = grantEnum.nextElement();
Enumeration<CryptoPermissionEntry> permEnum =
ge.permissionElements();
while (permEnum.hasMoreElements()) {
CryptoPermissionEntry pe = permEnum.nextElement();
if (pe.cryptoPermission.equals(
"javax.crypto.CryptoAllPermission")) {
result.addElement(CryptoAllPermission.INSTANCE);
} else {
if (pe.checkParam) {
result.addElement(new CryptoPermission(
pe.alg,
pe.maxKeySize,
pe.algParamSpec,
pe.exemptionMechanism));
} else {
result.addElement(new CryptoPermission(
pe.alg,
pe.maxKeySize,
pe.exemptionMechanism));
}
}
}
}
CryptoPermission[] ret = new CryptoPermission[result.size()];
result.copyInto(ret);
return ret;
}
private boolean isConsistent(String alg, String exemptionMechanism,
Hashtable<String, Vector<String>> processedPermissions) {
String thisExemptionMechanism =
exemptionMechanism == null ? "none" : exemptionMechanism;
if (processedPermissions == null) {
processedPermissions = new Hashtable<String, Vector<String>>();
Vector<String> exemptionMechanisms = new Vector<>(1);
exemptionMechanisms.addElement(thisExemptionMechanism);
processedPermissions.put(alg, exemptionMechanisms);
return true;
}
if (processedPermissions.containsKey(CryptoAllPermission.ALG_NAME)) {
return false;
}
Vector<String> exemptionMechanisms;
if (processedPermissions.containsKey(alg)) {
exemptionMechanisms = processedPermissions.get(alg);
if (exemptionMechanisms.contains(thisExemptionMechanism)) {
return false;
}
} else {
exemptionMechanisms = new Vector<String>(1);
}
exemptionMechanisms.addElement(thisExemptionMechanism);
processedPermissions.put(alg, exemptionMechanisms);
return true;
}
/**
* Each grant entry in the policy configuration file is represented by a
* GrantEntry object. <p>
*
* <p>
* For example, the entry
* <pre>
* grant {
* permission javax.crypto.CryptoPermission "DES", 56;
* };
*
* </pre>
* is represented internally
* <pre>
*
* pe = new CryptoPermissionEntry("javax.crypto.CryptoPermission",
* "DES", 56);
*
* ge = new GrantEntry();
*
* ge.add(pe);
*
* </pre>
*
* @see java.security.Permission
* @see javax.crypto.CryptoPermission
* @see javax.crypto.CryptoPermissions
*/
private static class GrantEntry {
private Vector<CryptoPermissionEntry> permissionEntries;
GrantEntry() {
permissionEntries = new Vector<CryptoPermissionEntry>();
}
void add(CryptoPermissionEntry pe)
{
permissionEntries.addElement(pe);
}
boolean remove(CryptoPermissionEntry pe)
{
return permissionEntries.removeElement(pe);
}
boolean contains(CryptoPermissionEntry pe)
{
return permissionEntries.contains(pe);
}
/**
* Enumerate all the permission entries in this GrantEntry.
*/
Enumeration<CryptoPermissionEntry> permissionElements(){
return permissionEntries.elements();
}
}
/**
* Each crypto permission entry in the policy configuration file is
* represented by a CryptoPermissionEntry object. <p>
*
* <p>
* For example, the entry
* <pre>
* permission javax.crypto.CryptoPermission "DES", 56;
* </pre>
* is represented internally
* <pre>
*
* pe = new CryptoPermissionEntry("javax.crypto.cryptoPermission",
* "DES", 56);
* </pre>
*
* @see java.security.Permissions
* @see javax.crypto.CryptoPermission
* @see javax.crypto.CryptoAllPermission
*/
private static class CryptoPermissionEntry {
String cryptoPermission;
String alg;
String exemptionMechanism;
int maxKeySize;
boolean checkParam;
AlgorithmParameterSpec algParamSpec;
CryptoPermissionEntry() {
// Set default values.
maxKeySize = 0;
alg = null;
exemptionMechanism = null;
checkParam = false;
algParamSpec = null;
}
/**
* Calculates a hash code value for the object. Objects
* which are equal will also have the same hashcode.
*/
public int hashCode() {
int retval = cryptoPermission.hashCode();
if (alg != null) retval ^= alg.hashCode();
if (exemptionMechanism != null) {
retval ^= exemptionMechanism.hashCode();
}
retval ^= maxKeySize;
if (checkParam) retval ^= 100;
if (algParamSpec != null) {
retval ^= algParamSpec.hashCode();
}
return retval;
}
public boolean equals(Object obj) {
if (obj == this)
return true;
if (!(obj instanceof CryptoPermissionEntry))
return false;
CryptoPermissionEntry that = (CryptoPermissionEntry) obj;
if (this.cryptoPermission == null) {
if (that.cryptoPermission != null) return false;
} else {
if (!this.cryptoPermission.equals(
that.cryptoPermission))
return false;
}
if (this.alg == null) {
if (that.alg != null) return false;
} else {
if (!this.alg.equalsIgnoreCase(that.alg))
return false;
}
if (!(this.maxKeySize == that.maxKeySize)) return false;
if (this.checkParam != that.checkParam) return false;
if (this.algParamSpec == null) {
if (that.algParamSpec != null) return false;
} else {
if (!this.algParamSpec.equals(that.algParamSpec))
return false;
}
// everything matched -- the 2 objects are equal
return true;
}
}
static final class ParsingException extends GeneralSecurityException {
private static final long serialVersionUID = 7147241245566588374L;
/**
* Constructs a ParsingException with the specified
* detail message.
* @param msg the detail message.
*/
ParsingException(String msg) {
super(msg);
}
ParsingException(int line, String msg) {
super("line " + line + ": " + msg);
}
ParsingException(int line, String expect, String actual) {
super("line "+line+": expected '"+expect+"', found '"+actual+"'");
}
}
}

View File

@@ -0,0 +1,433 @@
/*
* Copyright (c) 2001, 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact 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.crypto;
import java.io.*;
import java.security.*;
import java.security.spec.*;
import sun.security.x509.AlgorithmId;
import sun.security.util.DerValue;
import sun.security.util.DerInputStream;
import sun.security.util.DerOutputStream;
/**
* This class implements the <code>EncryptedPrivateKeyInfo</code> type
* as defined in PKCS #8.
* <p>Its ASN.1 definition is as follows:
*
* <pre>
* EncryptedPrivateKeyInfo ::= SEQUENCE {
* encryptionAlgorithm AlgorithmIdentifier,
* encryptedData OCTET STRING }
*
* AlgorithmIdentifier ::= SEQUENCE {
* algorithm OBJECT IDENTIFIER,
* parameters ANY DEFINED BY algorithm OPTIONAL }
* </pre>
*
* @author Valerie Peng
*
* @see java.security.spec.PKCS8EncodedKeySpec
*
* @since 1.4
*/
public class EncryptedPrivateKeyInfo {
// the "encryptionAlgorithm" field
private AlgorithmId algid;
// the "encryptedData" field
private byte[] encryptedData;
// the ASN.1 encoded contents of this class
private byte[] encoded = null;
/**
* Constructs (i.e., parses) an <code>EncryptedPrivateKeyInfo</code> from
* its ASN.1 encoding.
* @param encoded the ASN.1 encoding of this object. The contents of
* the array are copied to protect against subsequent modification.
* @exception NullPointerException if the <code>encoded</code> is null.
* @exception IOException if error occurs when parsing the ASN.1 encoding.
*/
public EncryptedPrivateKeyInfo(byte[] encoded) throws IOException {
if (encoded == null) {
throw new NullPointerException("the encoded parameter " +
"must be non-null");
}
this.encoded = encoded.clone();
DerValue val = DerValue.wrap(this.encoded);
if (val.tag != DerValue.tag_Sequence) {
throw new IOException("DER header error: no SEQ tag");
}
DerValue[] seq = new DerValue[2];
seq[0] = val.data.getDerValue();
seq[1] = val.data.getDerValue();
if (val.data.available() != 0) {
throw new IOException("overrun, bytes = " + val.data.available());
}
this.algid = AlgorithmId.parse(seq[0]);
if (seq[0].data.available() != 0) {
throw new IOException("encryptionAlgorithm field overrun");
}
this.encryptedData = seq[1].getOctetString();
if (seq[1].data.available() != 0) {
throw new IOException("encryptedData field overrun");
}
}
/**
* Constructs an <code>EncryptedPrivateKeyInfo</code> from the
* encryption algorithm name and the encrypted data.
*
* <p>Note: This constructor will use null as the value of the
* algorithm parameters. If the encryption algorithm has
* parameters whose value is not null, a different constructor,
* e.g. EncryptedPrivateKeyInfo(AlgorithmParameters, byte[]),
* should be used.
*
* @param algName encryption algorithm name. See Appendix A in the
* <a href=
* "{@docRoot}/../technotes/guides/security/crypto/CryptoSpec.html#AppA">
* Java Cryptography Architecture Reference Guide</a>
* for information about standard Cipher algorithm names.
* @param encryptedData encrypted data. The contents of
* <code>encrypedData</code> are copied to protect against subsequent
* modification when constructing this object.
* @exception NullPointerException if <code>algName</code> or
* <code>encryptedData</code> is null.
* @exception IllegalArgumentException if <code>encryptedData</code>
* is empty, i.e. 0-length.
* @exception NoSuchAlgorithmException if the specified algName is
* not supported.
*/
public EncryptedPrivateKeyInfo(String algName, byte[] encryptedData)
throws NoSuchAlgorithmException {
if (algName == null)
throw new NullPointerException("the algName parameter " +
"must be non-null");
this.algid = AlgorithmId.get(algName);
if (encryptedData == null) {
throw new NullPointerException("the encryptedData " +
"parameter must be non-null");
} else if (encryptedData.length == 0) {
throw new IllegalArgumentException("the encryptedData " +
"parameter must not be empty");
} else {
this.encryptedData = encryptedData.clone();
}
// delay the generation of ASN.1 encoding until
// getEncoded() is called
this.encoded = null;
}
/**
* Constructs an <code>EncryptedPrivateKeyInfo</code> from the
* encryption algorithm parameters and the encrypted data.
*
* @param algParams the algorithm parameters for the encryption
* algorithm. <code>algParams.getEncoded()</code> should return
* the ASN.1 encoded bytes of the <code>parameters</code> field
* of the <code>AlgorithmIdentifer</code> component of the
* <code>EncryptedPrivateKeyInfo</code> type.
* @param encryptedData encrypted data. The contents of
* <code>encrypedData</code> are copied to protect against
* subsequent modification when constructing this object.
* @exception NullPointerException if <code>algParams</code> or
* <code>encryptedData</code> is null.
* @exception IllegalArgumentException if <code>encryptedData</code>
* is empty, i.e. 0-length.
* @exception NoSuchAlgorithmException if the specified algName of
* the specified <code>algParams</code> parameter is not supported.
*/
public EncryptedPrivateKeyInfo(AlgorithmParameters algParams,
byte[] encryptedData) throws NoSuchAlgorithmException {
if (algParams == null) {
throw new NullPointerException("algParams must be non-null");
}
this.algid = AlgorithmId.get(algParams);
if (encryptedData == null) {
throw new NullPointerException("encryptedData must be non-null");
} else if (encryptedData.length == 0) {
throw new IllegalArgumentException("the encryptedData " +
"parameter must not be empty");
} else {
this.encryptedData = encryptedData.clone();
}
// delay the generation of ASN.1 encoding until
// getEncoded() is called
this.encoded = null;
}
/**
* Returns the encryption algorithm.
* <p>Note: Standard name is returned instead of the specified one
* in the constructor when such mapping is available.
* See Appendix A in the
* <a href=
* "{@docRoot}/../technotes/guides/security/crypto/CryptoSpec.html#AppA">
* Java Cryptography Architecture Reference Guide</a>
* for information about standard Cipher algorithm names.
*
* @return the encryption algorithm name.
*/
public String getAlgName() {
return this.algid.getName();
}
/**
* Returns the algorithm parameters used by the encryption algorithm.
* @return the algorithm parameters.
*/
public AlgorithmParameters getAlgParameters() {
return this.algid.getParameters();
}
/**
* Returns the encrypted data.
* @return the encrypted data. Returns a new array
* each time this method is called.
*/
public byte[] getEncryptedData() {
return this.encryptedData.clone();
}
/**
* Extract the enclosed PKCS8EncodedKeySpec object from the
* encrypted data and return it.
* <br>Note: In order to successfully retrieve the enclosed
* PKCS8EncodedKeySpec object, <code>cipher</code> needs
* to be initialized to either Cipher.DECRYPT_MODE or
* Cipher.UNWRAP_MODE, with the same key and parameters used
* for generating the encrypted data.
*
* @param cipher the initialized cipher object which will be
* used for decrypting the encrypted data.
* @return the PKCS8EncodedKeySpec object.
* @exception NullPointerException if <code>cipher</code>
* is null.
* @exception InvalidKeySpecException if the given cipher is
* inappropriate for the encrypted data or the encrypted
* data is corrupted and cannot be decrypted.
*/
public PKCS8EncodedKeySpec getKeySpec(Cipher cipher)
throws InvalidKeySpecException {
byte[] encoded = null;
try {
encoded = cipher.doFinal(encryptedData);
checkPKCS8Encoding(encoded);
} catch (GeneralSecurityException |
IOException |
IllegalStateException ex) {
throw new InvalidKeySpecException(
"Cannot retrieve the PKCS8EncodedKeySpec", ex);
}
return new PKCS8EncodedKeySpec(encoded);
}
private PKCS8EncodedKeySpec getKeySpecImpl(Key decryptKey,
Provider provider) throws NoSuchAlgorithmException,
InvalidKeyException {
byte[] encoded = null;
Cipher c;
try {
if (provider == null) {
// use the most preferred one
c = Cipher.getInstance(algid.getName());
} else {
c = Cipher.getInstance(algid.getName(), provider);
}
c.init(Cipher.DECRYPT_MODE, decryptKey, algid.getParameters());
encoded = c.doFinal(encryptedData);
checkPKCS8Encoding(encoded);
} catch (NoSuchAlgorithmException nsae) {
// rethrow
throw nsae;
} catch (GeneralSecurityException | IOException ex) {
throw new InvalidKeyException(
"Cannot retrieve the PKCS8EncodedKeySpec", ex);
}
return new PKCS8EncodedKeySpec(encoded);
}
/**
* Extract the enclosed PKCS8EncodedKeySpec object from the
* encrypted data and return it.
* @param decryptKey key used for decrypting the encrypted data.
* @return the PKCS8EncodedKeySpec object.
* @exception NullPointerException if <code>decryptKey</code>
* is null.
* @exception NoSuchAlgorithmException if cannot find appropriate
* cipher to decrypt the encrypted data.
* @exception InvalidKeyException if <code>decryptKey</code>
* cannot be used to decrypt the encrypted data or the decryption
* result is not a valid PKCS8KeySpec.
*
* @since 1.5
*/
public PKCS8EncodedKeySpec getKeySpec(Key decryptKey)
throws NoSuchAlgorithmException, InvalidKeyException {
if (decryptKey == null) {
throw new NullPointerException("decryptKey is null");
}
return getKeySpecImpl(decryptKey, null);
}
/**
* Extract the enclosed PKCS8EncodedKeySpec object from the
* encrypted data and return it.
* @param decryptKey key used for decrypting the encrypted data.
* @param providerName the name of provider whose Cipher
* implementation will be used.
* @return the PKCS8EncodedKeySpec object.
* @exception NullPointerException if <code>decryptKey</code>
* or <code>providerName</code> is null.
* @exception NoSuchProviderException if no provider
* <code>providerName</code> is registered.
* @exception NoSuchAlgorithmException if cannot find appropriate
* cipher to decrypt the encrypted data.
* @exception InvalidKeyException if <code>decryptKey</code>
* cannot be used to decrypt the encrypted data or the decryption
* result is not a valid PKCS8KeySpec.
*
* @since 1.5
*/
public PKCS8EncodedKeySpec getKeySpec(Key decryptKey,
String providerName) throws NoSuchProviderException,
NoSuchAlgorithmException, InvalidKeyException {
if (decryptKey == null) {
throw new NullPointerException("decryptKey is null");
}
if (providerName == null) {
throw new NullPointerException("provider is null");
}
Provider provider = Security.getProvider(providerName);
if (provider == null) {
throw new NoSuchProviderException("provider " +
providerName + " not found");
}
return getKeySpecImpl(decryptKey, provider);
}
/**
* Extract the enclosed PKCS8EncodedKeySpec object from the
* encrypted data and return it.
* @param decryptKey key used for decrypting the encrypted data.
* @param provider the name of provider whose Cipher implementation
* will be used.
* @return the PKCS8EncodedKeySpec object.
* @exception NullPointerException if <code>decryptKey</code>
* or <code>provider</code> is null.
* @exception NoSuchAlgorithmException if cannot find appropriate
* cipher to decrypt the encrypted data in <code>provider</code>.
* @exception InvalidKeyException if <code>decryptKey</code>
* cannot be used to decrypt the encrypted data or the decryption
* result is not a valid PKCS8KeySpec.
*
* @since 1.5
*/
public PKCS8EncodedKeySpec getKeySpec(Key decryptKey,
Provider provider) throws NoSuchAlgorithmException,
InvalidKeyException {
if (decryptKey == null) {
throw new NullPointerException("decryptKey is null");
}
if (provider == null) {
throw new NullPointerException("provider is null");
}
return getKeySpecImpl(decryptKey, provider);
}
/**
* Returns the ASN.1 encoding of this object.
* @return the ASN.1 encoding. Returns a new array
* each time this method is called.
* @exception IOException if error occurs when constructing its
* ASN.1 encoding.
*/
public byte[] getEncoded() throws IOException {
if (this.encoded == null) {
DerOutputStream out = new DerOutputStream();
DerOutputStream tmp = new DerOutputStream();
// encode encryption algorithm
algid.encode(tmp);
// encode encrypted data
tmp.putOctetString(encryptedData);
// wrap everything into a SEQUENCE
out.write(DerValue.tag_Sequence, tmp);
this.encoded = out.toByteArray();
}
return this.encoded.clone();
}
private static void checkTag(DerValue val, byte tag, String valName)
throws IOException {
if (val.getTag() != tag) {
throw new IOException("invalid key encoding - wrong tag for " +
valName);
}
}
@SuppressWarnings("fallthrough")
private static void checkPKCS8Encoding(byte[] encodedKey)
throws IOException {
DerInputStream in = new DerInputStream(encodedKey);
DerValue[] values = in.getSequence(3);
switch (values.length) {
case 4:
checkTag(values[3], DerValue.TAG_CONTEXT, "attributes");
/* fall through */
case 3:
checkTag(values[0], DerValue.tag_Integer, "version");
DerInputStream algid = values[1].toDerInputStream();
algid.getOID();
if (algid.available() != 0) {
algid.getDerValue();
}
checkTag(values[2], DerValue.tag_OctetString, "privateKey");
break;
default:
throw new IOException("invalid key encoding");
}
}
}

View File

@@ -0,0 +1,486 @@
/*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.crypto;
import java.security.AlgorithmParameters;
import java.security.Provider;
import java.security.Key;
import java.security.Security;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.InvalidKeyException;
import java.security.InvalidAlgorithmParameterException;
import java.security.spec.AlgorithmParameterSpec;
import sun.security.jca.GetInstance.Instance;
/**
* This class provides the functionality of an exemption mechanism, examples
* of which are <i>key recovery</i>, <i>key weakening</i>, and
* <i>key escrow</i>.
*
* <p>Applications or applets that use an exemption mechanism may be granted
* stronger encryption capabilities than those which don't.
*
* @since 1.4
*/
public class ExemptionMechanism {
// The provider
private Provider provider;
// The provider implementation (delegate)
private ExemptionMechanismSpi exmechSpi;
// The name of the exemption mechanism.
private String mechanism;
// Flag which indicates whether this ExemptionMechanism
// result is generated successfully.
private boolean done = false;
// State information
private boolean initialized = false;
// Store away the key at init() time for later comparison.
private Key keyStored = null;
/**
* Creates a ExemptionMechanism object.
*
* @param exmechSpi the delegate
* @param provider the provider
* @param mechanism the exemption mechanism
*/
protected ExemptionMechanism(ExemptionMechanismSpi exmechSpi,
Provider provider,
String mechanism) {
this.exmechSpi = exmechSpi;
this.provider = provider;
this.mechanism = mechanism;
}
/**
* Returns the exemption mechanism name of this
* <code>ExemptionMechanism</code> object.
*
* <p>This is the same name that was specified in one of the
* <code>getInstance</code> calls that created this
* <code>ExemptionMechanism</code> object.
*
* @return the exemption mechanism name of this
* <code>ExemptionMechanism</code> object.
*/
public final String getName() {
return this.mechanism;
}
/**
* Returns an <code>ExemptionMechanism</code> object that implements the
* specified exemption mechanism algorithm.
*
* <p> This method traverses the list of registered security Providers,
* starting with the most preferred Provider.
* A new ExemptionMechanism object encapsulating the
* ExemptionMechanismSpi implementation from the first
* Provider that supports the specified algorithm is returned.
*
* <p> Note that the list of registered providers may be retrieved via
* the {@link Security#getProviders() Security.getProviders()} method.
*
* @param algorithm the standard name of the requested exemption
* mechanism.
* See the ExemptionMechanism section in the
* <a href=
* "{@docRoot}/../technotes/guides/security/StandardNames.html#Exemption">
* Java Cryptography Architecture Standard Algorithm Name Documentation</a>
* for information about standard exemption mechanism names.
*
* @return the new <code>ExemptionMechanism</code> object.
*
* @exception NullPointerException if <code>algorithm</code>
* is null.
*
* @exception NoSuchAlgorithmException if no Provider supports an
* ExemptionMechanismSpi implementation for the
* specified algorithm.
*
* @see java.security.Provider
*/
public static final ExemptionMechanism getInstance(String algorithm)
throws NoSuchAlgorithmException {
Instance instance = JceSecurity.getInstance("ExemptionMechanism",
ExemptionMechanismSpi.class, algorithm);
return new ExemptionMechanism((ExemptionMechanismSpi)instance.impl,
instance.provider, algorithm);
}
/**
* Returns an <code>ExemptionMechanism</code> object that implements the
* specified exemption mechanism algorithm.
*
* <p> A new ExemptionMechanism object encapsulating the
* ExemptionMechanismSpi implementation from the specified provider
* is returned. The specified provider must be registered
* in the security provider list.
*
* <p> Note that the list of registered providers may be retrieved via
* the {@link Security#getProviders() Security.getProviders()} method.
* @param algorithm the standard name of the requested exemption mechanism.
* See the ExemptionMechanism section in the
* <a href=
* "{@docRoot}/../technotes/guides/security/StandardNames.html#Exemption">
* Java Cryptography Architecture Standard Algorithm Name Documentation</a>
* for information about standard exemption mechanism names.
*
* @param provider the name of the provider.
*
* @return the new <code>ExemptionMechanism</code> object.
*
* @exception NullPointerException if <code>algorithm</code>
* is null.
*
* @exception NoSuchAlgorithmException if an ExemptionMechanismSpi
* implementation for the specified algorithm is not
* available from the specified provider.
*
* @exception NoSuchProviderException if the specified provider is not
* registered in the security provider list.
*
* @exception IllegalArgumentException if the <code>provider</code>
* is null or empty.
*
* @see java.security.Provider
*/
public static final ExemptionMechanism getInstance(String algorithm,
String provider) throws NoSuchAlgorithmException,
NoSuchProviderException {
Instance instance = JceSecurity.getInstance("ExemptionMechanism",
ExemptionMechanismSpi.class, algorithm, provider);
return new ExemptionMechanism((ExemptionMechanismSpi)instance.impl,
instance.provider, algorithm);
}
/**
* Returns an <code>ExemptionMechanism</code> object that implements the
* specified exemption mechanism algorithm.
*
* <p> A new ExemptionMechanism object encapsulating the
* ExemptionMechanismSpi implementation from the specified Provider
* object is returned. Note that the specified Provider object
* does not have to be registered in the provider list.
*
* @param algorithm the standard name of the requested exemption mechanism.
* See the ExemptionMechanism section in the
* <a href=
* "{@docRoot}/../technotes/guides/security/StandardNames.html#Exemption">
* Java Cryptography Architecture Standard Algorithm Name Documentation</a>
* for information about standard exemption mechanism names.
*
* @param provider the provider.
*
* @return the new <code>ExemptionMechanism</code> object.
*
* @exception NullPointerException if <code>algorithm</code>
* is null.
*
* @exception NoSuchAlgorithmException if an ExemptionMechanismSpi
* implementation for the specified algorithm is not available
* from the specified Provider object.
*
* @exception IllegalArgumentException if the <code>provider</code>
* is null.
*
* @see java.security.Provider
*/
public static final ExemptionMechanism getInstance(String algorithm,
Provider provider) throws NoSuchAlgorithmException {
Instance instance = JceSecurity.getInstance("ExemptionMechanism",
ExemptionMechanismSpi.class, algorithm, provider);
return new ExemptionMechanism((ExemptionMechanismSpi)instance.impl,
instance.provider, algorithm);
}
/**
* Returns the provider of this <code>ExemptionMechanism</code> object.
*
* @return the provider of this <code>ExemptionMechanism</code> object.
*/
public final Provider getProvider() {
return this.provider;
}
/**
* Returns whether the result blob has been generated successfully by this
* exemption mechanism.
*
* <p>The method also makes sure that the key passed in is the same as
* the one this exemption mechanism used in initializing and generating
* phases.
*
* @param key the key the crypto is going to use.
*
* @return whether the result blob of the same key has been generated
* successfully by this exemption mechanism; false if <code>key</code>
* is null.
*
* @exception ExemptionMechanismException if problem(s) encountered
* while determining whether the result blob has been generated successfully
* by this exemption mechanism object.
*/
public final boolean isCryptoAllowed(Key key)
throws ExemptionMechanismException {
boolean ret = false;
if (done && (key != null)) {
// Check if the key passed in is the same as the one
// this exemption mechanism used.
ret = keyStored.equals(key);
}
return ret;
}
/**
* Returns the length in bytes that an output buffer would need to be in
* order to hold the result of the next
* {@link #genExemptionBlob(byte[]) genExemptionBlob}
* operation, given the input length <code>inputLen</code> (in bytes).
*
* <p>The actual output length of the next
* {@link #genExemptionBlob(byte[]) genExemptionBlob}
* call may be smaller than the length returned by this method.
*
* @param inputLen the input length (in bytes)
*
* @return the required output buffer size (in bytes)
*
* @exception IllegalStateException if this exemption mechanism is in a
* wrong state (e.g., has not yet been initialized)
*/
public final int getOutputSize(int inputLen) throws IllegalStateException {
if (!initialized) {
throw new IllegalStateException(
"ExemptionMechanism not initialized");
}
if (inputLen < 0) {
throw new IllegalArgumentException(
"Input size must be equal to " + "or greater than zero");
}
return exmechSpi.engineGetOutputSize(inputLen);
}
/**
* Initializes this exemption mechanism with a key.
*
* <p>If this exemption mechanism requires any algorithm parameters
* that cannot be derived from the given <code>key</code>, the
* underlying exemption mechanism implementation is supposed to
* generate the required parameters itself (using provider-specific
* default values); in the case that algorithm parameters must be
* specified by the caller, an <code>InvalidKeyException</code> is raised.
*
* @param key the key for this exemption mechanism
*
* @exception InvalidKeyException if the given key is inappropriate for
* this exemption mechanism.
* @exception ExemptionMechanismException if problem(s) encountered in the
* process of initializing.
*/
public final void init(Key key)
throws InvalidKeyException, ExemptionMechanismException {
done = false;
initialized = false;
keyStored = key;
exmechSpi.engineInit(key);
initialized = true;
}
/**
* Initializes this exemption mechanism with a key and a set of algorithm
* parameters.
*
* <p>If this exemption mechanism requires any algorithm parameters
* and <code>params</code> is null, the underlying exemption
* mechanism implementation is supposed to generate the required
* parameters itself (using provider-specific default values); in the case
* that algorithm parameters must be specified by the caller, an
* <code>InvalidAlgorithmParameterException</code> is raised.
*
* @param key the key for this exemption mechanism
* @param params the algorithm parameters
*
* @exception InvalidKeyException if the given key is inappropriate for
* this exemption mechanism.
* @exception InvalidAlgorithmParameterException if the given algorithm
* parameters are inappropriate for this exemption mechanism.
* @exception ExemptionMechanismException if problem(s) encountered in the
* process of initializing.
*/
public final void init(Key key, AlgorithmParameterSpec params)
throws InvalidKeyException, InvalidAlgorithmParameterException,
ExemptionMechanismException {
done = false;
initialized = false;
keyStored = key;
exmechSpi.engineInit(key, params);
initialized = true;
}
/**
* Initializes this exemption mechanism with a key and a set of algorithm
* parameters.
*
* <p>If this exemption mechanism requires any algorithm parameters
* and <code>params</code> is null, the underlying exemption mechanism
* implementation is supposed to generate the required parameters itself
* (using provider-specific default values); in the case that algorithm
* parameters must be specified by the caller, an
* <code>InvalidAlgorithmParameterException</code> is raised.
*
* @param key the key for this exemption mechanism
* @param params the algorithm parameters
*
* @exception InvalidKeyException if the given key is inappropriate for
* this exemption mechanism.
* @exception InvalidAlgorithmParameterException if the given algorithm
* parameters are inappropriate for this exemption mechanism.
* @exception ExemptionMechanismException if problem(s) encountered in the
* process of initializing.
*/
public final void init(Key key, AlgorithmParameters params)
throws InvalidKeyException, InvalidAlgorithmParameterException,
ExemptionMechanismException {
done = false;
initialized = false;
keyStored = key;
exmechSpi.engineInit(key, params);
initialized = true;
}
/**
* Generates the exemption mechanism key blob.
*
* @return the new buffer with the result key blob.
*
* @exception IllegalStateException if this exemption mechanism is in
* a wrong state (e.g., has not been initialized).
* @exception ExemptionMechanismException if problem(s) encountered in the
* process of generating.
*/
public final byte[] genExemptionBlob() throws IllegalStateException,
ExemptionMechanismException {
if (!initialized) {
throw new IllegalStateException(
"ExemptionMechanism not initialized");
}
byte[] blob = exmechSpi.engineGenExemptionBlob();
done = true;
return blob;
}
/**
* Generates the exemption mechanism key blob, and stores the result in
* the <code>output</code> buffer.
*
* <p>If the <code>output</code> buffer is too small to hold the result,
* a <code>ShortBufferException</code> is thrown. In this case, repeat this
* call with a larger output buffer. Use
* {@link #getOutputSize(int) getOutputSize} to determine how big
* the output buffer should be.
*
* @param output the buffer for the result
*
* @return the number of bytes stored in <code>output</code>
*
* @exception IllegalStateException if this exemption mechanism is in
* a wrong state (e.g., has not been initialized).
* @exception ShortBufferException if the given output buffer is too small
* to hold the result.
* @exception ExemptionMechanismException if problem(s) encountered in the
* process of generating.
*/
public final int genExemptionBlob(byte[] output)
throws IllegalStateException, ShortBufferException,
ExemptionMechanismException {
if (!initialized) {
throw new IllegalStateException
("ExemptionMechanism not initialized");
}
int n = exmechSpi.engineGenExemptionBlob(output, 0);
done = true;
return n;
}
/**
* Generates the exemption mechanism key blob, and stores the result in
* the <code>output</code> buffer, starting at <code>outputOffset</code>
* inclusive.
*
* <p>If the <code>output</code> buffer is too small to hold the result,
* a <code>ShortBufferException</code> is thrown. In this case, repeat this
* call with a larger output buffer. Use
* {@link #getOutputSize(int) getOutputSize} to determine how big
* the output buffer should be.
*
* @param output the buffer for the result
* @param outputOffset the offset in <code>output</code> where the result
* is stored
*
* @return the number of bytes stored in <code>output</code>
*
* @exception IllegalStateException if this exemption mechanism is in
* a wrong state (e.g., has not been initialized).
* @exception ShortBufferException if the given output buffer is too small
* to hold the result.
* @exception ExemptionMechanismException if problem(s) encountered in the
* process of generating.
*/
public final int genExemptionBlob(byte[] output, int outputOffset)
throws IllegalStateException, ShortBufferException,
ExemptionMechanismException {
if (!initialized) {
throw new IllegalStateException
("ExemptionMechanism not initialized");
}
int n = exmechSpi.engineGenExemptionBlob(output, outputOffset);
done = true;
return n;
}
/**
* Ensures that the key stored away by this ExemptionMechanism
* object will be wiped out when there are no more references to it.
*/
protected void finalize() {
keyStored = null;
// Are there anything else we could do?
}
}

View File

@@ -0,0 +1,59 @@
/*
* Copyright (c) 1999, 2007, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.crypto;
import java.security.GeneralSecurityException;
/**
* This is the generic ExemptionMechanism exception.
*
* @since 1.4
*/
public class ExemptionMechanismException extends GeneralSecurityException {
private static final long serialVersionUID = 1572699429277957109L;
/**
* Constructs a ExemptionMechanismException with no detailed message.
* (A detailed message is a String that describes this particular
* exception.)
*/
public ExemptionMechanismException() {
super();
}
/**
* Constructs a ExemptionMechanismException with the specified
* detailed message. (A detailed message is a String that describes
* this particular exception.)
*
* @param msg the detailed message.
*/
public ExemptionMechanismException(String msg) {
super(msg);
}
}

View File

@@ -0,0 +1,170 @@
/*
* Copyright (c) 1999, 2007, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.crypto;
import java.security.Key;
import java.security.AlgorithmParameters;
import java.security.InvalidKeyException;
import java.security.InvalidAlgorithmParameterException;
import java.security.spec.AlgorithmParameterSpec;
/**
* This class defines the <i>Service Provider Interface</i> (<b>SPI</b>)
* for the <code>ExemptionMechanism</code> class.
* All the abstract methods in this class must be implemented by each
* cryptographic service provider who wishes to supply the implementation
* of a particular exemption mechanism.
*
* @author Sharon Liu
*
* @since 1.4
*/
public abstract class ExemptionMechanismSpi {
/**
* Returns the length in bytes that an output buffer would need to be in
* order to hold the result of the next
* {@link #engineGenExemptionBlob(byte[], int) engineGenExemptionBlob}
* operation, given the input length <code>inputLen</code> (in bytes).
*
* <p>The actual output length of the next
* {@link #engineGenExemptionBlob(byte[], int) engineGenExemptionBlob}
* call may be smaller than the length returned by this method.
*
* @param inputLen the input length (in bytes)
*
* @return the required output buffer size (in bytes)
*/
protected abstract int engineGetOutputSize(int inputLen);
/**
* Initializes this exemption mechanism with a key.
*
* <p>If this exemption mechanism requires any algorithm parameters
* that cannot be derived from the given <code>key</code>, the underlying
* exemption mechanism implementation is supposed to generate the required
* parameters itself (using provider-specific default values); in the case
* that algorithm parameters must be specified by the caller, an
* <code>InvalidKeyException</code> is raised.
*
* @param key the key for this exemption mechanism
*
* @exception InvalidKeyException if the given key is inappropriate for
* this exemption mechanism.
* @exception ExemptionMechanismException if problem(s) encountered in the
* process of initializing.
*/
protected abstract void engineInit(Key key)
throws InvalidKeyException, ExemptionMechanismException;
/**
* Initializes this exemption mechanism with a key and a set of algorithm
* parameters.
*
* <p>If this exemption mechanism requires any algorithm parameters and
* <code>params</code> is null, the underlying exemption mechanism
* implementation is supposed to generate the required parameters
* itself (using provider-specific default values); in the case that
* algorithm parameters must be specified by the caller, an
* <code>InvalidAlgorithmParameterException</code> is raised.
*
* @param key the key for this exemption mechanism
* @param params the algorithm parameters
*
* @exception InvalidKeyException if the given key is inappropriate for
* this exemption mechanism.
* @exception InvalidAlgorithmParameterException if the given algorithm
* parameters are inappropriate for this exemption mechanism.
* @exception ExemptionMechanismException if problem(s) encountered in the
* process of initializing.
*/
protected abstract void engineInit(Key key, AlgorithmParameterSpec params)
throws InvalidKeyException, InvalidAlgorithmParameterException,
ExemptionMechanismException;
/**
* Initializes this exemption mechanism with a key and a set of algorithm
* parameters.
*
* <p>If this exemption mechanism requires any algorithm parameters
* and <code>params</code> is null, the underlying exemption mechanism
* implementation is supposed to generate the required parameters
* itself (using provider-specific default values); in the case that
* algorithm parameters must be specified by the caller, an
* <code>InvalidAlgorithmParameterException</code> is raised.
*
* @param key the key for this exemption mechanism
* @param params the algorithm parameters
*
* @exception InvalidKeyException if the given key is inappropriate for
* this exemption mechanism.
* @exception InvalidAlgorithmParameterException if the given algorithm
* parameters are inappropriate for this exemption mechanism.
* @exception ExemptionMechanismException if problem(s) encountered in the
* process of initializing.
*/
protected abstract void engineInit(Key key, AlgorithmParameters params)
throws InvalidKeyException, InvalidAlgorithmParameterException,
ExemptionMechanismException;
/**
* Generates the exemption mechanism key blob.
*
* @return the new buffer with the result key blob.
*
* @exception ExemptionMechanismException if problem(s) encountered in the
* process of generating.
*/
protected abstract byte[] engineGenExemptionBlob()
throws ExemptionMechanismException;
/**
* Generates the exemption mechanism key blob, and stores the result in
* the <code>output</code> buffer, starting at <code>outputOffset</code>
* inclusive.
*
* <p>If the <code>output</code> buffer is too small to hold the result,
* a <code>ShortBufferException</code> is thrown. In this case, repeat this
* call with a larger output buffer. Use
* {@link #engineGetOutputSize(int) engineGetOutputSize} to determine
* how big the output buffer should be.
*
* @param output the buffer for the result
* @param outputOffset the offset in <code>output</code> where the result
* is stored
*
* @return the number of bytes stored in <code>output</code>
*
* @exception ShortBufferException if the given output buffer is too small
* to hold the result.
* @exception ExemptionMechanismException if problem(s) encountered in the
* process of generating.
*/
protected abstract int engineGenExemptionBlob
(byte[] output, int outputOffset)
throws ShortBufferException, ExemptionMechanismException;
}

View File

@@ -0,0 +1,60 @@
/*
* Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.crypto;
/**
* This exception is thrown when the length of data provided to a block
* cipher is incorrect, i.e., does not match the block size of the cipher.
*
* @author Jan Luehe
*
* @since 1.4
*/
public class IllegalBlockSizeException
extends java.security.GeneralSecurityException {
private static final long serialVersionUID = -1965144811953540392L;
/**
* Constructs an IllegalBlockSizeException with no detail message.
* A detail message is a String that describes this particular
* exception.
*/
public IllegalBlockSizeException() {
super();
}
/**
* Constructs an IllegalBlockSizeException with the specified
* detail message.
*
* @param msg the detail message.
*/
public IllegalBlockSizeException(String msg) {
super(msg);
}
}

View File

@@ -0,0 +1,153 @@
/*
* Copyright (c) 2007, 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 javax.crypto;
import java.io.*;
import java.net.*;
import java.security.*;
import java.util.jar.*;
/**
* This class verifies JAR files (and any supporting JAR files), and
* determines whether they may be used in this implementation.
*
* The JCE in OpenJDK has an open cryptographic interface, meaning it
* does not restrict which providers can be used. Compliance with
* United States export controls and with local law governing the
* import/export of products incorporating the JCE in the OpenJDK is
* the responsibility of the licensee.
*
* @since 1.7
*/
final class JarVerifier {
// The URL for the JAR file we want to verify.
private URL jarURL;
private boolean savePerms;
private CryptoPermissions appPerms = null;
/**
* Creates a JarVerifier object to verify the given URL.
*
* @param jarURL the JAR file to be verified.
* @param savePerms if true, save the permissions allowed by the
* exemption mechanism
*/
JarVerifier(URL jarURL, boolean savePerms) {
this.jarURL = jarURL;
this.savePerms = savePerms;
}
/**
* Verify the JAR file is signed by an entity which has a certificate
* issued by a trusted CA.
*
* In OpenJDK, we just need to examine the "cryptoperms" file to see
* if any permissions were bundled together with this jar file.
*/
void verify() throws JarException, IOException {
// Short-circuit. If we weren't asked to save any, we're done.
if (!savePerms) {
return;
}
// If the protocol of jarURL isn't "jar", we should
// construct a JAR URL so we can open a JarURLConnection
// for verifying this provider.
final URL url = jarURL.getProtocol().equalsIgnoreCase("jar")?
jarURL : new URL("jar:" + jarURL.toString() + "!/");
JarFile jf = null;
try {
// Get a link to the Jarfile to search.
try {
jf = AccessController.doPrivileged(
new PrivilegedExceptionAction<JarFile>() {
public JarFile run() throws Exception {
JarURLConnection conn =
(JarURLConnection) url.openConnection();
// You could do some caching here as
// an optimization.
conn.setUseCaches(false);
return conn.getJarFile();
}
});
} catch (java.security.PrivilegedActionException pae) {
throw new SecurityException("Cannot load " + url.toString(), pae);
}
if (jf != null) {
JarEntry je = jf.getJarEntry("cryptoPerms");
if (je == null) {
throw new JarException(
"Can not find cryptoPerms");
}
try {
appPerms = new CryptoPermissions();
appPerms.load(jf.getInputStream(je));
} catch (Exception ex) {
JarException jex =
new JarException("Cannot load/parse" +
jarURL.toString());
jex.initCause(ex);
throw jex;
}
}
} finally {
// Only call close() when caching is not enabled.
// Otherwise, exceptions will be thrown for all
// subsequent accesses of this cached jar.
if (jf != null) {
jf.close();
}
}
}
/**
* Verify that the provided certs include the
* framework signing certificate.
*
* @param certs the list of certs to be checked.
* @throws Exception if the list of certs did not contain
* the framework signing certificate
*/
static void verifyPolicySigned(java.security.cert.Certificate[] certs)
throws Exception {
}
/**
* Returns the permissions which are bundled with the JAR file,
* aka the "cryptoperms" file.
*
* NOTE: if this JarVerifier instance is constructed with "savePerms"
* equal to false, then this method would always return null.
*/
CryptoPermissions getPermissions() {
return appPerms;
}
}

View File

@@ -0,0 +1,396 @@
/*
* Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact 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.crypto;
import java.util.*;
import java.util.jar.*;
import java.io.*;
import java.net.URL;
import java.nio.file.*;
import java.security.*;
import java.security.Provider.Service;
import sun.security.jca.*;
import sun.security.jca.GetInstance.Instance;
import sun.security.util.Debug;
/**
* This class instantiates implementations of JCE engine classes from
* providers registered with the java.security.Security object.
*
* @author Jan Luehe
* @author Sharon Liu
* @since 1.4
*/
final class JceSecurity {
static final SecureRandom RANDOM = new SecureRandom();
// The defaultPolicy and exemptPolicy will be set up
// in the static initializer.
private static CryptoPermissions defaultPolicy = null;
private static CryptoPermissions exemptPolicy = null;
// Map<Provider,?> of the providers we already have verified
// value == PROVIDER_VERIFIED is successfully verified
// value is failure cause Exception in error case
private final static Map<Provider, Object> verificationResults =
new IdentityHashMap<>();
// Map<Provider,?> of the providers currently being verified
private final static Map<Provider, Object> verifyingProviders =
new IdentityHashMap<>();
private static final boolean isRestricted;
private static final Debug debug =
Debug.getInstance("jca", "Cipher");
/*
* Don't let anyone instantiate this.
*/
private JceSecurity() {
}
static {
try {
AccessController.doPrivileged(
new PrivilegedExceptionAction<Object>() {
public Object run() throws Exception {
setupJurisdictionPolicies();
return null;
}
});
isRestricted = defaultPolicy.implies(
CryptoAllPermission.INSTANCE) ? false : true;
} catch (Exception e) {
throw new SecurityException(
"Can not initialize cryptographic mechanism", e);
}
}
static Instance getInstance(String type, Class<?> clazz, String algorithm,
String provider) throws NoSuchAlgorithmException,
NoSuchProviderException {
Service s = GetInstance.getService(type, algorithm, provider);
Exception ve = getVerificationResult(s.getProvider());
if (ve != null) {
String msg = "JCE cannot authenticate the provider " + provider;
throw (NoSuchProviderException)
new NoSuchProviderException(msg).initCause(ve);
}
return GetInstance.getInstance(s, clazz);
}
static Instance getInstance(String type, Class<?> clazz, String algorithm,
Provider provider) throws NoSuchAlgorithmException {
Service s = GetInstance.getService(type, algorithm, provider);
Exception ve = JceSecurity.getVerificationResult(provider);
if (ve != null) {
String msg = "JCE cannot authenticate the provider "
+ provider.getName();
throw new SecurityException(msg, ve);
}
return GetInstance.getInstance(s, clazz);
}
static Instance getInstance(String type, Class<?> clazz, String algorithm)
throws NoSuchAlgorithmException {
List<Service> services = GetInstance.getServices(type, algorithm);
NoSuchAlgorithmException failure = null;
for (Service s : services) {
if (canUseProvider(s.getProvider()) == false) {
// allow only signed providers
continue;
}
try {
Instance instance = GetInstance.getInstance(s, clazz);
return instance;
} catch (NoSuchAlgorithmException e) {
failure = e;
}
}
throw new NoSuchAlgorithmException("Algorithm " + algorithm
+ " not available", failure);
}
/**
* Verify if the JAR at URL codeBase is a signed exempt application
* JAR file and returns the permissions bundled with the JAR.
*
* @throws Exception on error
*/
static CryptoPermissions verifyExemptJar(URL codeBase) throws Exception {
JarVerifier jv = new JarVerifier(codeBase, true);
jv.verify();
return jv.getPermissions();
}
/**
* Verify if the JAR at URL codeBase is a signed provider JAR file.
*
* @throws Exception on error
*/
static void verifyProviderJar(URL codeBase) throws Exception {
// Verify the provider JAR file and all
// supporting JAR files if there are any.
JarVerifier jv = new JarVerifier(codeBase, false);
jv.verify();
}
private final static Object PROVIDER_VERIFIED = Boolean.TRUE;
/*
* Verify that the provider JAR files are signed properly, which
* means the signer's certificate can be traced back to a
* JCE trusted CA.
* Return null if ok, failure Exception if verification failed.
*/
static synchronized Exception getVerificationResult(Provider p) {
Object o = verificationResults.get(p);
if (o == PROVIDER_VERIFIED) {
return null;
} else if (o != null) {
return (Exception)o;
}
if (verifyingProviders.get(p) != null) {
// this method is static synchronized, must be recursion
// return failure now but do not save the result
return new NoSuchProviderException("Recursion during verification");
}
try {
verifyingProviders.put(p, Boolean.FALSE);
URL providerURL = getCodeBase(p.getClass());
verifyProviderJar(providerURL);
// Verified ok, cache result
verificationResults.put(p, PROVIDER_VERIFIED);
return null;
} catch (Exception e) {
verificationResults.put(p, e);
return e;
} finally {
verifyingProviders.remove(p);
}
}
// return whether this provider is properly signed and can be used by JCE
static boolean canUseProvider(Provider p) {
return getVerificationResult(p) == null;
}
// dummy object to represent null
private static final URL NULL_URL;
static {
try {
NULL_URL = new URL("http://null.oracle.com/");
} catch (Exception e) {
throw new RuntimeException(e);
}
}
// reference to a Map we use as a cache for codebases
private static final Map<Class<?>, URL> codeBaseCacheRef =
new WeakHashMap<>();
/*
* Returns the CodeBase for the given class.
*/
static URL getCodeBase(final Class<?> clazz) {
synchronized (codeBaseCacheRef) {
URL url = codeBaseCacheRef.get(clazz);
if (url == null) {
url = AccessController.doPrivileged(new PrivilegedAction<URL>() {
public URL run() {
ProtectionDomain pd = clazz.getProtectionDomain();
if (pd != null) {
CodeSource cs = pd.getCodeSource();
if (cs != null) {
return cs.getLocation();
}
}
return NULL_URL;
}
});
codeBaseCacheRef.put(clazz, url);
}
return (url == NULL_URL) ? null : url;
}
}
/*
* This is called from within an doPrivileged block.
*
* Following logic is used to decide what policy files are selected.
*
* If the new Security property (crypto.policy) is set in the
* java.security file, or has been set dynamically using the
* Security.setProperty() call before the JCE framework has
* been initialized, that setting will be used.
* Remember - this property is not defined by default. A conscious
* user edit or an application call is required.
*
* Otherwise, if user has policy jar files installed in the legacy
* <java-home>/lib/security/ directory, the JDK will honor whatever
* setting is set by those policy files. (legacy/current behavior)
*
* If none of the above 2 conditions are met, the JDK will default
* to using the unlimited crypto policy files found in the
* <java-home>/lib/security/policy/unlimited/ directory
*/
private static void setupJurisdictionPolicies() throws Exception {
// Sanity check the crypto.policy Security property. Single
// directory entry, no pseudo-directories (".", "..", leading/trailing
// path separators). normalize()/getParent() will help later.
String javaHomeProperty = System.getProperty("java.home");
String cryptoPolicyProperty = Security.getProperty("crypto.policy");
Path cpPath = (cryptoPolicyProperty == null) ? null :
Paths.get(cryptoPolicyProperty);
if ((cpPath != null) && ((cpPath.getNameCount() != 1) ||
(cpPath.compareTo(cpPath.getFileName())) != 0)) {
throw new SecurityException(
"Invalid policy directory name format: " +
cryptoPolicyProperty);
}
if (cpPath == null) {
// Security property is not set, use default path
cpPath = Paths.get(javaHomeProperty, "lib", "security");
} else {
// populate with java.home
cpPath = Paths.get(javaHomeProperty, "lib", "security",
"policy", cryptoPolicyProperty);
}
if (debug != null) {
debug.println("crypto policy directory: " + cpPath);
}
File exportJar = new File(cpPath.toFile(),"US_export_policy.jar");
File importJar = new File(cpPath.toFile(),"local_policy.jar");
if (cryptoPolicyProperty == null && (!exportJar.exists() ||
!importJar.exists())) {
// Compatibility set up. If crypto.policy is not defined.
// check to see if legacy jars exist in lib directory. If
// they don't exist, we default to unlimited policy mode.
cpPath = Paths.get(
javaHomeProperty, "lib", "security", "policy", "unlimited");
// point to the new jar files in limited directory
exportJar = new File(cpPath.toFile(),"US_export_policy.jar");
importJar = new File(cpPath.toFile(),"local_policy.jar");
}
URL jceCipherURL = ClassLoader.getSystemResource
("javax/crypto/Cipher.class");
if ((jceCipherURL == null) ||
!exportJar.exists() || !importJar.exists()) {
throw new SecurityException
("Cannot locate policy or framework files!");
}
// Read jurisdiction policies.
CryptoPermissions defaultExport = new CryptoPermissions();
CryptoPermissions exemptExport = new CryptoPermissions();
loadPolicies(exportJar, defaultExport, exemptExport);
CryptoPermissions defaultImport = new CryptoPermissions();
CryptoPermissions exemptImport = new CryptoPermissions();
loadPolicies(importJar, defaultImport, exemptImport);
// Merge the export and import policies for default applications.
if (defaultExport.isEmpty() || defaultImport.isEmpty()) {
throw new SecurityException("Missing mandatory jurisdiction " +
"policy files");
}
defaultPolicy = defaultExport.getMinimum(defaultImport);
// Merge the export and import policies for exempt applications.
if (exemptExport.isEmpty()) {
exemptPolicy = exemptImport.isEmpty() ? null : exemptImport;
} else {
exemptPolicy = exemptExport.getMinimum(exemptImport);
}
}
/**
* Load the policies from the specified file. Also checks that the
* policies are correctly signed.
*/
private static void loadPolicies(File jarPathName,
CryptoPermissions defaultPolicy,
CryptoPermissions exemptPolicy)
throws Exception {
JarFile jf = new JarFile(jarPathName);
Enumeration<JarEntry> entries = jf.entries();
while (entries.hasMoreElements()) {
JarEntry je = entries.nextElement();
InputStream is = null;
try {
if (je.getName().startsWith("default_")) {
is = jf.getInputStream(je);
defaultPolicy.load(is);
} else if (je.getName().startsWith("exempt_")) {
is = jf.getInputStream(je);
exemptPolicy.load(is);
} else {
continue;
}
} finally {
if (is != null) {
is.close();
}
}
// Enforce the signer restraint, i.e. signer of JCE framework
// jar should also be the signer of the two jurisdiction policy
// jar files.
JarVerifier.verifyPolicySigned(je.getCertificates());
}
// Close and nullify the JarFile reference to help GC.
jf.close();
jf = null;
}
static CryptoPermissions getDefaultPolicy() {
return defaultPolicy;
}
static CryptoPermissions getExemptPolicy() {
return exemptPolicy;
}
static boolean isRestricted() {
return isRestricted;
}
}

View File

@@ -0,0 +1,259 @@
/*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.crypto;
import java.security.*;
import java.net.*;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
/**
* The JCE security manager.
*
* <p>The JCE security manager is responsible for determining the maximum
* allowable cryptographic strength for a given applet/application, for a given
* algorithm, by consulting the configured jurisdiction policy files and
* the cryptographic permissions bundled with the applet/application.
*
* <p>Note that this security manager is never installed, only instantiated.
*
* @author Jan Luehe
*
* @since 1.4
*/
final class JceSecurityManager extends SecurityManager {
private static final CryptoPermissions defaultPolicy;
private static final CryptoPermissions exemptPolicy;
private static final CryptoAllPermission allPerm;
private static final Vector<Class<?>> TrustedCallersCache =
new Vector<>(2);
private static final ConcurrentMap<URL,CryptoPermissions> exemptCache =
new ConcurrentHashMap<>();
private static final CryptoPermissions CACHE_NULL_MARK =
new CryptoPermissions();
// singleton instance
static final JceSecurityManager INSTANCE;
static {
defaultPolicy = JceSecurity.getDefaultPolicy();
exemptPolicy = JceSecurity.getExemptPolicy();
allPerm = CryptoAllPermission.INSTANCE;
INSTANCE = AccessController.doPrivileged(
new PrivilegedAction<JceSecurityManager>() {
public JceSecurityManager run() {
return new JceSecurityManager();
}
});
}
private JceSecurityManager() {
// empty
}
/**
* Returns the maximum allowable crypto strength for the given
* applet/application, for the given algorithm.
*/
CryptoPermission getCryptoPermission(String alg) {
// Need to convert to uppercase since the crypto perm
// lookup is case sensitive.
alg = alg.toUpperCase(Locale.ENGLISH);
// If CryptoAllPermission is granted by default, we return that.
// Otherwise, this will be the permission we return if anything goes
// wrong.
CryptoPermission defaultPerm = getDefaultPermission(alg);
if (defaultPerm == CryptoAllPermission.INSTANCE) {
return defaultPerm;
}
// Determine the codebase of the caller of the JCE API.
// This is the codebase of the first class which is not in
// javax.crypto.* packages.
// NOTE: javax.crypto.* package maybe subject to package
// insertion, so need to check its classloader as well.
Class<?>[] context = getClassContext();
URL callerCodeBase = null;
int i;
for (i=0; i<context.length; i++) {
Class<?> cls = context[i];
callerCodeBase = JceSecurity.getCodeBase(cls);
if (callerCodeBase != null) {
break;
} else {
if (cls.getName().startsWith("javax.crypto.")) {
// skip jce classes since they aren't the callers
continue;
}
// use default permission when the caller is system classes
return defaultPerm;
}
}
if (i == context.length) {
return defaultPerm;
}
CryptoPermissions appPerms = exemptCache.get(callerCodeBase);
if (appPerms == null) {
// no match found in cache
synchronized (this.getClass()) {
appPerms = exemptCache.get(callerCodeBase);
if (appPerms == null) {
appPerms = getAppPermissions(callerCodeBase);
exemptCache.putIfAbsent(callerCodeBase,
(appPerms == null? CACHE_NULL_MARK:appPerms));
}
}
}
if (appPerms == null || appPerms == CACHE_NULL_MARK) {
return defaultPerm;
}
// If the app was granted the special CryptoAllPermission, return that.
if (appPerms.implies(allPerm)) {
return allPerm;
}
// Check if the crypto permissions granted to the app contain a
// crypto permission for the requested algorithm that does not require
// any exemption mechanism to be enforced.
// Return that permission, if present.
PermissionCollection appPc = appPerms.getPermissionCollection(alg);
if (appPc == null) {
return defaultPerm;
}
Enumeration<Permission> enum_ = appPc.elements();
while (enum_.hasMoreElements()) {
CryptoPermission cp = (CryptoPermission)enum_.nextElement();
if (cp.getExemptionMechanism() == null) {
return cp;
}
}
// Check if the jurisdiction file for exempt applications contains
// any entries for the requested algorithm.
// If not, return the default permission.
PermissionCollection exemptPc =
exemptPolicy.getPermissionCollection(alg);
if (exemptPc == null) {
return defaultPerm;
}
// In the jurisdiction file for exempt applications, go through the
// list of CryptoPermission entries for the requested algorithm, and
// stop at the first entry:
// - that is implied by the collection of crypto permissions granted
// to the app, and
// - whose exemption mechanism is available from one of the
// registered CSPs
enum_ = exemptPc.elements();
while (enum_.hasMoreElements()) {
CryptoPermission cp = (CryptoPermission)enum_.nextElement();
try {
ExemptionMechanism.getInstance(cp.getExemptionMechanism());
if (cp.getAlgorithm().equals(
CryptoPermission.ALG_NAME_WILDCARD)) {
CryptoPermission newCp;
if (cp.getCheckParam()) {
newCp = new CryptoPermission(
alg, cp.getMaxKeySize(),
cp.getAlgorithmParameterSpec(),
cp.getExemptionMechanism());
} else {
newCp = new CryptoPermission(
alg, cp.getMaxKeySize(),
cp.getExemptionMechanism());
}
if (appPerms.implies(newCp)) {
return newCp;
}
}
if (appPerms.implies(cp)) {
return cp;
}
} catch (Exception e) {
continue;
}
}
return defaultPerm;
}
private static CryptoPermissions getAppPermissions(URL callerCodeBase) {
// Check if app is exempt, and retrieve the permissions bundled with it
try {
return JceSecurity.verifyExemptJar(callerCodeBase);
} catch (Exception e) {
// Jar verification fails
return null;
}
}
/**
* Returns the default permission for the given algorithm.
*/
private CryptoPermission getDefaultPermission(String alg) {
Enumeration<Permission> enum_ =
defaultPolicy.getPermissionCollection(alg).elements();
return (CryptoPermission)enum_.nextElement();
}
// See bug 4341369 & 4334690 for more info.
boolean isCallerTrusted() {
// Get the caller and its codebase.
Class<?>[] context = getClassContext();
URL callerCodeBase = null;
int i;
for (i=0; i<context.length; i++) {
callerCodeBase = JceSecurity.getCodeBase(context[i]);
if (callerCodeBase != null) {
break;
}
}
// The caller is in the JCE framework.
if (i == context.length) {
return true;
}
//The caller has been verified.
if (TrustedCallersCache.contains(context[i])) {
return true;
}
// Check whether the caller is a trusted provider.
try {
JceSecurity.verifyProviderJar(callerCodeBase);
} catch (Exception e2) {
return false;
}
TrustedCallersCache.addElement(context[i]);
return true;
}
}

View File

@@ -0,0 +1,650 @@
/*
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact 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.crypto;
import java.util.*;
import java.security.*;
import java.security.Provider.Service;
import java.security.spec.*;
import sun.security.util.Debug;
import sun.security.jca.*;
import sun.security.jca.GetInstance.Instance;
/**
* This class provides the functionality of a key agreement (or key
* exchange) protocol.
* <p>
* The keys involved in establishing a shared secret are created by one of the
* key generators ({@code KeyPairGenerator} or
* {@code KeyGenerator}), a {@code KeyFactory}, or as a result from
* an intermediate phase of the key agreement protocol.
*
* <p> For each of the correspondents in the key exchange, {@code doPhase}
* needs to be called. For example, if this key exchange is with one other
* party, {@code doPhase} needs to be called once, with the
* {@code lastPhase} flag set to {@code true}.
* If this key exchange is
* with two other parties, {@code doPhase} needs to be called twice,
* the first time setting the {@code lastPhase} flag to
* {@code false}, and the second time setting it to {@code true}.
* There may be any number of parties involved in a key exchange.
*
* <p> Every implementation of the Java platform is required to support the
* following standard {@code KeyAgreement} algorithm:
* <ul>
* <li>{@code DiffieHellman}</li>
* </ul>
* This algorithm is described in the <a href=
* "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyAgreement">
* KeyAgreement section</a> of the
* Java Cryptography Architecture Standard Algorithm Name Documentation.
* Consult the release documentation for your implementation to see if any
* other algorithms are supported.
*
* @author Jan Luehe
*
* @see KeyGenerator
* @see SecretKey
* @since 1.4
*/
public class KeyAgreement {
private static final Debug debug =
Debug.getInstance("jca", "KeyAgreement");
private static final Debug pdebug =
Debug.getInstance("provider", "Provider");
private static final boolean skipDebug =
Debug.isOn("engine=") && !Debug.isOn("keyagreement");
// The provider
private Provider provider;
// The provider implementation (delegate)
private KeyAgreementSpi spi;
// The name of the key agreement algorithm.
private final String algorithm;
// next service to try in provider selection
// null once provider is selected
private Service firstService;
// remaining services to try in provider selection
// null once provider is selected
private Iterator<Service> serviceIterator;
private final Object lock;
/**
* Creates a KeyAgreement object.
*
* @param keyAgreeSpi the delegate
* @param provider the provider
* @param algorithm the algorithm
*/
protected KeyAgreement(KeyAgreementSpi keyAgreeSpi, Provider provider,
String algorithm) {
this.spi = keyAgreeSpi;
this.provider = provider;
this.algorithm = algorithm;
lock = null;
}
private KeyAgreement(Service s, Iterator<Service> t, String algorithm) {
firstService = s;
serviceIterator = t;
this.algorithm = algorithm;
lock = new Object();
}
/**
* Returns the algorithm name of this {@code KeyAgreement} object.
*
* <p>This is the same name that was specified in one of the
* {@code getInstance} calls that created this
* {@code KeyAgreement} object.
*
* @return the algorithm name of this {@code KeyAgreement} object.
*/
public final String getAlgorithm() {
return this.algorithm;
}
/**
* Returns a {@code KeyAgreement} object that implements the
* specified key agreement algorithm.
*
* <p> This method traverses the list of registered security Providers,
* starting with the most preferred Provider.
* A new KeyAgreement object encapsulating the
* KeyAgreementSpi implementation from the first
* Provider that supports the specified algorithm is returned.
*
* <p> Note that the list of registered providers may be retrieved via
* the {@link Security#getProviders() Security.getProviders()} method.
*
* @param algorithm the standard name of the requested key agreement
* algorithm.
* See the KeyAgreement section in the <a href=
* "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyAgreement">
* Java Cryptography Architecture Standard Algorithm Name Documentation</a>
* for information about standard algorithm names.
*
* @return the new {@code KeyAgreement} object.
*
* @exception NullPointerException if the specified algorithm
* is null.
*
* @exception NoSuchAlgorithmException if no Provider supports a
* KeyAgreementSpi implementation for the
* specified algorithm.
*
* @see java.security.Provider
*/
public static final KeyAgreement getInstance(String algorithm)
throws NoSuchAlgorithmException {
List<Service> services =
GetInstance.getServices("KeyAgreement", algorithm);
// make sure there is at least one service from a signed provider
Iterator<Service> t = services.iterator();
while (t.hasNext()) {
Service s = t.next();
if (JceSecurity.canUseProvider(s.getProvider()) == false) {
continue;
}
return new KeyAgreement(s, t, algorithm);
}
throw new NoSuchAlgorithmException
("Algorithm " + algorithm + " not available");
}
/**
* Returns a {@code KeyAgreement} object that implements the
* specified key agreement algorithm.
*
* <p> A new KeyAgreement object encapsulating the
* KeyAgreementSpi implementation from the specified provider
* is returned. The specified provider must be registered
* in the security provider list.
*
* <p> Note that the list of registered providers may be retrieved via
* the {@link Security#getProviders() Security.getProviders()} method.
*
* @param algorithm the standard name of the requested key agreement
* algorithm.
* See the KeyAgreement section in the <a href=
* "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyAgreement">
* Java Cryptography Architecture Standard Algorithm Name Documentation</a>
* for information about standard algorithm names.
*
* @param provider the name of the provider.
*
* @return the new {@code KeyAgreement} object.
*
* @exception NullPointerException if the specified algorithm
* is null.
*
* @exception NoSuchAlgorithmException if a KeyAgreementSpi
* implementation for the specified algorithm is not
* available from the specified provider.
*
* @exception NoSuchProviderException if the specified provider is not
* registered in the security provider list.
*
* @exception IllegalArgumentException if the {@code provider}
* is null or empty.
*
* @see java.security.Provider
*/
public static final KeyAgreement getInstance(String algorithm,
String provider) throws NoSuchAlgorithmException,
NoSuchProviderException {
Instance instance = JceSecurity.getInstance
("KeyAgreement", KeyAgreementSpi.class, algorithm, provider);
return new KeyAgreement((KeyAgreementSpi)instance.impl,
instance.provider, algorithm);
}
/**
* Returns a {@code KeyAgreement} object that implements the
* specified key agreement algorithm.
*
* <p> A new KeyAgreement object encapsulating the
* KeyAgreementSpi implementation from the specified Provider
* object is returned. Note that the specified Provider object
* does not have to be registered in the provider list.
*
* @param algorithm the standard name of the requested key agreement
* algorithm.
* See the KeyAgreement section in the <a href=
* "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyAgreement">
* Java Cryptography Architecture Standard Algorithm Name Documentation</a>
* for information about standard algorithm names.
*
* @param provider the provider.
*
* @return the new {@code KeyAgreement} object.
*
* @exception NullPointerException if the specified algorithm
* is null.
*
* @exception NoSuchAlgorithmException if a KeyAgreementSpi
* implementation for the specified algorithm is not available
* from the specified Provider object.
*
* @exception IllegalArgumentException if the {@code provider}
* is null.
*
* @see java.security.Provider
*/
public static final KeyAgreement getInstance(String algorithm,
Provider provider) throws NoSuchAlgorithmException {
Instance instance = JceSecurity.getInstance
("KeyAgreement", KeyAgreementSpi.class, algorithm, provider);
return new KeyAgreement((KeyAgreementSpi)instance.impl,
instance.provider, algorithm);
}
// max number of debug warnings to print from chooseFirstProvider()
private static int warnCount = 10;
/**
* Choose the Spi from the first provider available. Used if
* delayed provider selection is not possible because init()
* is not the first method called.
*/
void chooseFirstProvider() {
if (spi != null) {
return;
}
synchronized (lock) {
if (spi != null) {
return;
}
if (debug != null) {
int w = --warnCount;
if (w >= 0) {
debug.println("KeyAgreement.init() not first method "
+ "called, disabling delayed provider selection");
if (w == 0) {
debug.println("Further warnings of this type will "
+ "be suppressed");
}
new Exception("Call trace").printStackTrace();
}
}
Exception lastException = null;
while ((firstService != null) || serviceIterator.hasNext()) {
Service s;
if (firstService != null) {
s = firstService;
firstService = null;
} else {
s = serviceIterator.next();
}
if (JceSecurity.canUseProvider(s.getProvider()) == false) {
continue;
}
try {
Object obj = s.newInstance(null);
if (obj instanceof KeyAgreementSpi == false) {
continue;
}
spi = (KeyAgreementSpi)obj;
provider = s.getProvider();
// not needed any more
firstService = null;
serviceIterator = null;
return;
} catch (Exception e) {
lastException = e;
}
}
ProviderException e = new ProviderException
("Could not construct KeyAgreementSpi instance");
if (lastException != null) {
e.initCause(lastException);
}
throw e;
}
}
private final static int I_NO_PARAMS = 1;
private final static int I_PARAMS = 2;
private void implInit(KeyAgreementSpi spi, int type, Key key,
AlgorithmParameterSpec params, SecureRandom random)
throws InvalidKeyException, InvalidAlgorithmParameterException {
if (type == I_NO_PARAMS) {
spi.engineInit(key, random);
} else { // I_PARAMS
spi.engineInit(key, params, random);
}
}
private void chooseProvider(int initType, Key key,
AlgorithmParameterSpec params, SecureRandom random)
throws InvalidKeyException, InvalidAlgorithmParameterException {
synchronized (lock) {
if (spi != null) {
implInit(spi, initType, key, params, random);
return;
}
Exception lastException = null;
while ((firstService != null) || serviceIterator.hasNext()) {
Service s;
if (firstService != null) {
s = firstService;
firstService = null;
} else {
s = serviceIterator.next();
}
// if provider says it does not support this key, ignore it
if (s.supportsParameter(key) == false) {
continue;
}
if (JceSecurity.canUseProvider(s.getProvider()) == false) {
continue;
}
try {
KeyAgreementSpi spi = (KeyAgreementSpi)s.newInstance(null);
implInit(spi, initType, key, params, random);
provider = s.getProvider();
this.spi = spi;
firstService = null;
serviceIterator = null;
return;
} catch (Exception e) {
// NoSuchAlgorithmException from newInstance()
// InvalidKeyException from init()
// RuntimeException (ProviderException) from init()
if (lastException == null) {
lastException = e;
}
}
}
// no working provider found, fail
if (lastException instanceof InvalidKeyException) {
throw (InvalidKeyException)lastException;
}
if (lastException instanceof InvalidAlgorithmParameterException) {
throw (InvalidAlgorithmParameterException)lastException;
}
if (lastException instanceof RuntimeException) {
throw (RuntimeException)lastException;
}
String kName = (key != null) ? key.getClass().getName() : "(null)";
throw new InvalidKeyException
("No installed provider supports this key: "
+ kName, lastException);
}
}
/**
* Returns the provider of this {@code KeyAgreement} object.
*
* @return the provider of this {@code KeyAgreement} object
*/
public final Provider getProvider() {
chooseFirstProvider();
return this.provider;
}
/**
* Initializes this key agreement with the given key, which is required to
* contain all the algorithm parameters required for this key agreement.
*
* <p> If this key agreement requires any random bytes, it will get
* them using the
* {@link java.security.SecureRandom}
* implementation of the highest-priority
* installed provider as the source of randomness.
* (If none of the installed providers supply an implementation of
* SecureRandom, a system-provided source of randomness will be used.)
*
* @param key the party's private information. For example, in the case
* of the Diffie-Hellman key agreement, this would be the party's own
* Diffie-Hellman private key.
*
* @exception InvalidKeyException if the given key is
* inappropriate for this key agreement, e.g., is of the wrong type or
* has an incompatible algorithm type.
*/
public final void init(Key key) throws InvalidKeyException {
init(key, JceSecurity.RANDOM);
}
/**
* Initializes this key agreement with the given key and source of
* randomness. The given key is required to contain all the algorithm
* parameters required for this key agreement.
*
* <p> If the key agreement algorithm requires random bytes, it gets them
* from the given source of randomness, {@code random}.
* However, if the underlying
* algorithm implementation does not require any random bytes,
* {@code random} is ignored.
*
* @param key the party's private information. For example, in the case
* of the Diffie-Hellman key agreement, this would be the party's own
* Diffie-Hellman private key.
* @param random the source of randomness
*
* @exception InvalidKeyException if the given key is
* inappropriate for this key agreement, e.g., is of the wrong type or
* has an incompatible algorithm type.
*/
public final void init(Key key, SecureRandom random)
throws InvalidKeyException {
if (spi != null) {
spi.engineInit(key, random);
} else {
try {
chooseProvider(I_NO_PARAMS, key, null, random);
} catch (InvalidAlgorithmParameterException e) {
// should never occur
throw new InvalidKeyException(e);
}
}
if (!skipDebug && pdebug != null) {
pdebug.println("KeyAgreement." + algorithm + " algorithm from: " +
this.provider.getName());
}
}
/**
* Initializes this key agreement with the given key and set of
* algorithm parameters.
*
* <p> If this key agreement requires any random bytes, it will get
* them using the
* {@link java.security.SecureRandom}
* implementation of the highest-priority
* installed provider as the source of randomness.
* (If none of the installed providers supply an implementation of
* SecureRandom, a system-provided source of randomness will be used.)
*
* @param key the party's private information. For example, in the case
* of the Diffie-Hellman key agreement, this would be the party's own
* Diffie-Hellman private key.
* @param params the key agreement parameters
*
* @exception InvalidKeyException if the given key is
* inappropriate for this key agreement, e.g., is of the wrong type or
* has an incompatible algorithm type.
* @exception InvalidAlgorithmParameterException if the given parameters
* are inappropriate for this key agreement.
*/
public final void init(Key key, AlgorithmParameterSpec params)
throws InvalidKeyException, InvalidAlgorithmParameterException
{
init(key, params, JceSecurity.RANDOM);
}
/**
* Initializes this key agreement with the given key, set of
* algorithm parameters, and source of randomness.
*
* @param key the party's private information. For example, in the case
* of the Diffie-Hellman key agreement, this would be the party's own
* Diffie-Hellman private key.
* @param params the key agreement parameters
* @param random the source of randomness
*
* @exception InvalidKeyException if the given key is
* inappropriate for this key agreement, e.g., is of the wrong type or
* has an incompatible algorithm type.
* @exception InvalidAlgorithmParameterException if the given parameters
* are inappropriate for this key agreement.
*/
public final void init(Key key, AlgorithmParameterSpec params,
SecureRandom random)
throws InvalidKeyException, InvalidAlgorithmParameterException
{
if (spi != null) {
spi.engineInit(key, params, random);
} else {
chooseProvider(I_PARAMS, key, params, random);
}
if (!skipDebug && pdebug != null) {
pdebug.println("KeyAgreement." + algorithm + " algorithm from: " +
this.provider.getName());
}
}
/**
* Executes the next phase of this key agreement with the given
* key that was received from one of the other parties involved in this key
* agreement.
*
* @param key the key for this phase. For example, in the case of
* Diffie-Hellman between 2 parties, this would be the other party's
* Diffie-Hellman public key.
* @param lastPhase flag which indicates whether or not this is the last
* phase of this key agreement.
*
* @return the (intermediate) key resulting from this phase, or null
* if this phase does not yield a key
*
* @exception InvalidKeyException if the given key is inappropriate for
* this phase.
* @exception IllegalStateException if this key agreement has not been
* initialized.
*/
public final Key doPhase(Key key, boolean lastPhase)
throws InvalidKeyException, IllegalStateException
{
chooseFirstProvider();
return spi.engineDoPhase(key, lastPhase);
}
/**
* Generates the shared secret and returns it in a new buffer.
*
* <p>This method resets this {@code KeyAgreement} object, so that it
* can be reused for further key agreements. Unless this key agreement is
* reinitialized with one of the {@code init} methods, the same
* private information and algorithm parameters will be used for
* subsequent key agreements.
*
* @return the new buffer with the shared secret
*
* @exception IllegalStateException if this key agreement has not been
* completed yet
*/
public final byte[] generateSecret() throws IllegalStateException {
chooseFirstProvider();
return spi.engineGenerateSecret();
}
/**
* Generates the shared secret, and places it into the buffer
* {@code sharedSecret}, beginning at {@code offset} inclusive.
*
* <p>If the {@code sharedSecret} buffer is too small to hold the
* result, a {@code ShortBufferException} is thrown.
* In this case, this call should be repeated with a larger output buffer.
*
* <p>This method resets this {@code KeyAgreement} object, so that it
* can be reused for further key agreements. Unless this key agreement is
* reinitialized with one of the {@code init} methods, the same
* private information and algorithm parameters will be used for
* subsequent key agreements.
*
* @param sharedSecret the buffer for the shared secret
* @param offset the offset in {@code sharedSecret} where the
* shared secret will be stored
*
* @return the number of bytes placed into {@code sharedSecret}
*
* @exception IllegalStateException if this key agreement has not been
* completed yet
* @exception ShortBufferException if the given output buffer is too small
* to hold the secret
*/
public final int generateSecret(byte[] sharedSecret, int offset)
throws IllegalStateException, ShortBufferException
{
chooseFirstProvider();
return spi.engineGenerateSecret(sharedSecret, offset);
}
/**
* Creates the shared secret and returns it as a {@code SecretKey}
* object of the specified algorithm.
*
* <p>This method resets this {@code KeyAgreement} object, so that it
* can be reused for further key agreements. Unless this key agreement is
* reinitialized with one of the {@code init} methods, the same
* private information and algorithm parameters will be used for
* subsequent key agreements.
*
* @param algorithm the requested secret-key algorithm
*
* @return the shared secret key
*
* @exception IllegalStateException if this key agreement has not been
* completed yet
* @exception NoSuchAlgorithmException if the specified secret-key
* algorithm is not available
* @exception InvalidKeyException if the shared secret-key material cannot
* be used to generate a secret key of the specified algorithm (e.g.,
* the key material is too short)
*/
public final SecretKey generateSecret(String algorithm)
throws IllegalStateException, NoSuchAlgorithmException,
InvalidKeyException
{
chooseFirstProvider();
return spi.engineGenerateSecret(algorithm);
}
}

View File

@@ -0,0 +1,204 @@
/*
* Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.crypto;
import java.security.*;
import java.security.spec.*;
/**
* This class defines the <i>Service Provider Interface</i> (<b>SPI</b>)
* for the <code>KeyAgreement</code> class.
* All the abstract methods in this class must be implemented by each
* cryptographic service provider who wishes to supply the implementation
* of a particular key agreement algorithm.
*
* <p> The keys involved in establishing a shared secret are created by one
* of the
* key generators (<code>KeyPairGenerator</code> or
* <code>KeyGenerator</code>), a <code>KeyFactory</code>, or as a result from
* an intermediate phase of the key agreement protocol
* ({@link #engineDoPhase(java.security.Key, boolean) engineDoPhase}).
*
* <p> For each of the correspondents in the key exchange,
* <code>engineDoPhase</code>
* needs to be called. For example, if the key exchange is with one other
* party, <code>engineDoPhase</code> needs to be called once, with the
* <code>lastPhase</code> flag set to <code>true</code>.
* If the key exchange is
* with two other parties, <code>engineDoPhase</code> needs to be called twice,
* the first time setting the <code>lastPhase</code> flag to
* <code>false</code>, and the second time setting it to <code>true</code>.
* There may be any number of parties involved in a key exchange.
*
* @author Jan Luehe
*
* @see KeyGenerator
* @see SecretKey
* @since 1.4
*/
public abstract class KeyAgreementSpi {
/**
* Initializes this key agreement with the given key and source of
* randomness. The given key is required to contain all the algorithm
* parameters required for this key agreement.
*
* <p> If the key agreement algorithm requires random bytes, it gets them
* from the given source of randomness, <code>random</code>.
* However, if the underlying
* algorithm implementation does not require any random bytes,
* <code>random</code> is ignored.
*
* @param key the party's private information. For example, in the case
* of the Diffie-Hellman key agreement, this would be the party's own
* Diffie-Hellman private key.
* @param random the source of randomness
*
* @exception InvalidKeyException if the given key is
* inappropriate for this key agreement, e.g., is of the wrong type or
* has an incompatible algorithm type.
*/
protected abstract void engineInit(Key key, SecureRandom random)
throws InvalidKeyException;
/**
* Initializes this key agreement with the given key, set of
* algorithm parameters, and source of randomness.
*
* @param key the party's private information. For example, in the case
* of the Diffie-Hellman key agreement, this would be the party's own
* Diffie-Hellman private key.
* @param params the key agreement parameters
* @param random the source of randomness
*
* @exception InvalidKeyException if the given key is
* inappropriate for this key agreement, e.g., is of the wrong type or
* has an incompatible algorithm type.
* @exception InvalidAlgorithmParameterException if the given parameters
* are inappropriate for this key agreement.
*/
protected abstract void engineInit(Key key, AlgorithmParameterSpec params,
SecureRandom random)
throws InvalidKeyException, InvalidAlgorithmParameterException;
/**
* Executes the next phase of this key agreement with the given
* key that was received from one of the other parties involved in this key
* agreement.
*
* @param key the key for this phase. For example, in the case of
* Diffie-Hellman between 2 parties, this would be the other party's
* Diffie-Hellman public key.
* @param lastPhase flag which indicates whether or not this is the last
* phase of this key agreement.
*
* @return the (intermediate) key resulting from this phase, or null if
* this phase does not yield a key
*
* @exception InvalidKeyException if the given key is inappropriate for
* this phase.
* @exception IllegalStateException if this key agreement has not been
* initialized.
*/
protected abstract Key engineDoPhase(Key key, boolean lastPhase)
throws InvalidKeyException, IllegalStateException;
/**
* Generates the shared secret and returns it in a new buffer.
*
* <p>This method resets this <code>KeyAgreementSpi</code> object,
* so that it
* can be reused for further key agreements. Unless this key agreement is
* reinitialized with one of the <code>engineInit</code> methods, the same
* private information and algorithm parameters will be used for
* subsequent key agreements.
*
* @return the new buffer with the shared secret
*
* @exception IllegalStateException if this key agreement has not been
* completed yet
*/
protected abstract byte[] engineGenerateSecret()
throws IllegalStateException;
/**
* Generates the shared secret, and places it into the buffer
* <code>sharedSecret</code>, beginning at <code>offset</code> inclusive.
*
* <p>If the <code>sharedSecret</code> buffer is too small to hold the
* result, a <code>ShortBufferException</code> is thrown.
* In this case, this call should be repeated with a larger output buffer.
*
* <p>This method resets this <code>KeyAgreementSpi</code> object,
* so that it
* can be reused for further key agreements. Unless this key agreement is
* reinitialized with one of the <code>engineInit</code> methods, the same
* private information and algorithm parameters will be used for
* subsequent key agreements.
*
* @param sharedSecret the buffer for the shared secret
* @param offset the offset in <code>sharedSecret</code> where the
* shared secret will be stored
*
* @return the number of bytes placed into <code>sharedSecret</code>
*
* @exception IllegalStateException if this key agreement has not been
* completed yet
* @exception ShortBufferException if the given output buffer is too small
* to hold the secret
*/
protected abstract int engineGenerateSecret(byte[] sharedSecret,
int offset)
throws IllegalStateException, ShortBufferException;
/**
* Creates the shared secret and returns it as a secret key object
* of the requested algorithm type.
*
* <p>This method resets this <code>KeyAgreementSpi</code> object,
* so that it
* can be reused for further key agreements. Unless this key agreement is
* reinitialized with one of the <code>engineInit</code> methods, the same
* private information and algorithm parameters will be used for
* subsequent key agreements.
*
* @param algorithm the requested secret key algorithm
*
* @return the shared secret key
*
* @exception IllegalStateException if this key agreement has not been
* completed yet
* @exception NoSuchAlgorithmException if the requested secret key
* algorithm is not available
* @exception InvalidKeyException if the shared secret key material cannot
* be used to generate a secret key of the requested algorithm type (e.g.,
* the key material is too short)
*/
protected abstract SecretKey engineGenerateSecret(String algorithm)
throws IllegalStateException, NoSuchAlgorithmException,
InvalidKeyException;
}

View File

@@ -0,0 +1,556 @@
/*
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact 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.crypto;
import java.util.*;
import java.security.*;
import java.security.Provider.Service;
import java.security.spec.*;
import sun.security.jca.*;
import sun.security.jca.GetInstance.Instance;
import sun.security.util.Debug;
/**
* This class provides the functionality of a secret (symmetric) key generator.
*
* <p>Key generators are constructed using one of the {@code getInstance}
* class methods of this class.
*
* <p>KeyGenerator objects are reusable, i.e., after a key has been
* generated, the same KeyGenerator object can be re-used to generate further
* keys.
*
* <p>There are two ways to generate a key: in an algorithm-independent
* manner, and in an algorithm-specific manner.
* The only difference between the two is the initialization of the object:
*
* <ul>
* <li><b>Algorithm-Independent Initialization</b>
* <p>All key generators share the concepts of a <i>keysize</i> and a
* <i>source of randomness</i>.
* There is an
* {@link #init(int, java.security.SecureRandom) init}
* method in this KeyGenerator class that takes these two universally
* shared types of arguments. There is also one that takes just a
* {@code keysize} argument, and uses the SecureRandom implementation
* of the highest-priority installed provider as the source of randomness
* (or a system-provided source of randomness if none of the installed
* providers supply a SecureRandom implementation), and one that takes just a
* source of randomness.
*
* <p>Since no other parameters are specified when you call the above
* algorithm-independent {@code init} methods, it is up to the
* provider what to do about the algorithm-specific parameters (if any) to be
* associated with each of the keys.
*
* <li><b>Algorithm-Specific Initialization</b>
* <p>For situations where a set of algorithm-specific parameters already
* exists, there are two
* {@link #init(java.security.spec.AlgorithmParameterSpec) init}
* methods that have an {@code AlgorithmParameterSpec}
* argument. One also has a {@code SecureRandom} argument, while the
* other uses the SecureRandom implementation
* of the highest-priority installed provider as the source of randomness
* (or a system-provided source of randomness if none of the installed
* providers supply a SecureRandom implementation).
* </ul>
*
* <p>In case the client does not explicitly initialize the KeyGenerator
* (via a call to an {@code init} method), each provider must
* supply (and document) a default initialization.
*
* <p> Every implementation of the Java platform is required to support the
* following standard {@code KeyGenerator} algorithms with the keysizes in
* parentheses:
* <ul>
* <li>{@code AES} (128)</li>
* <li>{@code DES} (56)</li>
* <li>{@code DESede} (168)</li>
* <li>{@code HmacSHA1}</li>
* <li>{@code HmacSHA256}</li>
* </ul>
* These algorithms are described in the <a href=
* "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyGenerator">
* KeyGenerator section</a> of the
* Java Cryptography Architecture Standard Algorithm Name Documentation.
* Consult the release documentation for your implementation to see if any
* other algorithms are supported.
*
* @author Jan Luehe
*
* @see SecretKey
* @since 1.4
*/
public class KeyGenerator {
private static final Debug pdebug =
Debug.getInstance("provider", "Provider");
private static final boolean skipDebug =
Debug.isOn("engine=") && !Debug.isOn("keygenerator");
// see java.security.KeyPairGenerator for failover notes
private final static int I_NONE = 1;
private final static int I_RANDOM = 2;
private final static int I_PARAMS = 3;
private final static int I_SIZE = 4;
// The provider
private Provider provider;
// The provider implementation (delegate)
private volatile KeyGeneratorSpi spi;
// The algorithm
private final String algorithm;
private final Object lock = new Object();
private Iterator<Service> serviceIterator;
private int initType;
private int initKeySize;
private AlgorithmParameterSpec initParams;
private SecureRandom initRandom;
/**
* Creates a KeyGenerator object.
*
* @param keyGenSpi the delegate
* @param provider the provider
* @param algorithm the algorithm
*/
protected KeyGenerator(KeyGeneratorSpi keyGenSpi, Provider provider,
String algorithm) {
this.spi = keyGenSpi;
this.provider = provider;
this.algorithm = algorithm;
if (!skipDebug && pdebug != null) {
pdebug.println("KeyGenerator." + algorithm + " algorithm from: " +
this.provider.getName());
}
}
private KeyGenerator(String algorithm) throws NoSuchAlgorithmException {
this.algorithm = algorithm;
List<Service> list =
GetInstance.getServices("KeyGenerator", algorithm);
serviceIterator = list.iterator();
initType = I_NONE;
// fetch and instantiate initial spi
if (nextSpi(null, false) == null) {
throw new NoSuchAlgorithmException
(algorithm + " KeyGenerator not available");
}
if (!skipDebug && pdebug != null) {
pdebug.println("KeyGenerator." + algorithm + " algorithm from: " +
this.provider.getName());
}
}
/**
* Returns the algorithm name of this {@code KeyGenerator} object.
*
* <p>This is the same name that was specified in one of the
* {@code getInstance} calls that created this
* {@code KeyGenerator} object.
*
* @return the algorithm name of this {@code KeyGenerator} object.
*/
public final String getAlgorithm() {
return this.algorithm;
}
/**
* Returns a {@code KeyGenerator} object that generates secret keys
* for the specified algorithm.
*
* <p> This method traverses the list of registered security Providers,
* starting with the most preferred Provider.
* A new KeyGenerator object encapsulating the
* KeyGeneratorSpi implementation from the first
* Provider that supports the specified algorithm is returned.
*
* <p> Note that the list of registered providers may be retrieved via
* the {@link Security#getProviders() Security.getProviders()} method.
*
* @param algorithm the standard name of the requested key algorithm.
* See the KeyGenerator section in the <a href=
* "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyGenerator">
* Java Cryptography Architecture Standard Algorithm Name Documentation</a>
* for information about standard algorithm names.
*
* @return the new {@code KeyGenerator} object.
*
* @exception NullPointerException if the specified algorithm is null.
*
* @exception NoSuchAlgorithmException if no Provider supports a
* KeyGeneratorSpi implementation for the
* specified algorithm.
*
* @see java.security.Provider
*/
public static final KeyGenerator getInstance(String algorithm)
throws NoSuchAlgorithmException {
return new KeyGenerator(algorithm);
}
/**
* Returns a {@code KeyGenerator} object that generates secret keys
* for the specified algorithm.
*
* <p> A new KeyGenerator object encapsulating the
* KeyGeneratorSpi implementation from the specified provider
* is returned. The specified provider must be registered
* in the security provider list.
*
* <p> Note that the list of registered providers may be retrieved via
* the {@link Security#getProviders() Security.getProviders()} method.
*
* @param algorithm the standard name of the requested key algorithm.
* See the KeyGenerator section in the <a href=
* "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyGenerator">
* Java Cryptography Architecture Standard Algorithm Name Documentation</a>
* for information about standard algorithm names.
*
* @param provider the name of the provider.
*
* @return the new {@code KeyGenerator} object.
*
* @exception NullPointerException if the specified algorithm is null.
*
* @exception NoSuchAlgorithmException if a KeyGeneratorSpi
* implementation for the specified algorithm is not
* available from the specified provider.
*
* @exception NoSuchProviderException if the specified provider is not
* registered in the security provider list.
*
* @exception IllegalArgumentException if the {@code provider}
* is null or empty.
*
* @see java.security.Provider
*/
public static final KeyGenerator getInstance(String algorithm,
String provider) throws NoSuchAlgorithmException,
NoSuchProviderException {
Instance instance = JceSecurity.getInstance("KeyGenerator",
KeyGeneratorSpi.class, algorithm, provider);
return new KeyGenerator((KeyGeneratorSpi)instance.impl,
instance.provider, algorithm);
}
/**
* Returns a {@code KeyGenerator} object that generates secret keys
* for the specified algorithm.
*
* <p> A new KeyGenerator object encapsulating the
* KeyGeneratorSpi implementation from the specified Provider
* object is returned. Note that the specified Provider object
* does not have to be registered in the provider list.
*
* @param algorithm the standard name of the requested key algorithm.
* See the KeyGenerator section in the <a href=
* "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyGenerator">
* Java Cryptography Architecture Standard Algorithm Name Documentation</a>
* for information about standard algorithm names.
*
* @param provider the provider.
*
* @return the new {@code KeyGenerator} object.
*
* @exception NullPointerException if the specified algorithm is null.
*
* @exception NoSuchAlgorithmException if a KeyGeneratorSpi
* implementation for the specified algorithm is not available
* from the specified Provider object.
*
* @exception IllegalArgumentException if the {@code provider}
* is null.
*
* @see java.security.Provider
*/
public static final KeyGenerator getInstance(String algorithm,
Provider provider) throws NoSuchAlgorithmException {
Instance instance = JceSecurity.getInstance("KeyGenerator",
KeyGeneratorSpi.class, algorithm, provider);
return new KeyGenerator((KeyGeneratorSpi)instance.impl,
instance.provider, algorithm);
}
/**
* Returns the provider of this {@code KeyGenerator} object.
*
* @return the provider of this {@code KeyGenerator} object
*/
public final Provider getProvider() {
synchronized (lock) {
disableFailover();
return provider;
}
}
/**
* Update the active spi of this class and return the next
* implementation for failover. If no more implemenations are
* available, this method returns null. However, the active spi of
* this class is never set to null.
*/
private KeyGeneratorSpi nextSpi(KeyGeneratorSpi oldSpi,
boolean reinit) {
synchronized (lock) {
// somebody else did a failover concurrently
// try that spi now
if ((oldSpi != null) && (oldSpi != spi)) {
return spi;
}
if (serviceIterator == null) {
return null;
}
while (serviceIterator.hasNext()) {
Service s = serviceIterator.next();
if (JceSecurity.canUseProvider(s.getProvider()) == false) {
continue;
}
try {
Object inst = s.newInstance(null);
// ignore non-spis
if (inst instanceof KeyGeneratorSpi == false) {
continue;
}
KeyGeneratorSpi spi = (KeyGeneratorSpi)inst;
if (reinit) {
if (initType == I_SIZE) {
spi.engineInit(initKeySize, initRandom);
} else if (initType == I_PARAMS) {
spi.engineInit(initParams, initRandom);
} else if (initType == I_RANDOM) {
spi.engineInit(initRandom);
} else if (initType != I_NONE) {
throw new AssertionError
("KeyGenerator initType: " + initType);
}
}
provider = s.getProvider();
this.spi = spi;
return spi;
} catch (Exception e) {
// ignore
}
}
disableFailover();
return null;
}
}
void disableFailover() {
serviceIterator = null;
initType = 0;
initParams = null;
initRandom = null;
}
/**
* Initializes this key generator.
*
* @param random the source of randomness for this generator
*/
public final void init(SecureRandom random) {
if (serviceIterator == null) {
spi.engineInit(random);
return;
}
RuntimeException failure = null;
KeyGeneratorSpi mySpi = spi;
do {
try {
mySpi.engineInit(random);
initType = I_RANDOM;
initKeySize = 0;
initParams = null;
initRandom = random;
return;
} catch (RuntimeException e) {
if (failure == null) {
failure = e;
}
mySpi = nextSpi(mySpi, false);
}
} while (mySpi != null);
throw failure;
}
/**
* Initializes this key generator with the specified parameter set.
*
* <p> If this key generator requires any random bytes, it will get them
* using the
* {@link java.security.SecureRandom}
* implementation of the highest-priority installed
* provider as the source of randomness.
* (If none of the installed providers supply an implementation of
* SecureRandom, a system-provided source of randomness will be used.)
*
* @param params the key generation parameters
*
* @exception InvalidAlgorithmParameterException if the given parameters
* are inappropriate for this key generator
*/
public final void init(AlgorithmParameterSpec params)
throws InvalidAlgorithmParameterException
{
init(params, JceSecurity.RANDOM);
}
/**
* Initializes this key generator with the specified parameter
* set and a user-provided source of randomness.
*
* @param params the key generation parameters
* @param random the source of randomness for this key generator
*
* @exception InvalidAlgorithmParameterException if {@code params} is
* inappropriate for this key generator
*/
public final void init(AlgorithmParameterSpec params, SecureRandom random)
throws InvalidAlgorithmParameterException
{
if (serviceIterator == null) {
spi.engineInit(params, random);
return;
}
Exception failure = null;
KeyGeneratorSpi mySpi = spi;
do {
try {
mySpi.engineInit(params, random);
initType = I_PARAMS;
initKeySize = 0;
initParams = params;
initRandom = random;
return;
} catch (Exception e) {
if (failure == null) {
failure = e;
}
mySpi = nextSpi(mySpi, false);
}
} while (mySpi != null);
if (failure instanceof InvalidAlgorithmParameterException) {
throw (InvalidAlgorithmParameterException)failure;
}
if (failure instanceof RuntimeException) {
throw (RuntimeException)failure;
}
throw new InvalidAlgorithmParameterException("init() failed", failure);
}
/**
* Initializes this key generator for a certain keysize.
*
* <p> If this key generator requires any random bytes, it will get them
* using the
* {@link java.security.SecureRandom}
* implementation of the highest-priority installed
* provider as the source of randomness.
* (If none of the installed providers supply an implementation of
* SecureRandom, a system-provided source of randomness will be used.)
*
* @param keysize the keysize. This is an algorithm-specific metric,
* specified in number of bits.
*
* @exception InvalidParameterException if the keysize is wrong or not
* supported.
*/
public final void init(int keysize) {
init(keysize, JceSecurity.RANDOM);
}
/**
* Initializes this key generator for a certain keysize, using a
* user-provided source of randomness.
*
* @param keysize the keysize. This is an algorithm-specific metric,
* specified in number of bits.
* @param random the source of randomness for this key generator
*
* @exception InvalidParameterException if the keysize is wrong or not
* supported.
*/
public final void init(int keysize, SecureRandom random) {
if (serviceIterator == null) {
spi.engineInit(keysize, random);
return;
}
RuntimeException failure = null;
KeyGeneratorSpi mySpi = spi;
do {
try {
mySpi.engineInit(keysize, random);
initType = I_SIZE;
initKeySize = keysize;
initParams = null;
initRandom = random;
return;
} catch (RuntimeException e) {
if (failure == null) {
failure = e;
}
mySpi = nextSpi(mySpi, false);
}
} while (mySpi != null);
throw failure;
}
/**
* Generates a secret key.
*
* @return the new key
*/
public final SecretKey generateKey() {
if (serviceIterator == null) {
return spi.engineGenerateKey();
}
RuntimeException failure = null;
KeyGeneratorSpi mySpi = spi;
do {
try {
return mySpi.engineGenerateKey();
} catch (RuntimeException e) {
if (failure == null) {
failure = e;
}
mySpi = nextSpi(mySpi, true);
}
} while (mySpi != null);
throw failure;
}
}

View File

@@ -0,0 +1,86 @@
/*
* Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.crypto;
import java.security.*;
import java.security.spec.*;
/**
* This class defines the <i>Service Provider Interface</i> (<b>SPI</b>)
* for the <code>KeyGenerator</code> class.
* All the abstract methods in this class must be implemented by each
* cryptographic service provider who wishes to supply the implementation
* of a key generator for a particular algorithm.
*
* @author Jan Luehe
*
* @see SecretKey
* @since 1.4
*/
public abstract class KeyGeneratorSpi {
/**
* Initializes the key generator.
*
* @param random the source of randomness for this generator
*/
protected abstract void engineInit(SecureRandom random);
/**
* Initializes the key generator with the specified parameter
* set and a user-provided source of randomness.
*
* @param params the key generation parameters
* @param random the source of randomness for this key generator
*
* @exception InvalidAlgorithmParameterException if <code>params</code> is
* inappropriate for this key generator
*/
protected abstract void engineInit(AlgorithmParameterSpec params,
SecureRandom random)
throws InvalidAlgorithmParameterException;
/**
* Initializes this key generator for a certain keysize, using the given
* source of randomness.
*
* @param keysize the keysize. This is an algorithm-specific metric,
* specified in number of bits.
* @param random the source of randomness for this key generator
*
* @exception InvalidParameterException if the keysize is wrong or not
* supported.
*/
protected abstract void engineInit(int keysize, SecureRandom random);
/**
* Generates a secret key.
*
* @return the new key
*/
protected abstract SecretKey engineGenerateKey();
}

View File

@@ -0,0 +1,672 @@
/*
* Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact 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.crypto;
import java.util.*;
import java.security.*;
import java.security.Provider.Service;
import java.security.spec.AlgorithmParameterSpec;
import java.nio.ByteBuffer;
import sun.security.util.Debug;
import sun.security.jca.*;
import sun.security.jca.GetInstance.Instance;
/**
* This class provides the functionality of a "Message Authentication Code"
* (MAC) algorithm.
*
* <p> A MAC provides a way to check
* the integrity of information transmitted over or stored in an unreliable
* medium, based on a secret key. Typically, message
* authentication codes are used between two parties that share a secret
* key in order to validate information transmitted between these
* parties.
*
* <p> A MAC mechanism that is based on cryptographic hash functions is
* referred to as HMAC. HMAC can be used with any cryptographic hash function,
* e.g., SHA256 or SHA384, in combination with a secret shared key. HMAC is
* specified in RFC 2104.
*
* <p> Every implementation of the Java platform is required to support
* the following standard {@code Mac} algorithms:
* <ul>
* <li>{@code HmacMD5}</li>
* <li>{@code HmacSHA1}</li>
* <li>{@code HmacSHA256}</li>
* </ul>
* These algorithms are described in the
* <a href="{@docRoot}/../technotes/guides/security/StandardNames.html#Mac">
* Mac section</a> of the
* Java Cryptography Architecture Standard Algorithm Name Documentation.
* Consult the release documentation for your implementation to see if any
* other algorithms are supported.
*
* @author Jan Luehe
*
* @since 1.4
*/
public class Mac implements Cloneable {
private static final Debug debug =
Debug.getInstance("jca", "Mac");
private static final Debug pdebug =
Debug.getInstance("provider", "Provider");
private static final boolean skipDebug =
Debug.isOn("engine=") && !Debug.isOn("mac");
// The provider
private Provider provider;
// The provider implementation (delegate)
private MacSpi spi;
// The name of the MAC algorithm.
private final String algorithm;
// Has this object been initialized?
private boolean initialized = false;
// next service to try in provider selection
// null once provider is selected
private Service firstService;
// remaining services to try in provider selection
// null once provider is selected
private Iterator<Service> serviceIterator;
private final Object lock;
/**
* Creates a MAC object.
*
* @param macSpi the delegate
* @param provider the provider
* @param algorithm the algorithm
*/
protected Mac(MacSpi macSpi, Provider provider, String algorithm) {
this.spi = macSpi;
this.provider = provider;
this.algorithm = algorithm;
serviceIterator = null;
lock = null;
}
private Mac(Service s, Iterator<Service> t, String algorithm) {
firstService = s;
serviceIterator = t;
this.algorithm = algorithm;
lock = new Object();
}
/**
* Returns the algorithm name of this {@code Mac} object.
*
* <p>This is the same name that was specified in one of the
* {@code getInstance} calls that created this
* {@code Mac} object.
*
* @return the algorithm name of this {@code Mac} object.
*/
public final String getAlgorithm() {
return this.algorithm;
}
/**
* Returns a {@code Mac} object that implements the
* specified MAC algorithm.
*
* <p> This method traverses the list of registered security Providers,
* starting with the most preferred Provider.
* A new Mac object encapsulating the
* MacSpi implementation from the first
* Provider that supports the specified algorithm is returned.
*
* <p> Note that the list of registered providers may be retrieved via
* the {@link Security#getProviders() Security.getProviders()} method.
*
* @param algorithm the standard name of the requested MAC algorithm.
* See the Mac section in the <a href=
* "{@docRoot}/../technotes/guides/security/StandardNames.html#Mac">
* Java Cryptography Architecture Standard Algorithm Name Documentation</a>
* for information about standard algorithm names.
*
* @return the new {@code Mac} object.
*
* @exception NoSuchAlgorithmException if no Provider supports a
* MacSpi implementation for the
* specified algorithm.
*
* @see java.security.Provider
*/
public static final Mac getInstance(String algorithm)
throws NoSuchAlgorithmException {
List<Service> services = GetInstance.getServices("Mac", algorithm);
// make sure there is at least one service from a signed provider
Iterator<Service> t = services.iterator();
while (t.hasNext()) {
Service s = t.next();
if (JceSecurity.canUseProvider(s.getProvider()) == false) {
continue;
}
return new Mac(s, t, algorithm);
}
throw new NoSuchAlgorithmException
("Algorithm " + algorithm + " not available");
}
/**
* Returns a {@code Mac} object that implements the
* specified MAC algorithm.
*
* <p> A new Mac object encapsulating the
* MacSpi implementation from the specified provider
* is returned. The specified provider must be registered
* in the security provider list.
*
* <p> Note that the list of registered providers may be retrieved via
* the {@link Security#getProviders() Security.getProviders()} method.
*
* @param algorithm the standard name of the requested MAC algorithm.
* See the Mac section in the <a href=
* "{@docRoot}/../technotes/guides/security/StandardNames.html#Mac">
* Java Cryptography Architecture Standard Algorithm Name Documentation</a>
* for information about standard algorithm names.
*
* @param provider the name of the provider.
*
* @return the new {@code Mac} object.
*
* @exception NoSuchAlgorithmException if a MacSpi
* implementation for the specified algorithm is not
* available from the specified provider.
*
* @exception NoSuchProviderException if the specified provider is not
* registered in the security provider list.
*
* @exception IllegalArgumentException if the {@code provider}
* is null or empty.
*
* @see java.security.Provider
*/
public static final Mac getInstance(String algorithm, String provider)
throws NoSuchAlgorithmException, NoSuchProviderException {
Instance instance = JceSecurity.getInstance
("Mac", MacSpi.class, algorithm, provider);
return new Mac((MacSpi)instance.impl, instance.provider, algorithm);
}
/**
* Returns a {@code Mac} object that implements the
* specified MAC algorithm.
*
* <p> A new Mac object encapsulating the
* MacSpi implementation from the specified Provider
* object is returned. Note that the specified Provider object
* does not have to be registered in the provider list.
*
* @param algorithm the standard name of the requested MAC algorithm.
* See the Mac section in the <a href=
* "{@docRoot}/../technotes/guides/security/StandardNames.html#Mac">
* Java Cryptography Architecture Standard Algorithm Name Documentation</a>
* for information about standard algorithm names.
*
* @param provider the provider.
*
* @return the new {@code Mac} object.
*
* @exception NoSuchAlgorithmException if a MacSpi
* implementation for the specified algorithm is not available
* from the specified Provider object.
*
* @exception IllegalArgumentException if the {@code provider}
* is null.
*
* @see java.security.Provider
*/
public static final Mac getInstance(String algorithm, Provider provider)
throws NoSuchAlgorithmException {
Instance instance = JceSecurity.getInstance
("Mac", MacSpi.class, algorithm, provider);
return new Mac((MacSpi)instance.impl, instance.provider, algorithm);
}
// max number of debug warnings to print from chooseFirstProvider()
private static int warnCount = 10;
/**
* Choose the Spi from the first provider available. Used if
* delayed provider selection is not possible because init()
* is not the first method called.
*/
void chooseFirstProvider() {
if ((spi != null) || (serviceIterator == null)) {
return;
}
synchronized (lock) {
if (spi != null) {
return;
}
if (debug != null) {
int w = --warnCount;
if (w >= 0) {
debug.println("Mac.init() not first method "
+ "called, disabling delayed provider selection");
if (w == 0) {
debug.println("Further warnings of this type will "
+ "be suppressed");
}
new Exception("Call trace").printStackTrace();
}
}
Exception lastException = null;
while ((firstService != null) || serviceIterator.hasNext()) {
Service s;
if (firstService != null) {
s = firstService;
firstService = null;
} else {
s = serviceIterator.next();
}
if (JceSecurity.canUseProvider(s.getProvider()) == false) {
continue;
}
try {
Object obj = s.newInstance(null);
if (obj instanceof MacSpi == false) {
continue;
}
spi = (MacSpi)obj;
provider = s.getProvider();
// not needed any more
firstService = null;
serviceIterator = null;
return;
} catch (NoSuchAlgorithmException e) {
lastException = e;
}
}
ProviderException e = new ProviderException
("Could not construct MacSpi instance");
if (lastException != null) {
e.initCause(lastException);
}
throw e;
}
}
private void chooseProvider(Key key, AlgorithmParameterSpec params)
throws InvalidKeyException, InvalidAlgorithmParameterException {
synchronized (lock) {
if (spi != null) {
spi.engineInit(key, params);
return;
}
Exception lastException = null;
while ((firstService != null) || serviceIterator.hasNext()) {
Service s;
if (firstService != null) {
s = firstService;
firstService = null;
} else {
s = serviceIterator.next();
}
// if provider says it does not support this key, ignore it
if (s.supportsParameter(key) == false) {
continue;
}
if (JceSecurity.canUseProvider(s.getProvider()) == false) {
continue;
}
try {
MacSpi spi = (MacSpi)s.newInstance(null);
spi.engineInit(key, params);
provider = s.getProvider();
this.spi = spi;
firstService = null;
serviceIterator = null;
return;
} catch (Exception e) {
// NoSuchAlgorithmException from newInstance()
// InvalidKeyException from init()
// RuntimeException (ProviderException) from init()
if (lastException == null) {
lastException = e;
}
}
}
// no working provider found, fail
if (lastException instanceof InvalidKeyException) {
throw (InvalidKeyException)lastException;
}
if (lastException instanceof InvalidAlgorithmParameterException) {
throw (InvalidAlgorithmParameterException)lastException;
}
if (lastException instanceof RuntimeException) {
throw (RuntimeException)lastException;
}
String kName = (key != null) ? key.getClass().getName() : "(null)";
throw new InvalidKeyException
("No installed provider supports this key: "
+ kName, lastException);
}
}
/**
* Returns the provider of this {@code Mac} object.
*
* @return the provider of this {@code Mac} object.
*/
public final Provider getProvider() {
chooseFirstProvider();
return this.provider;
}
/**
* Returns the length of the MAC in bytes.
*
* @return the MAC length in bytes.
*/
public final int getMacLength() {
chooseFirstProvider();
return spi.engineGetMacLength();
}
/**
* Initializes this {@code Mac} object with the given key.
*
* @param key the key.
*
* @exception InvalidKeyException if the given key is inappropriate for
* initializing this MAC.
*/
public final void init(Key key) throws InvalidKeyException {
try {
if (spi != null) {
spi.engineInit(key, null);
} else {
chooseProvider(key, null);
}
} catch (InvalidAlgorithmParameterException e) {
throw new InvalidKeyException("init() failed", e);
}
initialized = true;
if (!skipDebug && pdebug != null) {
pdebug.println("Mac." + algorithm + " algorithm from: " +
this.provider.getName());
}
}
/**
* Initializes this {@code Mac} object with the given key and
* algorithm parameters.
*
* @param key the key.
* @param params the algorithm parameters.
*
* @exception InvalidKeyException if the given key is inappropriate for
* initializing this MAC.
* @exception InvalidAlgorithmParameterException if the given algorithm
* parameters are inappropriate for this MAC.
*/
public final void init(Key key, AlgorithmParameterSpec params)
throws InvalidKeyException, InvalidAlgorithmParameterException {
if (spi != null) {
spi.engineInit(key, params);
} else {
chooseProvider(key, params);
}
initialized = true;
if (!skipDebug && pdebug != null) {
pdebug.println("Mac." + algorithm + " algorithm from: " +
this.provider.getName());
}
}
/**
* Processes the given byte.
*
* @param input the input byte to be processed.
*
* @exception IllegalStateException if this {@code Mac} has not been
* initialized.
*/
public final void update(byte input) throws IllegalStateException {
chooseFirstProvider();
if (initialized == false) {
throw new IllegalStateException("MAC not initialized");
}
spi.engineUpdate(input);
}
/**
* Processes the given array of bytes.
*
* @param input the array of bytes to be processed.
*
* @exception IllegalStateException if this {@code Mac} has not been
* initialized.
*/
public final void update(byte[] input) throws IllegalStateException {
chooseFirstProvider();
if (initialized == false) {
throw new IllegalStateException("MAC not initialized");
}
if (input != null) {
spi.engineUpdate(input, 0, input.length);
}
}
/**
* Processes the first {@code len} bytes in {@code input},
* starting at {@code offset} inclusive.
*
* @param input the input buffer.
* @param offset the offset in {@code input} where the input starts.
* @param len the number of bytes to process.
*
* @exception IllegalStateException if this {@code Mac} has not been
* initialized.
*/
public final void update(byte[] input, int offset, int len)
throws IllegalStateException {
chooseFirstProvider();
if (initialized == false) {
throw new IllegalStateException("MAC not initialized");
}
if (input != null) {
if ((offset < 0) || (len > (input.length - offset)) || (len < 0))
throw new IllegalArgumentException("Bad arguments");
spi.engineUpdate(input, offset, len);
}
}
/**
* Processes {@code input.remaining()} bytes in the ByteBuffer
* {@code input}, starting at {@code input.position()}.
* Upon return, the buffer's position will be equal to its limit;
* its limit will not have changed.
*
* @param input the ByteBuffer
*
* @exception IllegalStateException if this {@code Mac} has not been
* initialized.
* @since 1.5
*/
public final void update(ByteBuffer input) {
chooseFirstProvider();
if (initialized == false) {
throw new IllegalStateException("MAC not initialized");
}
if (input == null) {
throw new IllegalArgumentException("Buffer must not be null");
}
spi.engineUpdate(input);
}
/**
* Finishes the MAC operation.
*
* <p>A call to this method resets this {@code Mac} object to the
* state it was in when previously initialized via a call to
* {@code init(Key)} or
* {@code init(Key, AlgorithmParameterSpec)}.
* That is, the object is reset and available to generate another MAC from
* the same key, if desired, via new calls to {@code update} and
* {@code doFinal}.
* (In order to reuse this {@code Mac} object with a different key,
* it must be reinitialized via a call to {@code init(Key)} or
* {@code init(Key, AlgorithmParameterSpec)}.
*
* @return the MAC result.
*
* @exception IllegalStateException if this {@code Mac} has not been
* initialized.
*/
public final byte[] doFinal() throws IllegalStateException {
chooseFirstProvider();
if (initialized == false) {
throw new IllegalStateException("MAC not initialized");
}
byte[] mac = spi.engineDoFinal();
spi.engineReset();
return mac;
}
/**
* Finishes the MAC operation.
*
* <p>A call to this method resets this {@code Mac} object to the
* state it was in when previously initialized via a call to
* {@code init(Key)} or
* {@code init(Key, AlgorithmParameterSpec)}.
* That is, the object is reset and available to generate another MAC from
* the same key, if desired, via new calls to {@code update} and
* {@code doFinal}.
* (In order to reuse this {@code Mac} object with a different key,
* it must be reinitialized via a call to {@code init(Key)} or
* {@code init(Key, AlgorithmParameterSpec)}.
*
* <p>The MAC result is stored in {@code output}, starting at
* {@code outOffset} inclusive.
*
* @param output the buffer where the MAC result is stored
* @param outOffset the offset in {@code output} where the MAC is
* stored
*
* @exception ShortBufferException if the given output buffer is too small
* to hold the result
* @exception IllegalStateException if this {@code Mac} has not been
* initialized.
*/
public final void doFinal(byte[] output, int outOffset)
throws ShortBufferException, IllegalStateException
{
chooseFirstProvider();
if (initialized == false) {
throw new IllegalStateException("MAC not initialized");
}
int macLen = getMacLength();
if (output == null || output.length-outOffset < macLen) {
throw new ShortBufferException
("Cannot store MAC in output buffer");
}
byte[] mac = doFinal();
System.arraycopy(mac, 0, output, outOffset, macLen);
return;
}
/**
* Processes the given array of bytes and finishes the MAC operation.
*
* <p>A call to this method resets this {@code Mac} object to the
* state it was in when previously initialized via a call to
* {@code init(Key)} or
* {@code init(Key, AlgorithmParameterSpec)}.
* That is, the object is reset and available to generate another MAC from
* the same key, if desired, via new calls to {@code update} and
* {@code doFinal}.
* (In order to reuse this {@code Mac} object with a different key,
* it must be reinitialized via a call to {@code init(Key)} or
* {@code init(Key, AlgorithmParameterSpec)}.
*
* @param input data in bytes
* @return the MAC result.
*
* @exception IllegalStateException if this {@code Mac} has not been
* initialized.
*/
public final byte[] doFinal(byte[] input) throws IllegalStateException
{
chooseFirstProvider();
if (initialized == false) {
throw new IllegalStateException("MAC not initialized");
}
update(input);
return doFinal();
}
/**
* Resets this {@code Mac} object.
*
* <p>A call to this method resets this {@code Mac} object to the
* state it was in when previously initialized via a call to
* {@code init(Key)} or
* {@code init(Key, AlgorithmParameterSpec)}.
* That is, the object is reset and available to generate another MAC from
* the same key, if desired, via new calls to {@code update} and
* {@code doFinal}.
* (In order to reuse this {@code Mac} object with a different key,
* it must be reinitialized via a call to {@code init(Key)} or
* {@code init(Key, AlgorithmParameterSpec)}.
*/
public final void reset() {
chooseFirstProvider();
spi.engineReset();
}
/**
* Returns a clone if the provider implementation is cloneable.
*
* @return a clone if the provider implementation is cloneable.
*
* @exception CloneNotSupportedException if this is called on a
* delegate that does not support {@code Cloneable}.
*/
public final Object clone() throws CloneNotSupportedException {
chooseFirstProvider();
Mac that = (Mac)super.clone();
that.spi = (MacSpi)this.spi.clone();
return that;
}
}

View File

@@ -0,0 +1,153 @@
/*
* Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.crypto;
import java.security.*;
import java.security.spec.*;
import java.nio.ByteBuffer;
/**
* This class defines the <i>Service Provider Interface</i> (<b>SPI</b>)
* for the <code>Mac</code> class.
* All the abstract methods in this class must be implemented by each
* cryptographic service provider who wishes to supply the implementation
* of a particular MAC algorithm.
*
* <p> Implementations are free to implement the Cloneable interface.
*
* @author Jan Luehe
*
* @since 1.4
*/
public abstract class MacSpi {
/**
* Returns the length of the MAC in bytes.
*
* @return the MAC length in bytes.
*/
protected abstract int engineGetMacLength();
/**
* Initializes the MAC with the given (secret) key and algorithm
* parameters.
*
* @param key the (secret) key.
* @param params the algorithm parameters.
*
* @exception InvalidKeyException if the given key is inappropriate for
* initializing this MAC.
* @exception InvalidAlgorithmParameterException if the given algorithm
* parameters are inappropriate for this MAC.
*/
protected abstract void engineInit(Key key,
AlgorithmParameterSpec params)
throws InvalidKeyException, InvalidAlgorithmParameterException ;
/**
* Processes the given byte.
*
* @param input the input byte to be processed.
*/
protected abstract void engineUpdate(byte input);
/**
* Processes the first <code>len</code> bytes in <code>input</code>,
* starting at <code>offset</code> inclusive.
*
* @param input the input buffer.
* @param offset the offset in <code>input</code> where the input starts.
* @param len the number of bytes to process.
*/
protected abstract void engineUpdate(byte[] input, int offset, int len);
/**
* Processes <code>input.remaining()</code> bytes in the ByteBuffer
* <code>input</code>, starting at <code>input.position()</code>.
* Upon return, the buffer's position will be equal to its limit;
* its limit will not have changed.
*
* <p>Subclasses should consider overriding this method if they can
* process ByteBuffers more efficiently than byte arrays.
*
* @param input the ByteBuffer
* @since 1.5
*/
protected void engineUpdate(ByteBuffer input) {
if (input.hasRemaining() == false) {
return;
}
if (input.hasArray()) {
byte[] b = input.array();
int ofs = input.arrayOffset();
int pos = input.position();
int lim = input.limit();
engineUpdate(b, ofs + pos, lim - pos);
input.position(lim);
} else {
int len = input.remaining();
byte[] b = new byte[CipherSpi.getTempArraySize(len)];
while (len > 0) {
int chunk = Math.min(len, b.length);
input.get(b, 0, chunk);
engineUpdate(b, 0, chunk);
len -= chunk;
}
}
}
/**
* Completes the MAC computation and resets the MAC for further use,
* maintaining the secret key that the MAC was initialized with.
*
* @return the MAC result.
*/
protected abstract byte[] engineDoFinal();
/**
* Resets the MAC for further use, maintaining the secret key that the
* MAC was initialized with.
*/
protected abstract void engineReset();
/**
* Returns a clone if the implementation is cloneable.
*
* @return a clone if the implementation is cloneable.
*
* @exception CloneNotSupportedException if this is called
* on an implementation that does not support <code>Cloneable</code>.
*/
public Object clone() throws CloneNotSupportedException {
if (this instanceof Cloneable) {
return super.clone();
} else {
throw new CloneNotSupportedException();
}
}
}

View File

@@ -0,0 +1,61 @@
/*
* Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.crypto;
import java.security.GeneralSecurityException;
/**
* This exception is thrown when a particular padding mechanism is
* requested but is not available in the environment.
*
* @author Jan Luehe
*
* @since 1.4
*/
public class NoSuchPaddingException extends GeneralSecurityException {
private static final long serialVersionUID = -4572885201200175466L;
/**
* Constructs a NoSuchPaddingException with no detail
* message. A detail message is a String that describes this
* particular exception.
*/
public NoSuchPaddingException() {
super();
}
/**
* Constructs a NoSuchPaddingException with the specified
* detail message.
*
* @param msg the detail message.
*/
public NoSuchPaddingException(String msg) {
super(msg);
}
}

View File

@@ -0,0 +1,47 @@
/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.crypto;
/**
* The NullCipher class is a class that provides an
* "identity cipher" -- one that does not transform the plain text. As
* a consequence, the ciphertext is identical to the plaintext. All
* initialization methods do nothing, while the blocksize is set to 1
* byte.
*
* @author Li Gong
* @since 1.4
*/
public class NullCipher extends Cipher {
/**
* Creates a NullCipher object.
*/
public NullCipher() {
super(new NullCipherSpi(), null);
}
}

View File

@@ -0,0 +1,113 @@
/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.crypto;
import java.security.*;
import java.security.spec.*;
/**
* This class provides a delegate for the identity cipher - one that does not
* transform the plain text.
*
* @author Li Gong
* @see NullCipher
*
* @since 1.4
*/
final class NullCipherSpi extends CipherSpi {
/*
* Do not let anybody instantiate this directly (protected).
*/
protected NullCipherSpi() {}
public void engineSetMode(String mode) {}
public void engineSetPadding(String padding) {}
protected int engineGetBlockSize() {
return 1;
}
protected int engineGetOutputSize(int inputLen) {
return inputLen;
}
protected byte[] engineGetIV() {
byte[] x = new byte[8];
return x;
}
protected AlgorithmParameters engineGetParameters() {
return null;
}
protected void engineInit(int mode, Key key, SecureRandom random) {}
protected void engineInit(int mode, Key key,
AlgorithmParameterSpec params,
SecureRandom random) {}
protected void engineInit(int mode, Key key,
AlgorithmParameters params,
SecureRandom random) {}
protected byte[] engineUpdate(byte[] input, int inputOffset,
int inputLen) {
if (input == null) return null;
byte[] x = new byte[inputLen];
System.arraycopy(input, inputOffset, x, 0, inputLen);
return x;
}
protected int engineUpdate(byte[] input, int inputOffset,
int inputLen, byte[] output,
int outputOffset) {
if (input == null) return 0;
System.arraycopy(input, inputOffset, output, outputOffset, inputLen);
return inputLen;
}
protected byte[] engineDoFinal(byte[] input, int inputOffset,
int inputLen)
{
return engineUpdate(input, inputOffset, inputLen);
}
protected int engineDoFinal(byte[] input, int inputOffset,
int inputLen, byte[] output,
int outputOffset)
{
return engineUpdate(input, inputOffset, inputLen,
output, outputOffset);
}
protected int engineGetKeySize(Key key)
{
return 0;
}
}

View File

@@ -0,0 +1,488 @@
/*
* Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact 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.crypto;
import sun.misc.SharedSecrets;
import java.io.*;
import java.security.AlgorithmParameters;
import java.security.Key;
import java.security.InvalidKeyException;
import java.security.InvalidAlgorithmParameterException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
/**
* This class enables a programmer to create an object and protect its
* confidentiality with a cryptographic algorithm.
*
* <p> Given any Serializable object, one can create a SealedObject
* that encapsulates the original object, in serialized
* format (i.e., a "deep copy"), and seals (encrypts) its serialized contents,
* using a cryptographic algorithm such as AES, to protect its
* confidentiality. The encrypted content can later be decrypted (with
* the corresponding algorithm using the correct decryption key) and
* de-serialized, yielding the original object.
*
* <p> Note that the Cipher object must be fully initialized with the
* correct algorithm, key, padding scheme, etc., before being applied
* to a SealedObject.
*
* <p> The original object that was sealed can be recovered in two different
* ways:
*
* <ul>
*
* <li>by using the {@link #getObject(javax.crypto.Cipher) getObject}
* method that takes a <code>Cipher</code> object.
*
* <p> This method requires a fully initialized <code>Cipher</code> object,
* initialized with the
* exact same algorithm, key, padding scheme, etc., that were used to seal the
* object.
*
* <p> This approach has the advantage that the party who unseals the
* sealed object does not require knowledge of the decryption key. For example,
* after one party has initialized the cipher object with the required
* decryption key, it could hand over the cipher object to
* another party who then unseals the sealed object.
*
* <li>by using one of the
* {@link #getObject(java.security.Key) getObject} methods
* that take a <code>Key</code> object.
*
* <p> In this approach, the <code>getObject</code> method creates a cipher
* object for the appropriate decryption algorithm and initializes it with the
* given decryption key and the algorithm parameters (if any) that were stored
* in the sealed object.
*
* <p> This approach has the advantage that the party who
* unseals the object does not need to keep track of the parameters (e.g., an
* IV) that were used to seal the object.
*
* </ul>
*
* @author Li Gong
* @author Jan Luehe
* @see Cipher
* @since 1.4
*/
public class SealedObject implements Serializable {
static final long serialVersionUID = 4482838265551344752L;
/**
* The serialized object contents in encrypted format.
*
* @serial
*/
private byte[] encryptedContent = null;
/**
* The algorithm that was used to seal this object.
*
* @serial
*/
private String sealAlg = null;
/**
* The algorithm of the parameters used.
*
* @serial
*/
private String paramsAlg = null;
/**
* The cryptographic parameters used by the sealing Cipher,
* encoded in the default format.
* <p>
* That is, <code>cipher.getParameters().getEncoded()</code>.
*
* @serial
*/
protected byte[] encodedParams = null;
/**
* Constructs a SealedObject from any Serializable object.
*
* <p>The given object is serialized, and its serialized contents are
* encrypted using the given Cipher, which must be fully initialized.
*
* <p>Any algorithm parameters that may be used in the encryption
* operation are stored inside of the new <code>SealedObject</code>.
*
* @param object the object to be sealed; can be null.
* @param c the cipher used to seal the object.
*
* @exception NullPointerException if the given cipher is null.
* @exception IOException if an error occurs during serialization
* @exception IllegalBlockSizeException if the given cipher is a block
* cipher, no padding has been requested, and the total input length
* (i.e., the length of the serialized object contents) is not a multiple
* of the cipher's block size
*/
public SealedObject(Serializable object, Cipher c) throws IOException,
IllegalBlockSizeException
{
/*
* Serialize the object
*/
// creating a stream pipe-line, from a to b
ByteArrayOutputStream b = new ByteArrayOutputStream();
ObjectOutput a = new ObjectOutputStream(b);
byte[] content;
try {
// write and flush the object content to byte array
a.writeObject(object);
a.flush();
content = b.toByteArray();
} finally {
a.close();
}
/*
* Seal the object
*/
try {
this.encryptedContent = c.doFinal(content);
}
catch (BadPaddingException ex) {
// if sealing is encryption only
// Should never happen??
}
// Save the parameters
if (c.getParameters() != null) {
this.encodedParams = c.getParameters().getEncoded();
this.paramsAlg = c.getParameters().getAlgorithm();
}
// Save the encryption algorithm
this.sealAlg = c.getAlgorithm();
}
/**
* Constructs a SealedObject object from the passed-in SealedObject.
*
* @param so a SealedObject object
* @exception NullPointerException if the given sealed object is null.
*/
protected SealedObject(SealedObject so) {
this.encryptedContent = so.encryptedContent.clone();
this.sealAlg = so.sealAlg;
this.paramsAlg = so.paramsAlg;
if (so.encodedParams != null) {
this.encodedParams = so.encodedParams.clone();
} else {
this.encodedParams = null;
}
}
/**
* Returns the algorithm that was used to seal this object.
*
* @return the algorithm that was used to seal this object.
*/
public final String getAlgorithm() {
return this.sealAlg;
}
/**
* Retrieves the original (encapsulated) object.
*
* <p>This method creates a cipher for the algorithm that had been used in
* the sealing operation.
* If the default provider package provides an implementation of that
* algorithm, an instance of Cipher containing that implementation is used.
* If the algorithm is not available in the default package, other
* packages are searched.
* The Cipher object is initialized for decryption, using the given
* <code>key</code> and the parameters (if any) that had been used in the
* sealing operation.
*
* <p>The encapsulated object is unsealed and de-serialized, before it is
* returned.
*
* @param key the key used to unseal the object.
*
* @return the original object.
*
* @exception IOException if an error occurs during de-serialiazation.
* @exception ClassNotFoundException if an error occurs during
* de-serialiazation.
* @exception NoSuchAlgorithmException if the algorithm to unseal the
* object is not available.
* @exception InvalidKeyException if the given key cannot be used to unseal
* the object (e.g., it has the wrong algorithm).
* @exception NullPointerException if <code>key</code> is null.
*/
public final Object getObject(Key key)
throws IOException, ClassNotFoundException, NoSuchAlgorithmException,
InvalidKeyException
{
if (key == null) {
throw new NullPointerException("key is null");
}
try {
return unseal(key, null);
} catch (NoSuchProviderException nspe) {
// we've already caught NoSuchProviderException's and converted
// them into NoSuchAlgorithmException's with details about
// the failing algorithm
throw new NoSuchAlgorithmException("algorithm not found");
} catch (IllegalBlockSizeException ibse) {
throw new InvalidKeyException(ibse.getMessage());
} catch (BadPaddingException bpe) {
throw new InvalidKeyException(bpe.getMessage());
}
}
/**
* Retrieves the original (encapsulated) object.
*
* <p>The encapsulated object is unsealed (using the given Cipher,
* assuming that the Cipher is already properly initialized) and
* de-serialized, before it is returned.
*
* @param c the cipher used to unseal the object
*
* @return the original object.
*
* @exception NullPointerException if the given cipher is null.
* @exception IOException if an error occurs during de-serialiazation
* @exception ClassNotFoundException if an error occurs during
* de-serialiazation
* @exception IllegalBlockSizeException if the given cipher is a block
* cipher, no padding has been requested, and the total input length is
* not a multiple of the cipher's block size
* @exception BadPaddingException if the given cipher has been
* initialized for decryption, and padding has been specified, but
* the input data does not have proper expected padding bytes
*/
public final Object getObject(Cipher c)
throws IOException, ClassNotFoundException, IllegalBlockSizeException,
BadPaddingException
{
ObjectInput a = getExtObjectInputStream(c);
try {
Object obj = a.readObject();
return obj;
} finally {
a.close();
}
}
/**
* Retrieves the original (encapsulated) object.
*
* <p>This method creates a cipher for the algorithm that had been used in
* the sealing operation, using an implementation of that algorithm from
* the given <code>provider</code>.
* The Cipher object is initialized for decryption, using the given
* <code>key</code> and the parameters (if any) that had been used in the
* sealing operation.
*
* <p>The encapsulated object is unsealed and de-serialized, before it is
* returned.
*
* @param key the key used to unseal the object.
* @param provider the name of the provider of the algorithm to unseal
* the object.
*
* @return the original object.
*
* @exception IllegalArgumentException if the given provider is null
* or empty.
* @exception IOException if an error occurs during de-serialiazation.
* @exception ClassNotFoundException if an error occurs during
* de-serialiazation.
* @exception NoSuchAlgorithmException if the algorithm to unseal the
* object is not available.
* @exception NoSuchProviderException if the given provider is not
* configured.
* @exception InvalidKeyException if the given key cannot be used to unseal
* the object (e.g., it has the wrong algorithm).
* @exception NullPointerException if <code>key</code> is null.
*/
public final Object getObject(Key key, String provider)
throws IOException, ClassNotFoundException, NoSuchAlgorithmException,
NoSuchProviderException, InvalidKeyException
{
if (key == null) {
throw new NullPointerException("key is null");
}
if (provider == null || provider.length() == 0) {
throw new IllegalArgumentException("missing provider");
}
try {
return unseal(key, provider);
} catch (IllegalBlockSizeException | BadPaddingException ex) {
throw new InvalidKeyException(ex.getMessage());
}
}
private Object unseal(Key key, String provider)
throws IOException, ClassNotFoundException, NoSuchAlgorithmException,
NoSuchProviderException, InvalidKeyException,
IllegalBlockSizeException, BadPaddingException
{
/*
* Create the parameter object.
*/
AlgorithmParameters params = null;
if (this.encodedParams != null) {
try {
if (provider != null)
params = AlgorithmParameters.getInstance(this.paramsAlg,
provider);
else
params = AlgorithmParameters.getInstance(this.paramsAlg);
} catch (NoSuchProviderException nspe) {
if (provider == null) {
throw new NoSuchAlgorithmException(this.paramsAlg
+ " not found");
} else {
throw new NoSuchProviderException(nspe.getMessage());
}
}
params.init(this.encodedParams);
}
/*
* Create and initialize the cipher.
*/
Cipher c;
try {
if (provider != null)
c = Cipher.getInstance(this.sealAlg, provider);
else
c = Cipher.getInstance(this.sealAlg);
} catch (NoSuchPaddingException nspe) {
throw new NoSuchAlgorithmException("Padding that was used in "
+ "sealing operation not "
+ "available");
} catch (NoSuchProviderException nspe) {
if (provider == null) {
throw new NoSuchAlgorithmException(this.sealAlg+" not found");
} else {
throw new NoSuchProviderException(nspe.getMessage());
}
}
try {
if (params != null)
c.init(Cipher.DECRYPT_MODE, key, params);
else
c.init(Cipher.DECRYPT_MODE, key);
} catch (InvalidAlgorithmParameterException iape) {
// this should never happen, because we use the exact same
// parameters that were used in the sealing operation
throw new RuntimeException(iape.getMessage());
}
ObjectInput a = getExtObjectInputStream(c);
try {
Object obj = a.readObject();
return obj;
} finally {
a.close();
}
}
/**
* Restores the state of the SealedObject from a stream.
* @param s the object input stream.
* @exception NullPointerException if s is null.
*/
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException
{
s.defaultReadObject();
if (encryptedContent != null)
encryptedContent = encryptedContent.clone();
if (encodedParams != null)
encodedParams = encodedParams.clone();
}
// This method is also called inside SealedObjectForKeyProtector.java.
private ObjectInputStream getExtObjectInputStream(Cipher c)
throws BadPaddingException, IllegalBlockSizeException, IOException {
byte[] content = c.doFinal(this.encryptedContent);
ByteArrayInputStream b = new ByteArrayInputStream(content);
return new extObjectInputStream(b);
}
static {
SharedSecrets.setJavaxCryptoSealedObjectAccess((obj,c) -> obj.getExtObjectInputStream(c));
}
}
final class extObjectInputStream extends ObjectInputStream {
private static ClassLoader systemClassLoader = null;
extObjectInputStream(InputStream in)
throws IOException, StreamCorruptedException {
super(in);
}
protected Class<?> resolveClass(ObjectStreamClass v)
throws IOException, ClassNotFoundException
{
try {
/*
* Calling the super.resolveClass() first
* will let us pick up bug fixes in the super
* class (e.g., 4171142).
*/
return super.resolveClass(v);
} catch (ClassNotFoundException cnfe) {
/*
* This is a workaround for bug 4224921.
*/
ClassLoader loader = Thread.currentThread().getContextClassLoader();
if (loader == null) {
if (systemClassLoader == null) {
systemClassLoader = ClassLoader.getSystemClassLoader();
}
loader = systemClassLoader;
if (loader == null) {
throw new ClassNotFoundException(v.getName());
}
}
return Class.forName(v.getName(), false, loader);
}
}
}

View File

@@ -0,0 +1,68 @@
/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.crypto;
/**
* A secret (symmetric) key.
* The purpose of this interface is to group (and provide type safety
* for) all secret key interfaces.
* <p>
* Provider implementations of this interface must overwrite the
* {@code equals} and {@code hashCode} methods inherited from
* {@link java.lang.Object}, so that secret keys are compared based on
* their underlying key material and not based on reference.
* Implementations should override the default {@code destroy} and
* {@code isDestroyed} methods from the
* {@link javax.security.auth.Destroyable} interface to enable
* sensitive key information to be destroyed, cleared, or in the case
* where such information is immutable, unreferenced.
* Finally, since {@code SecretKey} is {@code Serializable}, implementations
* should also override
* {@link java.io.ObjectOutputStream#writeObject(java.lang.Object)}
* to prevent keys that have been destroyed from being serialized.
*
* <p>Keys that implement this interface return the string {@code RAW}
* as their encoding format (see {@code getFormat}), and return the
* raw key bytes as the result of a {@code getEncoded} method call. (The
* {@code getFormat} and {@code getEncoded} methods are inherited
* from the {@link java.security.Key} parent interface.)
*
* @author Jan Luehe
*
* @see SecretKeyFactory
* @see Cipher
* @since 1.4
*/
public interface SecretKey extends
java.security.Key, javax.security.auth.Destroyable {
/**
* The class fingerprint that is set to indicate serialization
* compatibility since J2SE 1.4.
*/
static final long serialVersionUID = -4795878709595146952L;
}

View File

@@ -0,0 +1,429 @@
/*
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact 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.crypto;
import java.util.*;
import java.security.*;
import java.security.Provider.Service;
import java.security.spec.*;
import sun.security.jca.*;
import sun.security.jca.GetInstance.Instance;
/**
* This class represents a factory for secret keys.
*
* <P> Key factories are used to convert <I>keys</I> (opaque
* cryptographic keys of type {@code Key}) into <I>key specifications</I>
* (transparent representations of the underlying key material), and vice
* versa.
* Secret key factories operate only on secret (symmetric) keys.
*
* <P> Key factories are bi-directional, i.e., they allow to build an opaque
* key object from a given key specification (key material), or to retrieve
* the underlying key material of a key object in a suitable format.
*
* <P> Application developers should refer to their provider's documentation
* to find out which key specifications are supported by the
* {@link #generateSecret(java.security.spec.KeySpec) generateSecret} and
* {@link #getKeySpec(javax.crypto.SecretKey, java.lang.Class) getKeySpec}
* methods.
* For example, the DES secret-key factory supplied by the "SunJCE" provider
* supports {@code DESKeySpec} as a transparent representation of DES
* keys, and that provider's secret-key factory for Triple DES keys supports
* {@code DESedeKeySpec} as a transparent representation of Triple DES
* keys.
*
* <p> Every implementation of the Java platform is required to support the
* following standard {@code SecretKeyFactory} algorithms:
* <ul>
* <li>{@code DES}</li>
* <li>{@code DESede}</li>
* </ul>
* These algorithms are described in the <a href=
* "{@docRoot}/../technotes/guides/security/StandardNames.html#SecretKeyFactory">
* SecretKeyFactory section</a> of the
* Java Cryptography Architecture Standard Algorithm Name Documentation.
* Consult the release documentation for your implementation to see if any
* other algorithms are supported.
*
* @author Jan Luehe
*
* @see SecretKey
* @see javax.crypto.spec.DESKeySpec
* @see javax.crypto.spec.DESedeKeySpec
* @see javax.crypto.spec.PBEKeySpec
* @since 1.4
*/
public class SecretKeyFactory {
// The provider
private Provider provider;
// The algorithm associated with this factory
private final String algorithm;
// The provider implementation (delegate)
private volatile SecretKeyFactorySpi spi;
// lock for mutex during provider selection
private final Object lock = new Object();
// remaining services to try in provider selection
// null once provider is selected
private Iterator<Service> serviceIterator;
/**
* Creates a SecretKeyFactory object.
*
* @param keyFacSpi the delegate
* @param provider the provider
* @param algorithm the secret-key algorithm
*/
protected SecretKeyFactory(SecretKeyFactorySpi keyFacSpi,
Provider provider, String algorithm) {
this.spi = keyFacSpi;
this.provider = provider;
this.algorithm = algorithm;
}
private SecretKeyFactory(String algorithm) throws NoSuchAlgorithmException {
this.algorithm = algorithm;
List<Service> list =
GetInstance.getServices("SecretKeyFactory", algorithm);
serviceIterator = list.iterator();
// fetch and instantiate initial spi
if (nextSpi(null) == null) {
throw new NoSuchAlgorithmException
(algorithm + " SecretKeyFactory not available");
}
}
/**
* Returns a {@code SecretKeyFactory} object that converts
* secret keys of the specified algorithm.
*
* <p> This method traverses the list of registered security Providers,
* starting with the most preferred Provider.
* A new SecretKeyFactory object encapsulating the
* SecretKeyFactorySpi implementation from the first
* Provider that supports the specified algorithm is returned.
*
* <p> Note that the list of registered providers may be retrieved via
* the {@link Security#getProviders() Security.getProviders()} method.
*
* @param algorithm the standard name of the requested secret-key
* algorithm.
* See the SecretKeyFactory section in the <a href=
* "{@docRoot}/../technotes/guides/security/StandardNames.html#SecretKeyFactory">
* Java Cryptography Architecture Standard Algorithm Name Documentation</a>
* for information about standard algorithm names.
*
* @return the new {@code SecretKeyFactory} object.
*
* @exception NullPointerException if the specified algorithm
* is null.
*
* @exception NoSuchAlgorithmException if no Provider supports a
* SecretKeyFactorySpi implementation for the
* specified algorithm.
*
* @see java.security.Provider
*/
public static final SecretKeyFactory getInstance(String algorithm)
throws NoSuchAlgorithmException {
return new SecretKeyFactory(algorithm);
}
/**
* Returns a {@code SecretKeyFactory} object that converts
* secret keys of the specified algorithm.
*
* <p> A new SecretKeyFactory object encapsulating the
* SecretKeyFactorySpi implementation from the specified provider
* is returned. The specified provider must be registered
* in the security provider list.
*
* <p> Note that the list of registered providers may be retrieved via
* the {@link Security#getProviders() Security.getProviders()} method.
*
* @param algorithm the standard name of the requested secret-key
* algorithm.
* See the SecretKeyFactory section in the <a href=
* "{@docRoot}/../technotes/guides/security/StandardNames.html#SecretKeyFactory">
* Java Cryptography Architecture Standard Algorithm Name Documentation</a>
* for information about standard algorithm names.
*
* @param provider the name of the provider.
*
* @return the new {@code SecretKeyFactory} object.
*
* @exception NoSuchAlgorithmException if a SecretKeyFactorySpi
* implementation for the specified algorithm is not
* available from the specified provider.
*
* @exception NullPointerException if the specified algorithm
* is null.
*
* @throws NoSuchProviderException if the specified provider is not
* registered in the security provider list.
*
* @exception IllegalArgumentException if the {@code provider}
* is null or empty.
*
* @see java.security.Provider
*/
public static final SecretKeyFactory getInstance(String algorithm,
String provider) throws NoSuchAlgorithmException,
NoSuchProviderException {
Instance instance = JceSecurity.getInstance("SecretKeyFactory",
SecretKeyFactorySpi.class, algorithm, provider);
return new SecretKeyFactory((SecretKeyFactorySpi)instance.impl,
instance.provider, algorithm);
}
/**
* Returns a {@code SecretKeyFactory} object that converts
* secret keys of the specified algorithm.
*
* <p> A new SecretKeyFactory object encapsulating the
* SecretKeyFactorySpi implementation from the specified Provider
* object is returned. Note that the specified Provider object
* does not have to be registered in the provider list.
*
* @param algorithm the standard name of the requested secret-key
* algorithm.
* See the SecretKeyFactory section in the <a href=
* "{@docRoot}/../technotes/guides/security/StandardNames.html#SecretKeyFactory">
* Java Cryptography Architecture Standard Algorithm Name Documentation</a>
* for information about standard algorithm names.
*
* @param provider the provider.
*
* @return the new {@code SecretKeyFactory} object.
*
* @exception NullPointerException if the specified algorithm
* is null.
*
* @exception NoSuchAlgorithmException if a SecretKeyFactorySpi
* implementation for the specified algorithm is not available
* from the specified Provider object.
*
* @exception IllegalArgumentException if the {@code provider}
* is null.
*
* @see java.security.Provider
*/
public static final SecretKeyFactory getInstance(String algorithm,
Provider provider) throws NoSuchAlgorithmException {
Instance instance = JceSecurity.getInstance("SecretKeyFactory",
SecretKeyFactorySpi.class, algorithm, provider);
return new SecretKeyFactory((SecretKeyFactorySpi)instance.impl,
instance.provider, algorithm);
}
/**
* Returns the provider of this {@code SecretKeyFactory} object.
*
* @return the provider of this {@code SecretKeyFactory} object
*/
public final Provider getProvider() {
synchronized (lock) {
// disable further failover after this call
serviceIterator = null;
return provider;
}
}
/**
* Returns the algorithm name of this {@code SecretKeyFactory} object.
*
* <p>This is the same name that was specified in one of the
* {@code getInstance} calls that created this
* {@code SecretKeyFactory} object.
*
* @return the algorithm name of this {@code SecretKeyFactory}
* object.
*/
public final String getAlgorithm() {
return this.algorithm;
}
/**
* Update the active spi of this class and return the next
* implementation for failover. If no more implemenations are
* available, this method returns null. However, the active spi of
* this class is never set to null.
*/
private SecretKeyFactorySpi nextSpi(SecretKeyFactorySpi oldSpi) {
synchronized (lock) {
// somebody else did a failover concurrently
// try that spi now
if ((oldSpi != null) && (oldSpi != spi)) {
return spi;
}
if (serviceIterator == null) {
return null;
}
while (serviceIterator.hasNext()) {
Service s = serviceIterator.next();
if (JceSecurity.canUseProvider(s.getProvider()) == false) {
continue;
}
try {
Object obj = s.newInstance(null);
if (obj instanceof SecretKeyFactorySpi == false) {
continue;
}
SecretKeyFactorySpi spi = (SecretKeyFactorySpi)obj;
provider = s.getProvider();
this.spi = spi;
return spi;
} catch (NoSuchAlgorithmException e) {
// ignore
}
}
serviceIterator = null;
return null;
}
}
/**
* Generates a {@code SecretKey} object from the provided key
* specification (key material).
*
* @param keySpec the specification (key material) of the secret key
*
* @return the secret key
*
* @exception InvalidKeySpecException if the given key specification
* is inappropriate for this secret-key factory to produce a secret key.
*/
public final SecretKey generateSecret(KeySpec keySpec)
throws InvalidKeySpecException {
if (serviceIterator == null) {
return spi.engineGenerateSecret(keySpec);
}
Exception failure = null;
SecretKeyFactorySpi mySpi = spi;
do {
try {
return mySpi.engineGenerateSecret(keySpec);
} catch (Exception e) {
if (failure == null) {
failure = e;
}
mySpi = nextSpi(mySpi);
}
} while (mySpi != null);
if (failure instanceof InvalidKeySpecException) {
throw (InvalidKeySpecException)failure;
}
throw new InvalidKeySpecException
("Could not generate secret key", failure);
}
/**
* Returns a specification (key material) of the given key object
* in the requested format.
*
* @param key the key
* @param keySpec the requested format in which the key material shall be
* returned
*
* @return the underlying key specification (key material) in the
* requested format
*
* @exception InvalidKeySpecException if the requested key specification is
* inappropriate for the given key (e.g., the algorithms associated with
* {@code key} and {@code keySpec} do not match, or
* {@code key} references a key on a cryptographic hardware device
* whereas {@code keySpec} is the specification of a software-based
* key), or the given key cannot be dealt with
* (e.g., the given key has an algorithm or format not supported by this
* secret-key factory).
*/
public final KeySpec getKeySpec(SecretKey key, Class<?> keySpec)
throws InvalidKeySpecException {
if (serviceIterator == null) {
return spi.engineGetKeySpec(key, keySpec);
}
Exception failure = null;
SecretKeyFactorySpi mySpi = spi;
do {
try {
return mySpi.engineGetKeySpec(key, keySpec);
} catch (Exception e) {
if (failure == null) {
failure = e;
}
mySpi = nextSpi(mySpi);
}
} while (mySpi != null);
if (failure instanceof InvalidKeySpecException) {
throw (InvalidKeySpecException)failure;
}
throw new InvalidKeySpecException
("Could not get key spec", failure);
}
/**
* Translates a key object, whose provider may be unknown or potentially
* untrusted, into a corresponding key object of this secret-key factory.
*
* @param key the key whose provider is unknown or untrusted
*
* @return the translated key
*
* @exception InvalidKeyException if the given key cannot be processed
* by this secret-key factory.
*/
public final SecretKey translateKey(SecretKey key)
throws InvalidKeyException {
if (serviceIterator == null) {
return spi.engineTranslateKey(key);
}
Exception failure = null;
SecretKeyFactorySpi mySpi = spi;
do {
try {
return mySpi.engineTranslateKey(key);
} catch (Exception e) {
if (failure == null) {
failure = e;
}
mySpi = nextSpi(mySpi);
}
} while (mySpi != null);
if (failure instanceof InvalidKeyException) {
throw (InvalidKeyException)failure;
}
throw new InvalidKeyException
("Could not translate key", failure);
}
}

View File

@@ -0,0 +1,108 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.crypto;
import java.security.*;
import java.security.spec.*;
/**
* This class defines the <i>Service Provider Interface</i> (<b>SPI</b>)
* for the <code>SecretKeyFactory</code> class.
* All the abstract methods in this class must be implemented by each
* cryptographic service provider who wishes to supply the implementation
* of a secret-key factory for a particular algorithm.
*
* <P> A provider should document all the key specifications supported by its
* secret key factory.
* For example, the DES secret-key factory supplied by the "SunJCE" provider
* supports <code>DESKeySpec</code> as a transparent representation of DES
* keys, and that provider's secret-key factory for Triple DES keys supports
* <code>DESedeKeySpec</code> as a transparent representation of Triple DES
* keys.
*
* @author Jan Luehe
*
* @see SecretKey
* @see javax.crypto.spec.DESKeySpec
* @see javax.crypto.spec.DESedeKeySpec
* @since 1.4
*/
public abstract class SecretKeyFactorySpi {
/**
* Generates a <code>SecretKey</code> object from the
* provided key specification (key material).
*
* @param keySpec the specification (key material) of the secret key
*
* @return the secret key
*
* @exception InvalidKeySpecException if the given key specification
* is inappropriate for this secret-key factory to produce a secret key.
*/
protected abstract SecretKey engineGenerateSecret(KeySpec keySpec)
throws InvalidKeySpecException;
/**
* Returns a specification (key material) of the given key
* object in the requested format.
*
* @param key the key
*
* @param keySpec the requested format in which the key material shall be
* returned
*
* @return the underlying key specification (key material) in the
* requested format
*
* @exception InvalidKeySpecException if the requested key specification is
* inappropriate for the given key (e.g., the algorithms associated with
* <code>key</code> and <code>keySpec</code> do not match, or
* <code>key</code> references a key on a cryptographic hardware device
* whereas <code>keySpec</code> is the specification of a software-based
* key), or the given key cannot be dealt with
* (e.g., the given key has an algorithm or format not supported by this
* secret-key factory).
*/
protected abstract KeySpec engineGetKeySpec(SecretKey key, Class<?> keySpec)
throws InvalidKeySpecException;
/**
* Translates a key object, whose provider may be unknown or
* potentially untrusted, into a corresponding key object of this
* secret-key factory.
*
* @param key the key whose provider is unknown or untrusted
*
* @return the translated key
*
* @exception InvalidKeyException if the given key cannot be processed
* by this secret-key factory.
*/
protected abstract SecretKey engineTranslateKey(SecretKey key)
throws InvalidKeyException;
}

View File

@@ -0,0 +1,61 @@
/*
* Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.crypto;
import java.security.GeneralSecurityException;
/**
* This exception is thrown when an output buffer provided by the user
* is too short to hold the operation result.
*
* @author Jan Luehe
*
* @since 1.4
*/
public class ShortBufferException extends GeneralSecurityException {
private static final long serialVersionUID = 8427718640832943747L;
/**
* Constructs a ShortBufferException with no detail
* message. A detail message is a String that describes this
* particular exception.
*/
public ShortBufferException() {
super();
}
/**
* Constructs a ShortBufferException with the specified
* detail message.
*
* @param msg the detail message.
*/
public ShortBufferException(String msg) {
super(msg);
}
}

View File

@@ -0,0 +1,48 @@
/*
* Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.crypto.interfaces;
import javax.crypto.spec.DHParameterSpec;
/**
* The interface to a Diffie-Hellman key.
*
* @author Jan Luehe
*
* @see javax.crypto.spec.DHParameterSpec
* @see DHPublicKey
* @see DHPrivateKey
* @since 1.4
*/
public interface DHKey {
/**
* Returns the key parameters.
*
* @return the key parameters
*/
DHParameterSpec getParams();
}

View File

@@ -0,0 +1,53 @@
/*
* Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.crypto.interfaces;
import java.math.BigInteger;
/**
* The interface to a Diffie-Hellman private key.
*
* @author Jan Luehe
*
* @see DHKey
* @see DHPublicKey
* @since 1.4
*/
public interface DHPrivateKey extends DHKey, java.security.PrivateKey {
/**
* The class fingerprint that is set to indicate serialization
* compatibility since J2SE 1.4.
*/
static final long serialVersionUID = 2211791113380396553L;
/**
* Returns the private value, <code>x</code>.
*
* @return the private value, <code>x</code>
*/
BigInteger getX();
}

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